shell版俄罗斯方块 分类: shell版俄罗斯方块 2015-07-26 19:41 8人阅读 评论(0) 收藏

shell能是命令行解释器,shell脚本是命令的有序结合。在网上看到一位哥们用shell语言写了一个游戏,俄罗斯方块,佩服呀。为了弥补童年的不足,我们一起用shell语言开始编写我们自己的俄罗斯方块吧。
我们先来回顾一下,俄罗斯都有哪些方块吧。
box0=(0  0  0  1  1  0  1  1)
 
box1=(0  2  1  2   2  2  3  2  1  0   1  1  1  2  1  3)
 
box3=(0  1  0  2   1  0   1  1  0  0  1  0  1  1  2  1)
 
box4=(0  1  0  2  1  1  2  1  1  0  1  1  1  2  2  2  0  1  1  1  2   0  2   1  0   0   1  0  1  1  1  2 )
 
box5=(0  1  1  1  2  1  2  2  1  0  1  1  1  2  2  0  0  0  0  1  1  1  2  1   0  2   1  0    1  1   1   2)
 
box6=(0  1  1  1  1  2   2  1  1  0  1  1  1   2   2   1   0  1  1  0  1  1  2  1  0   1  1  0  1   1   1  2 )
从上面我们可以看出,每幅图下面都有一个box = ()东东,这个是什么呢?它是shell中的数组,后面括号里面放的是它的元素,即坐标点.
一起来看看shell中数组的语法吧
Bash中,数组变量的赋值有两种方法:
(1)name=(value1 ... valuen)此时小标从0开始
(2)name[index]=value
下面以一个简单的脚本来说明,脚本内容如下
#!/bin/bash
#定义数组
A=(a   b   c   def)
#把数组按字符串显示输出
echo ${A[@]}或echo ${A[*]}
显示:a  b  c   def
#数组的长度表示${#A[*]}
len=${#A[*]}或者len=${#A[@]}
echo ${#A[*]}
显示: 4
#改变数组元素的值
A[3] ="hello word"
echo ${A[*]}
显示:a  b  c  hello word
#循环输出数组
len=${#A[@]}
for  ((i =  0;i < len;i ++))
do
    echo -n "${A[i]}"
done
________________________________

((  i = 0 ))
while ((  i < len ))
do
    echo "${A[i]}"
    (( i = i + 1))
done
#循环输出数组元素的另一种写法,注意,${A[*]}不能写成$A,$A默认是第一个元素,如果A="a b c ded",就可以写$A
for value in ${A[*]}
do
echo $value
done
现在坐标点有了,那怎样把这些坐标点显示在屏幕上?这里我们要看一下shell中echo的用法
echo的基本语法不在进行讲解,我们来看一些其他的
echo 要变换颜色的时候,要使用-e
格式:echo -e "33[背景颜色;字体颜色m字符串33[0m"
eg:
    echo -e "33[41;36m something here 33[0m"
其中41的位置代表底色,36的位置是代表字的颜色
那些ascii code是对颜色调用的始末
33[;m ... 33[0m
例子:
    让字体变为红色并且不停的闪烁
echo -e "33[31m33[05m请确认是否要停止当前的sequid进程,输入[Y|N]33[0m"
字背景颜色范围:40 -- 49
40:黑      41:深红    42:绿    43:黄    44:蓝    45:紫    46:深绿    47:白色
字颜色:30 -- 39
30:黑     31:红    32:绿    33:黄     34:蓝     35:紫     36:深绿    37:白
ANSI控制码的说明
33[0m  关闭所有属性    33[1m设置高亮度    33[4m下划线     33[y;xH设置光标位置
到这里我们把我们要在屏幕显示的坐标点都显示出来吧:
 
 
效果:
 

到此我们终于可以在屏幕上画出东东了。


前面一节,我们在屏幕上画出了俄罗斯方块,现在我们让它动起来,呵呵,动起来...
思想就是通过改变x,y的坐标,在屏幕的不同地方绘制图形。
方法是通过方向键(A   S   D  W)来改变x,y的坐标。

先来看看shell中的信号处理吧

一、trap捕捉到信号之后,可以有三种反应方式

(1)执行一段程序来处理这一信号

(2)接受信号的默认操作

(3)忽视这一信号

二、trap对上面三种方式提供了三种基本形式

第一种形式的trap命令在shell接受到signal  list清单中数值相同的信号时,将执行双引号中的命令串。

trap 'commands' signal-list

trap "commands" signal-list

为了恢复信号的默认操作,使用第二种形式的trap命令:
trap signal-list

第三种形式的trap命令允许忽视信号
trap ""  signal-list

注意:

(1)对信号11(段违例)不能捕捉,因为shell本身需要捕捉该信号去进行内存的转储

(2)在trap中可以定义对信号0的处理(实际上没有这个信号),shell程序在其终止(如执行exit语句时) 发出该信号

(3)在捕捉到signal-list中指定的信号并执行完相应的命令之后,如果这些命令没有将shell程序终止的话,shell程序将继续执行收到信号时所执行的命令后面的命令

另外,在trap语句中,单引号和双引号是不同的,当shell程序第一次碰到trap语句时,将把commands中的命令扫描一遍。此时若commands是单引号括起来的话,那么shell不会对commands中的变量和命令进行替换,否则commands中的变量和命令将用当时具体的值来替换。

  1. #!/bin/bash
  2. SigA=20
  3. SigS=21
  4. SigD=22
  5. SigW=23
  6. sig=0
  7. function Register_Signal()
  8. {
  9. trap "sig=$SigA;" $SigA
  10. trap "sig=$SigS;" $SigS
  11. trap "sig=$SigD;" $SigD
  12. trap "sig=$SigW;" $SigW
  13. }
  14. function Recive_Signal()
  15. {
  16. Register_Signal
  17. while true
  18. do
  19. sigThis=$sig
  20. case "$sigThis" in
  21. "$SigA")
  22. echo "A"
  23. sig=0
  24. ;;
  25. "$SigS")
  26. echo "S"
  27. sig=0
  28. ;;
  29. "$SigD")
  30. echo "D"
  31. sig=0
  32. ;;
  33. "$SigW")
  34. echo "W"
  35. sig=0
  36. ;;
  37. esac
  38. done
  39. }
  40. function Kill_Signal()
  41. {
  42. local sigThis
  43. while :
  44. do
  45. read -s -n 1 key
  46. case "$key" in
  47. "W"|"w")
  48. kill -$SigW $1
  49. ;;
  50. "S"|"s")
  51. kill -$SigS $1
  52. ;;
  53. "A"|"a")
  54. kill -$SigA $1
  55. ;;
  56. "D"|"d")
  57. kill -$SigD $1
  58. ;;
  59. "Q"|"q")
  60. kill -9 $1
  61. exit
  62. esac
  63. done
  64. }
  65. if [[ "$1" == "--show" ]]
  66. then
  67. Recive_Signal
  68. else
  69. bash $0 --show &
  70. Kill_Signal $!
  71. fi
