用Shell实现俄罗斯方块代码(Tetris.sh)

简介:
复制代码
  1 #!/bin/bash
  2  
  3 # Tetris Game
  4 # 10.21.2003 xhchen<[email]xhchen@winbond.com.tw[/email]>
  5  
  6 #APP declaration
  7 APP_NAME="${0##*[\\/]}"
  8 APP_VERSION="1.0"
  9  
 10  
 11 #颜色定义
 12 cRed=1
 13 cGreen=2
 14 cYellow=3
 15 cBlue=4
 16 cFuchsia=5
 17 cCyan=6
 18 cWhite=7
 19 colorTable=($cRed $cGreen $cYellow $cBlue $cFuchsia $cCyan $cWhite)
 20  
 21 #位置和大小
 22 iLeft=3
 23 iTop=2
 24 ((iTrayLeft = iLeft + 2))
 25 ((iTrayTop = iTop + 1))
 26 ((iTrayWidth = 10))
 27 ((iTrayHeight = 15))
 28  
 29 #颜色设置
 30 cBorder=$cGreen
 31 cScore=$cFuchsia
 32 cScoreValue=$cCyan
 33  
 34 #控制信号
 35 #改游戏使用两个进程,一个用于接收输入,一个用于游戏流程和显示界面;
 36 #当前者接收到上下左右等按键时,通过向后者发送signal的方式通知后者。
 37 sigRotate=25
 38 sigLeft=26
 39 sigRight=27
 40 sigDown=28
 41 sigAllDown=29
 42 sigExit=30
 43  
 44 #七中不同的方块的定义
 45 #通过旋转,每种方块的显示的样式可能有几种
 46 box0=(0 0 0 1 1 0 1 1)
 47 box1=(0 2 1 2 2 2 3 2 1 0 1 1 1 2 1 3)
 48 box2=(0 0 0 1 1 1 1 2 0 1 1 0 1 1 2 0)
 49 box3=(0 1 0 2 1 0 1 1 0 0 1 0 1 1 2 1)
 50 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)
 51 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)
 52 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)
 53 #所有其中方块的定义都放到box变量中
 54 box=(${box0[@]} ${box1[@]} ${box2[@]} ${box3[@]} ${box4[@]} ${box5[@]} ${box6[@]})
 55 #各种方块旋转后可能的样式数目
 56 countBox=(1 2 2 2 4 4 4)
 57 #各种方块再box数组中的偏移
 58 offsetBox=(0 1 3 5 7 11 15)
 59  
 60 #每提高一个速度级需要积累的分数
 61 iScoreEachLevel=50        #be greater than 7
 62  
 63 #运行时数据
 64 sig=0                #接收到的signal
 65 iScore=0        #总分
 66 iLevel=0        #速度级
 67 boxNew=()        #新下落的方块的位置定义
 68 cBoxNew=0        #新下落的方块的颜色
 69 iBoxNewType=0        #新下落的方块的种类
 70 iBoxNewRotate=0        #新下落的方块的旋转角度
 71 boxCur=()        #当前方块的位置定义
 72 cBoxCur=0        #当前方块的颜色
 73 iBoxCurType=0        #当前方块的种类
 74 iBoxCurRotate=0        #当前方块的旋转角度
 75 boxCurX=-1        #当前方块的x坐标位置
 76 boxCurY=-1        #当前方块的y坐标位置
 77 iMap=()                #背景方块图表
 78  
 79 #初始化所有背景方块为-1, 表示没有方块
 80 for ((i = 0; i < iTrayHeight * iTrayWidth; i++)); do iMap[$i]=-1; done
 81  
 82  
 83 #接收输入的进程的主函数
 84 function RunAsKeyReceiver()
 85 {
 86         local pidDisplayer key aKey sig cESC sTTY
 87  
 88         pidDisplayer=$1
 89         aKey=(0 0 0)
 90  
 91         cESC=`echo -ne "\033"`
 92         cSpace=`echo -ne "\040"`
 93  
 94         #保存终端属性。在read -s读取终端键时,终端的属性会被暂时改变。
 95         #如果在read -s时程序被不幸杀掉,可能会导致终端混乱,
 96         #需要在程序退出时恢复终端属性。
 97         sTTY=`stty -g`
 98  
 99         #捕捉退出信号
100         trap "MyExit;" INT TERM
101         trap "MyExitNoSub;" $sigExit
102  
103         #隐藏光标
104         echo -ne "\033[?25l"
105  
106  
107         while :
108         do
109                 #读取输入。注-s不回显,-n读到一个字符立即返回
110                 read -s -n 1 key
111  
112                 aKey[0]=${aKey[1]}
113                 aKey[1]=${aKey[2]}
114                 aKey[2]=$key
115                 sig=0
116  
117                 #判断输入了何种键
118                 if [[ $key == $cESC && ${aKey[1]} == $cESC ]]
119                 then
120                         #ESC键
121                         MyExit
122                 elif [[ ${aKey[0]} == $cESC && ${aKey[1]} == "[" ]]
123                 then
124                         if [[ $key == "A" ]]; then sig=$sigRotate        #<向上键>
125                         elif [[ $key == "B" ]]; then sig=$sigDown        #<向下键>
126                         elif [[ $key == "D" ]]; then sig=$sigLeft        #<向左键>
127                         elif [[ $key == "C" ]]; then sig=$sigRight        #<向右键>
128                         fi
129                 elif [[ $key == "W" || $key == "w" ]]; then sig=$sigRotate        #W, w
130                 elif [[ $key == "S" || $key == "s" ]]; then sig=$sigDown        #S, s
131                 elif [[ $key == "A" || $key == "a" ]]; then sig=$sigLeft        #A, a
132                 elif [[ $key == "D" || $key == "d" ]]; then sig=$sigRight        #D, d
133                 elif [[ "[$key]" == "[]" ]]; then sig=$sigAllDown        #空格键
134                 elif [[ $key == "Q" || $key == "q" ]]                        #Q, q
135                 then
136                         MyExit
137                 fi
138  
139                 if [[ $sig != 0 ]]
140                 then
141                         #向另一进程发送消息
142                         kill -$sig $pidDisplayer
143                 fi
144         done
145 }
146  
147 #退出前的恢复
148 function MyExitNoSub()
149 {
150         local y
151  
152         #恢复终端属性
153         stty $sTTY
154         ((y = iTop + iTrayHeight + 4))
155  
156         #显示光标
157         echo -e "\033[?25h\033[${y};0H"
158         exit
159 }
160  
161  
162 function MyExit()
163 {
164         #通知显示进程需要退出
165         kill -$sigExit $pidDisplayer
166  
167         MyExitNoSub
168 }
169  
170  
171 #处理显示和游戏流程的主函数
172 function RunAsDisplayer()
173 {
174         local sigThis
175         InitDraw
176  
177         #挂载各种信号的处理函数
178         trap "sig=$sigRotate;" $sigRotate
179         trap "sig=$sigLeft;" $sigLeft
180         trap "sig=$sigRight;" $sigRight
181         trap "sig=$sigDown;" $sigDown
182         trap "sig=$sigAllDown;" $sigAllDown
183         trap "ShowExit;" $sigExit
184  
185         while :
186         do
187                 #根据当前的速度级iLevel不同,设定相应的循环的次数
188                 for ((i = 0; i < 21 - iLevel; i++))
189                 do
190                         sleep 0.02
191                         sigThis=$sig
192                         sig=0
193  
194                         #根据sig变量判断是否接受到相应的信号
195                         if ((sigThis == sigRotate)); then BoxRotate;        #旋转
196                         elif ((sigThis == sigLeft)); then BoxLeft;        #左移一列
197                         elif ((sigThis == sigRight)); then BoxRight;        #右移一列
198                         elif ((sigThis == sigDown)); then BoxDown;        #下落一行
199                         elif ((sigThis == sigAllDown)); then BoxAllDown;        #下落到底
200                         fi
201                 done
202                 #kill -$sigDown $$
203                 BoxDown        #下落一行
204         done
205 }
206  
207  
208 #BoxMove(y, x), 测试是否可以把移动中的方块移到(x, y)的位置, 返回0则可以, 1不可以
209 function BoxMove()
210 {
211         local j i x y xTest yTest
212         yTest=$1
213         xTest=$2
214         for ((j = 0; j < 8; j += 2))
215         do
216                 ((i = j + 1))
217                 ((y = ${boxCur[$j]} + yTest))
218                 ((x = ${boxCur[$i]} + xTest))
219                 if (( y < 0 || y >= iTrayHeight || x < 0 || x >= iTrayWidth))
220                 then
221                         #撞到墙壁了
222                         return 1
223                 fi
224                 if ((${iMap[y * iTrayWidth + x]} != -1 ))
225                 then
226                         #撞到其他已经存在的方块了
227                         return 1
228                 fi
229         done
230         return 0;
231 }
232  
233  
234 #将当前移动中的方块放到背景方块中去,
235 #并计算新的分数和速度级。(即一次方块落到底部)
236 function Box2Map()
237 {
238         local j i x y xp yp line
239  
240         #将当前移动中的方块放到背景方块中去
241         for ((j = 0; j < 8; j += 2))
242         do
243                 ((i = j + 1))
244                 ((y = ${boxCur[$j]} + boxCurY))
245                 ((x = ${boxCur[$i]} + boxCurX))
246                 ((i = y * iTrayWidth + x))
247                 iMap[$i]=$cBoxCur
248         done
249  
250         #消去可被消去的行
251         line=0
252         for ((j = 0; j < iTrayWidth * iTrayHeight; j += iTrayWidth))
253         do
254                 for ((i = j + iTrayWidth - 1; i >= j; i--))
255                 do
256                         if ((${iMap[$i]} == -1)); then break; fi
相关文章
|
1月前
|
分布式计算 Hadoop Shell
使用shell脚本实现自动SSH互信功能
使用shell脚本实现自动SSH互信功能
29 1
|
2天前
|
Shell
shell脚本
shell脚本
9 2
|
9天前
|
Ubuntu Java Linux
Linux centos7 ubuntu 一键安装Java JDK 脚本 shell 脚本
Linux centos7 ubuntu 一键安装Java JDK 脚本 shell 脚本
|
10天前
|
Ubuntu Shell Linux
linux shell 后台执行脚本的方法 脚本后台运行 后台运行程
linux shell 后台执行脚本的方法 脚本后台运行 后台运行程
|
10天前
|
监控 Shell Linux
shell linux中用shell写一个占用CPU的脚本
shell linux中用shell写一个占用CPU的脚本
|
10天前
|
Shell Linux
shell linux中shell脚本编写俄罗斯方块
shell linux中shell脚本编写俄罗斯方块
|
10天前
|
Shell Linux Perl
Linux shell脚本sed使用
Linux shell脚本sed使用
|
10天前
|
Shell Linux
linux shell 脚本实现:根据文件内容中的每行分隔符放入数组,根据规则打印日志并重新创建目录 备份文件
linux shell 脚本实现:根据文件内容中的每行分隔符放入数组,根据规则打印日志并重新创建目录 备份文件
|
10天前
|
Shell Linux BI
linux shell脚本中 if 条件判断
linux shell脚本中 if 条件判断

热门文章

最新文章