这段shell脚本的功能是:按下A  S  D  W键会打印出对应的字母,按下 Q键退出
 
上一节我们学了一下shell脚本中信号的用法,这一节我们在屏幕上画出一个方块,并且让它动起来.

box0=(0  0  0  1  1  0  1  1)
现在我们就让box0在我们屏幕的任意地方动起来
实现功能:
A  -> 左移    D->右移     W->向上     S->向下
思路就是通过改变x,y的坐标,在屏幕不同的地方,把box0画出来

  1. #!/bin/bash 

  2. #信号
  3. SigA=20
  4. SigS=21
  5. SigD=22
  6. SigW=23
  7. sig=0

  8. #方块在屏幕上的坐标点
  9. box0=(0 0 0 1 1 0 1 1)

  10. #边缘距离
  11. top=3
  12. left=3

  13. #当前x,y坐标
  14. currentX=15
  15. currentY=2

  16. function Draw_Box()
  17. {
  18.     local i j x y

  19.     if (($== 0))
  20.     then
  21.         for ((= 0;i < 8;i += 2))
  22.         do
  23.             ((= left + 3 * (currentX + ${box0[i]})))
  24.             ((= top + currentY + ${box0[i+1]}))

  25.             echo -"33[${y};${x}H "
  26.         done
  27.     else
  28.         echo -"33[31m33[1m"
  29.         for ((= 0;i < 8;i += 2))
  30.         do
  31.             ((= left + 3 * (currentX + ${box0[i]})))
  32.             ((= top + currentY + ${box0[i+1]}))

  33.             echo -"33[${y};${x}H[*]"
  34.         done
  35.     fi

  36.     echo -"33[0m"
  37. }

  38. function move_left()
  39. {    

  40.     if ((currentX == 0 ))
  41.     then
  42.         return 1;
  43.     fi

  44.     #先清除以前的方块
  45.     Draw_Box 0
  46.     
  47.     #改变x坐标
  48.     (( currentX -- ))
  49.     
  50.     #画出新的方块
  51.     Draw_Box 1

  52.     return 0;
  53. }


  54. function move_right()
  55. {    

  56.     if ((currentX > 20 ))
  57.     then
  58.         return 1;
  59.     fi

  60.     #先清除以前的方块
  61.     Draw_Box 0
  62.     
  63.     #改变x坐标
  64.     (( currentX ++ ))
  65.     
  66.     #画出新的方块
  67.     Draw_Box 1

  68.     return 0;
  69. }


  70. function move_up()
  71. {    

  72.     if ((currentY == 0 ))
  73.     then
  74.         return 1;
  75.     fi

  76.     #先清除以前的方块
  77.     Draw_Box 0
  78.     
  79.     #改变x坐标
  80.     (( currentY -- ))
  81.     
  82.     #画出新的方块
  83.     Draw_Box 1

  84.     return 0;
  85. }


  86. function move_down()
  87. {    

  88.     if ((currenty > 20 ))
  89.     then
  90.         return 1;
  91.     fi

  92.     #先清除以前的方块
  93.     Draw_Box 0
  94.     
  95.     #改变x坐标
  96.     (( currentY ++ ))
  97.     
  98.     #画出新的方块
  99.     Draw_Box 1

  100.     return 0;
  101. }


  102. function Register_Signal()
  103. {
  104.     trap "sig=$SigA;" $SigA
  105.     trap "sig=$SigS;" $SigS
  106.     trap "sig=$SigD;" $SigD
  107.     trap "sig=$SigW;" $SigW
  108. }

  109. function Recive_Signal()
  110. {
  111.     Register_Signal

  112.     Draw_Box 1

  113.     while true
  114.     do
  115.         sigThis=$sig

  116.         case "$sigThis" in
  117.             "$SigA")
  118.                 move_left
  119.                 sig=0
  120.                 ;;

  121.             "$SigS")
  122.                 move_down
  123.                 sig=0
  124.                 ;;

  125.             "$SigD")
  126.                 move_right
  127.                 sig=0
  128.                 ;;

  129.             "$SigW")
  130.                 move_up
  131.                 sig=0
  132.                 ;;
  133.         esac
  134.         
  135.     done
  136. }

  137. function Kill_Signal()
  138. {
  139.     local sigThis

  140.     while :
  141.     do
  142.         read --n 1 key
  143.         
  144.         case "$key" in

  145.             "W"|"w")
  146.                 kill -$SigW $1
  147.                 ;;
  148.             "S"|"s")
  149.                 kill -$SigS $1
  150.                 ;;
  151.             "A"|"a")
  152.                 kill -$SigA $1
  153.                 ;;
  154.             "D"|"d")
  155.                 kill -$SigD $1
  156.                 ;;
  157.             "Q"|"q")
  158.                 kill -9 $1
  159.                 exit
  160.      esac

  161.     done
  162. }

  163. if [[ "$1" == "--show" ]]
  164. then
  165.     Recive_Signal
  166. else
  167.     bash $0 --show &
  168.     Kill_Signal $!
  169. fi
效果图:
 
就到这吧,下一节我们随机产生方块,让后让它改变形状。

现在,我们知道,怎样在屏幕上画方块,怎样让方块移动,今天我们将实现,系统随机产生方块,并且让其动起来,嗯,动起来....
 
现在看看在shell中产生随机数的方法

一、通过时间获得随机数(date)

可以说时间是唯一的,也不会重复的,从这个里面获得同一时间的唯一值。

例子:
    date   +%s
注意:date   空格   +%s

如果用它做随机数,相同一秒的数据是一样的。多线程里面基本不能满足要求了。

date   +%N
这个相当精确了,就算在多cpu,大量循环里面,同一秒里面,也很难出现相同结果,不过不同时间里面还会有大量重复碰撞

date  +%s%N
这个可以说比较完美,加入时间戳,又加上纳秒

接下来我们看怎么获得数据内怎么样获得随机数
 
程序运行的结果:
 
 
二、通过内部系统变量($RANDOM)
其实,linux已经提供有个系统环境变量了,直接就是随机数
echo $RANDOM
通过它,我们可以获得的数据是一个小于或等于5位的整数
学完了随机数,我们让它帮助我们产生随机方块吧。
 
  1. #!/bin/bash 

  2. #七中不同的方块的定义
  3. #通过旋转,每种方块的显示的样式可能有几种
  4. box0=(0 0 0 1 1 0 1 1)
  5. box1=(0 2 1 2 2 2 3 2 1 0 1 1 1 2 1 3)
  6. box2=(0 0 0 1 1 1 1 2 0 1 1 0 1 1 2 0)
  7. box3=(0 1 0 2 1 0 1 1 0 0 1 0 1 1 2 1)
  8. box4=(0 1 0 2 1 1 2 1 1 0 1 1 1 2 2 2 0 1 1 1 2 0 2 1 0 0 1 0 1 1 1 2)
  9. box5=(0 1 1 1 2 1 2 2 1 0 1 1 1 2 2 0 0 0 0 1 1 1 2 1 0 2 1 0 1 1 1 2)
  10. box6=(0 1 1 1 1 2 2 1 1 0 1 1 1 2 2 1 0 1 1 0 1 1 2 1 0 1 1 0 1 1 1 2)

  11. #把所有盒子放在box中
  12. box=(${box0[@]} ${box1[@]} ${box2[@]} ${box3[@]} ${box4[@]} ${box5[@]} ${box6[@]})

  13. #每个盒子在box中的偏移
  14. boxOffset=(0 1 3 5 7 11 15)

  15. #旋转次数
  16. rotateCount=(1 2 2 2 4 4 4)

  17. #颜色数组
  18. colourArry=(31 32 33 34 35 36 37)

  19. #选装类型
  20. rotateType=-1

  21. #盒子标号
  22. boxNum=-1

  23. #新盒子
  24. newBox=()

  25. #边缘距离
  26. top=3
  27. left=3

  28. #当前x,y坐标
  29. currentX=15
  30. currentY=2

  31. function Draw_Box()
  32. {
  33.     local i j x y

  34.     if (($== 0))
  35.     then
  36.         for ((= 0;< 8;+= 2))
  37.         do
  38.             ((= left + 3 * (currentX + ${newBox[i]})))
  39.             ((= top + currentY + ${newBox[i+1]}))

  40.             echo -"33[${y};${x}H "
  41.         done
  42.     else
  43.         echo -"33[${colourArry[$colourNum]}m33[1m"
  44.         for ((= 0;< 8;+= 2))
  45.         do
  46.             ((= left + 3 * (currentX + ${newBox[i]})))
  47.             ((= top + currentY + ${newBox[i+1]}))

  48.             echo -"33[${y};${x}H[*]"
  49.         done
  50.     fi

  51.     echo -"33[0m"
  52. }


  53. function Random_Box()
  54. {
  55.     #随机产生盒子号
  56.     (( boxNum = $RANDOM % 7 ))    
  57.     #随机长生盒子的类型
  58.     ((rotateType = $RANDOM % ${rotateCount[boxNum]}))
  59.     #随机产生颜色
  60.     ((colourNum = $RANDOM % ${#colourArry[*]}))

  61.     #找到所在box中的起始位置
  62.     ((= ${boxOffset[boxNum]} * 8 + rotateType * 8))

  63.     for(( i = 0 ;< 8;++))
  64.     do
  65.         ((newBox[i] = ${box[j+i]}))
  66.     done
  67. }

  68. while :
  69. do
  70.     Random_Box
  71.     Draw_Box 1
  72.     sleep 1
  73.     Draw_Box 0
  74. done
前面我们已经可以随机产生俄罗斯方块了,今天我们让它随键盘而改变

  1. #!/bin/bash 

  2. #七中不同的方块的定义
  3. #通过旋转,每种方块的显示的样式可能有几种
  4. box0=(0 0 0 1 1 0 1 1)
  5. box1=(0 2 1 2 2 2 3 2 1 0 1 1 1 2 1 3)
  6. box2=(0 0 0 1 1 1 1 2 0 1 1 0 1 1 2 0)
  7. box3=(0 1 0 2 1 0 1 1 0 0 1 0 1 1 2 1)
  8. box4=(0 1 0 2 1 1 2 1 1 0 1 1 1 2 2 2 0 1 1 1 2 0 2 1 0 0 1 0 1 1 1 2)
  9. box5=(0 1 1 1 2 1 2 2 1 0 1 1 1 2 2 0 0 0 0 1 1 1 2 1 0 2 1 0 1 1 1 2)
  10. box6=(0 1 1 1 1 2 2 1 1 0 1 1 1 2 2 1 0 1 1 0 1 1 2 1 0 1 1 0 1 1 1 2)

  11. #把所有盒子放在box中
  12. box=(${box0[@]} ${box1[@]} ${box2[@]} ${box3[@]} ${box4[@]} ${box5[@]} ${box6[@]})

  13. #每个盒子在box中的偏移
  14. boxOffset=(0 1 3 5 7 11 15)

  15. #旋转次数
  16. rotateCount=(1 2 2 2 4 4 4)

  17. #颜色数组
  18. colourArry=(31 32 33 34 35 36 37)

  19. #选装类型
  20. rotateType=-1

  21. #盒子标号
  22. boxNum=-1

  23. #新盒子
  24. newBox=()

  25. #边缘距离
  26. top=3
  27. left=3

  28. #当前x,y坐标
  29. currentX=15
  30. currentY=2

  31. #信号
  32. SigA=20
  33. SigS=21
  34. SigD=22
  35. SigW=23
  36. sig=0

  37. #随机产生盒子
  38. function Random_Box()
  39. {
  40.     #随机产生盒子号
  41.     (( boxNum = $RANDOM % 7 ))    
  42.     #随机长生盒子的类型
  43.     ((rotateType = $RANDOM % ${rotateCount[boxNum]}))
  44.     #随机产生颜色
  45.     ((colourNum = $RANDOM % ${#colourArry[*]}))

  46.     #找到所在box中的起始位置
  47.     ((= ${boxOffset[boxNum]} * 8 + rotateType * 8))

  48.     for(( i = 0 ;< 8;++))
  49.     do
  50.         ((newBox[i] = ${box[j+i]}))
  51.     done
  52. }


  53. function Draw_Box()
  54. {
  55.     local i j x y


  56.     if (($== 0))
  57.     then
  58.         for ((= 0;< 8;+= 2))
  59.         do
  60.             ((= left + 3 * (currentX + ${newBox[i]})))
  61.             ((= top + currentY + ${newBox[i+1]}))

  62.             echo -"33[${y};${x}H "
  63.         done
  64.     else
  65.         echo -"33[${colourArry[$colourNum]}m33[1m"
  66.         for ((= 0;< 8;+= 2))
  67.         do
  68.             ((= left + 3 * (currentX + ${newBox[i]})))
  69.             ((= top + currentY + ${newBox[i+1]}))

  70.             echo -"33[${y};${x}H[*]"
  71.         done
  72.     fi

  73.     echo -"33[0m"
  74. }

  75. function move_left()
  76. {    
  77.     local temp

  78.     if (( currentX == 0 ))
  79.     then
  80.         return 1
  81.     fi
  82.     
  83.     #先清除以前的方块
  84.     Draw_Box 0
  85.     
  86.     #改变x坐标
  87.     (( currentX -- ))
  88.     
  89.     #画出新的方块
  90.     Draw_Box 1

  91.     return 0
  92. }


  93. function move_right()
  94. {    

  95.     if ((currentX > 20 ))
  96.     then
  97.         return 1;
  98.     fi

  99.     #先清除以前的方块
  100.     Draw_Box 0
  101.     
  102.     #改变x坐标
  103.     (( currentX ++ ))
  104.     
  105.     #画出新的方块
  106.     Draw_Box 1

  107.     return 0;
  108. }

  109. #记录已经旋转的方块次数
  110. tempCount=0

  111. #按下w键旋转处理
  112. function box_rotate()
  113. {
  114.     local start_post
  115.     
  116.     ((tempCount ++))
  117.     #echo ${rotateCount[boxNum]}
  118.     if ((tempCount >= ${rotateCount[boxNum]}))
  119.     then
  120.         ((tempCount = 0))
  121.     fi

  122.     #每个盒子在box中的始位置
  123.     ((start_post = ${boxOffset[boxNum]} * 8 + tempCount * 8))

  124.     for ((= 0;< 8;++))
  125.     do
  126.         ((newBox[i] = ${box[start_post+i]}))
  127.     done

  128.     return 0
  129. }

  130. function move_rotate()
  131. {    

  132.     if ((currentY == 0 ))
  133.     then
  134.         return 1;
  135.     fi

  136.     #先清除以前的方块
  137.     Draw_Box 0
  138.     
  139.     #改变当前方块的形状
  140.     box_rotate
  141.         
  142.     #画出新的方块
  143.     Draw_Box 1

  144.     return 0;
  145. }


  146. function move_down()
  147. {    

  148.     if ((currenty > 20 ))
  149.     then
  150.         return 1;
  151.     fi

  152.     #先清除以前的方块
  153.     Draw_Box 0
  154.     
  155.     #改变x坐标
  156.     (( currentY ++ ))
  157.     
  158.     #画出新的方块
  159.     Draw_Box 1

  160.     return 0;
  161. }


  162. function Register_Signal()
  163. {
  164.     trap "sig=$SigA;" $SigA
  165.     trap "sig=$SigS;" $SigS
  166.     trap "sig=$SigD;" $SigD
  167.     trap "sig=$SigW;" $SigW
  168. }

  169. function Recive_Signal()
  170. {

  171.     Random_Box
  172.     Draw_Box 1
  173.     Register_Signal

  174.     while true
  175.     do
  176.         sigThis=$sig

  177.         case "$sigThis" in
  178.             "$SigA")
  179.                 move_left
  180.                 sig=0
  181.                 ;;

  182.             "$SigS")
  183.                 move_down
  184.                 sig=0
  185.                 ;;

  186.             "$SigD")
  187.                 move_right
  188.                 sig=0
  189.                 ;;

  190.             "$SigW")
  191.                 move_rotate
  192.                 sig=0
  193.                 ;;
  194.         esac
  195.         
  196.     done
  197. }

  198. function Kill_Signal()
  199. {
  200.     local sigThis

  201.     while :
  202.     do
  203.         read --n 1 key
  204.         
  205.         case "$key" in

  206.             "W"|"w")
  207.                 kill -$SigW $1
  208.                 ;;
  209.             "S"|"s")
  210.                 kill -$SigS $1
  211.                 ;;
  212.             "A"|"a")
  213.                 kill -$SigA $1
  214.                 ;;
  215.             "D"|"d")
  216.                 kill -$SigD $1
  217.                 ;;
  218.             "Q"|"q")
  219.                 kill -9 $1
  220.                 exit
  221.      esac

  222.     done
  223. }

  224. if [[ "$1" == "--show" ]]
  225. then
  226.     Recive_Signal
  227. else
  228.     bash $0 --show &
  229.     Kill_Signal $!
  230. fi
效果图:
 
红色部分是我们今天写的代码,思路是使用随机产生的盒子号确定此盒子在box中的位置,然后从此位置开始,把它的所有造型在屏幕上挨个画出来。
到现在为止,我们可以随机产生俄罗斯方块,并且可以移动和改变,下一节我们在屏幕上画出一个矩阵,让盒子从矩阵的顶部自动下落,到矩阵的底部停止。
 
我们现在屏幕上画出一个矩阵,这个很简单
  1. #!/bin/bash 

  2. clear

  3. #边缘距离
  4. left=10
  5. top=5

  6. #矩阵的长和宽
  7. widthSize=25
  8. hightSize=25

  9. #画出矩阵
  10. function draw_rectangle()
  11. {
  12.     local x y

  13.     echo -"33[32m33[46m33[1m"

  14.     for ((= 0 ;i < widthSize;i ++))
  15.     do
  16.         ((= left + i))
  17.         ((= top + hightSize - 1))
  18.     
  19.         echo -"33[${top};${x}H="
  20.         echo -"33[${y};${x}H="

  21.     done

  22.     for ((= 0 ;i < hightSize;i ++))
  23.     do
  24.         ((= left + widthSize - 1))
  25.         ((= top + i))
  26.     
  27.         echo -"33[${y};${left}H||"
  28.         echo -"33[${y};${x}H||"

  29.     done

  30.     echo -"33[0m"
  31. }

  32. draw_rectangle
效果图:
 
矩阵有了,接下来就是让盒子从矩阵的顶部下落下来到底部停止
  1. #!/bin/bash 

  2. #七中不同的方块的定义
  3. #通过旋转,每种方块的显示的样式可能有几种
  4. box0=(0 0 0 1 1 0 1 1)
  5. box1=(0 2 1 2 2 2 3 2 1 0 1 1 1 2 1 3)
  6. box2=(0 0 0 1 1 1 1 2 0 1 1 0 1 1 2 0)
  7. box3=(0 1 0 2 1 0 1 1 0 0 1 0 1 1 2 1)
  8. box4=(0 1 0 2 1 1 2 1 1 0 1 1 1 2 2 2 0 1 1 1 2 0 2 1 0 0 1 0 1 1 1 2)
  9. box5=(0 1 1 1 2 1 2 2 1 0 1 1 1 2 2 0 0 0 0 1 1 1 2 1 0 2 1 0 1 1 1 2)
  10. box6=(0 1 1 1 1 2 2 1 1 0 1 1 1 2 2 1 0 1 1 0 1 1 2 1 0 1 1 0 1 1 1 2)

  11. #把所有盒子放在box中
  12. box=(${box0[@]} ${box1[@]} ${box2[@]} ${box3[@]} ${box4[@]} ${box5[@]} ${box6[@]})

  13. #每个盒子在box中的偏移
  14. boxOffset=(0 1 3 5 7 11 15)

  15. #旋转次数
  16. rotateCount=(1 2 2 2 4 4 4)

  17. #颜色数组
  18. colourArry=(31 32 33 34 35 36 37)

  19. #选装类型
  20. rotateType=-1

  21. #盒子标号
  22. boxNum=-1

  23. #新盒子
  24. newBox=()

  25. #边缘距离
  26. left=10
  27. top=5

  28. #矩阵的长和宽
  29. widthSize=28
  30. hightSize=26

  31. #确定从矩阵那个地方出来
  32. function ensure_postion()
  33. {
  34.     local sumx=0 i j

  35.     ((minx = ${newBox[0]}))
  36.     ((miny = ${newBox[1]}))
  37.     ((maxy = miny ))
  38.     
  39.     for ((= 2; i < ${#newBox[*]};+= 2))
  40.     do 
  41.         #确定最小的x坐标
  42.         if ((minx > ${newBox[i]}))
  43.         then
  44.             ((minx = ${newBox[i]}))
  45.         fi
  46.         
  47.         #确定最小的y坐标
  48.         if ((miny > ${newBox[i+1]}))
  49.         then
  50.             ((miny = ${newBox[i+1]}))
  51.         fi

  52.         if ((${newBox[i]} == ${newBox[i-2]}))
  53.         then
  54.             continue
  55.         fi
  56.         
  57.         ((sumx ++))

  58.     done

  59.     if ((sumx == 0))
  60.     then
  61.         ((sumx = 1))
  62.     fi
  63.     
  64.     #当前x,y坐标
  65.     ((currentX = left + widthSize / 2 - sumx * 2 - minx))
  66.     ((currentY = top + 1 - miny))    

  67.     return 0
  68. }

  69. #画出矩阵
  70. function draw_rectangle()
  71. {
  72.     local x y

  73.     echo -"33[32m33[46m33[1m"

  74.     for ((= 0 ;i < widthSize;i ++))
  75.     do
  76.         ((= left + i))
  77.         ((= top + hightSize - 1))
  78.     
  79.         echo -"33[${top};${x}H="
  80.         echo -"33[${y};${x}H="

  81.     done

  82.     for ((= 0 ;i < hightSize;i ++))
  83.     do
  84.         ((= left + widthSize - 1))
  85.         ((= top + i))
  86.     
  87.         echo -"33[${y};${left}H||"
  88.         echo -"33[${y};${x}H||"

  89.     done

  90.     echo -"33[0m"
  91. }


  92. #画出方块
  93. function Draw_Box()
  94. {
  95.     local i j x y

  96.     if (($== 0))
  97.     then
  98.         for ((= 0;i < 8;i += 2))
  99.         do
  100.             ((= currentX + 3 * ${newBox[i]}))
  101.             ((= currentY + ${newBox[i+1]}))

  102.             echo -"33[${y};${x}H "
  103.         done
  104.     else
  105.         echo -"33[${colourArry[$colourNum]}m33[1m"
  106.         for ((= 0;i < 8;i += 2))
  107.         do
  108.             ((= currentX + 3 * ${newBox[i]}))
  109.             ((= currentY + ${newBox[i+1]}))

  110.             echo -"33[${y};${x}H[*]"
  111.         done
  112.     fi

  113.     echo -"33[0m"
  114. }

  115. #随机产生方块
  116. function Random_Box()
  117. {
  118.     #随机产生盒子号
  119.     (( boxNum = $RANDOM % 7 ))    
  120.     #随机长生盒子的类型
  121.     ((rotateType = $RANDOM % ${rotateCount[boxNum]}))
  122.     #随机产生颜色
  123.     ((colourNum = $RANDOM % ${#colourArry[*]}))

  124.     #找到所在box中的起始位置
  125.     ((= ${boxOffset[boxNum]} * 8 + rotateType * 8))

  126.     for(( i = 0 ;i < 8;i ++))
  127.     do
  128.         ((newBox[i] = ${box[j+i]}))
  129.     done
  130. }

  131. #判断能否下移
  132. function move_test()
  133. {
  134.     local vary=$1 i
  135.     
  136.     #当前的y坐标加上newBox里面的坐标,其值是否大于28
  137.     for ((= 0;i < ${#newBox[@]}; i += 2))
  138.     do
  139.         if ((vary + ${newBox[i+1]} > 28))
  140.         then
  141.             return 0
  142.         fi
  143.     done

  144.     return 1
  145. }


  146. draw_rectangle
  147. Random_Box
  148. ensure_postion

  149. while :
  150. do
  151.     Draw_Box 1

  152.     sleep 0.1
  153.     Draw_Box 0

  154.     ((currentY ++))

  155.     if move_test currentY
  156.     then
  157.         Draw_Box 1
  158.         sleep 2
  159.         Draw_Box 0
  160.         Random_Box
  161.         ensure_postion
  162.     fi

  163. done

  164. echo
效果图:
下一次,我们实现通过键盘改变方块形状和移动方块,并且实现累加


原文:chengyaogen.blog.chinaunix.net

原文地址:https://www.cnblogs.com/zclzqbx/p/4687042.html