In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-16 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/03 Report--
This article mainly introduces how to use shell script to write Tetris games, the article is very detailed, has a certain reference value, interested friends must read it!
Paste the following code into an empty Shell script file and run it in Bash!
The code is as follows:
#! / bin/bash
# Tetris Game
# 10.21.2003 xhchen
# APP declaration
APP_NAME= "${0,000,500 * [\\ /]}"
APP_VERSION= "1. 0"
# Color definition
CRed=1
CGreen=2
CYellow=3
CBlue=4
CFuchsia=5
CCyan=6
CWhite=7
ColorTable= ($cRed $cGreen $cYellow $cBlue $cFuchsia $cCyan $cWhite)
# location and size
ILeft=3
ITop=2
((iTrayLeft = iLeft + 2))
((iTrayTop = iTop + 1))
((iTrayWidth = 10))
((iTrayHeight = 15))
# Color Settings
CBorder=$cGreen
CScore=$cFuchsia
CScoreValue=$cCyan
# Control signal
# change the game to use two processes, one for receiving input and one for the game flow and display interface
# when the current user receives the up and down keys, notify the latter by sending signal to the latter.
SigRotate=25
SigLeft=26
SigRight=27
SigDown=28
SigAllDown=29
SigExit=30
# definition of different squares in # 7
# by rotation, there may be several styles for the display of each square
Box0= (0 0 1 1 0 1 1)
Box1= (0 2 1 2 2 2 3 2 1 0 1 1 1 2 1 3)
Box2= (0 0 1 1 1 2 0 1 1 0 1 1 2 0)
Box3= (0 1 0 2 1 0 1 0 1 0 1 1 1 2 1)
Box4= (0 1 0 2 1 1 1 0 1 1 1 2 2 2 0 1 1 1 2 0 2 1 0 1 0 1 1 1 12)
Box5= (0 1 1 1 2 1 2 1 0 1 1 1 2 2 2000 0 0 1 1 1 0 2 1 0 1 1 1 12)
Box6= (0 1 1 1 2 2 1 1 0 1 1 1 2 2 1 0 1 1 0 1 1 2 1 0 1 0 1 1 1 12)
# all the definitions of squares are put in the box variable
Box= (${box0 [@]} ${box1 [@]} ${box2 [@]} ${box3 [@]} ${box4 [@]} ${box5 [@]} ${box6 [@]})
# number of possible styles after rotation of various squares
CountBox= (1 2 2 2 4 4 4)
# offset of various squares in the box array
OffsetBox= (0 1 3 5 7 11 15)
# points accumulated for each increase in speed level
IScoreEachLevel=50 # be greater than 7
# Runtime data
Sig=0 # received signal
IScore=0 # Total score
ILevel=0 # speed class
BoxNew= () # the location definition of the newly fallen square
CBoxNew=0 # the color of the newly fallen square
IBoxNewType=0 # types of newly fallen squares
IBoxNewRotate=0 # rotation angle of the newly fallen square
BoxCur= () # the location definition of the current square
CBoxCur=0 # Color of the current square
IBoxCurType=0 # the category of the current square
IBoxCurRotate=0 # rotation angle of the current square
BoxCurX=-1 # the x coordinate position of the current square
BoxCurY=-1 # the y coordinate position of the current square
IMap= () # background square chart
# initialize all background squares as-1, which means there are no squares
For ((I = 0; I)
< iTrayHeight * iTrayWidth; i++)); do iMap[$i]=-1; done #接收输入的进程的主函数 function RunAsKeyReceiver() { local pidDisplayer key aKey sig cESC sTTY pidDisplayer=$1 aKey=(0 0 0) cESC=`echo -ne "\033"` cSpace=`echo -ne "\040"` #保存终端属性。在read -s读取终端键时,终端的属性会被暂时改变。 #如果在read -s时程序被不幸杀掉,可能会导致终端混乱, #需要在程序退出时恢复终端属性。 sTTY=`stty -g` #捕捉退出信号 trap "MyExit;" INT TERM trap "MyExitNoSub;" $sigExit #隐藏光标 echo -ne "\033[?25l" while : do #读取输入。注-s不回显,-n读到一个字符立即返回 read -s -n 1 key aKey[0]=${aKey[1]} aKey[1]=${aKey[2]} aKey[2]=$key sig=0 #判断输入了何种键 if [[ $key == $cESC && ${aKey[1]} == $cESC ]] then #ESC键 MyExit elif [[ ${aKey[0]} == $cESC && ${aKey[1]} == "[" ]] then if [[ $key == "A" ]]; then sig=$sigRotate # elif [[ $key == "B" ]]; then sig=$sigDown # elif [[ $key == "D" ]]; then sig=$sigLeft # elif [[ $key == "C" ]]; then sig=$sigRight # fi elif [[ $key == "W" || $key == "w" ]]; then sig=$sigRotate #W, w elif [[ $key == "S" || $key == "s" ]]; then sig=$sigDown #S, s elif [[ $key == "A" || $key == "a" ]]; then sig=$sigLeft #A, a elif [[ $key == "D" || $key == "d" ]]; then sig=$sigRight #D, d elif [[ "[$key]" == "[]" ]]; then sig=$sigAllDown #空格键 elif [[ $key == "Q" || $key == "q" ]] #Q, q then MyExit fi if [[ $sig != 0 ]] then #向另一进程发送消息 kill -$sig $pidDisplayer fi done } #退出前的恢复 function MyExitNoSub() { local y #恢复终端属性 stty $sTTY ((y = iTop + iTrayHeight + 4)) #显示光标 echo -e "\033[?25h\033[${y};0H" exit } function MyExit() { #通知显示进程需要退出 kill -$sigExit $pidDisplayer MyExitNoSub } #处理显示和游戏流程的主函数 function RunAsDisplayer() { local sigThis InitDraw #挂载各种信号的处理函数 trap "sig=$sigRotate;" $sigRotate trap "sig=$sigLeft;" $sigLeft trap "sig=$sigRight;" $sigRight trap "sig=$sigDown;" $sigDown trap "sig=$sigAllDown;" $sigAllDown trap "ShowExit;" $sigExit while : do #根据当前的速度级iLevel不同,设定相应的循环的次数 for ((i = 0; i < 21 - iLevel; i++)) do sleep 0.02 sigThis=$sig sig=0 #根据sig变量判断是否接受到相应的信号 if ((sigThis == sigRotate)); then BoxRotate; #旋转 elif ((sigThis == sigLeft)); then BoxLeft; #左移一列 elif ((sigThis == sigRight)); then BoxRight; #右移一列 elif ((sigThis == sigDown)); then BoxDown; #下落一行 elif ((sigThis == sigAllDown)); then BoxAllDown; #下落到底 fi done #kill -$sigDown $$ BoxDown #下落一行 done } #BoxMove(y, x), 测试是否可以把移动中的方块移到(x, y)的位置, 返回0则可以, 1不可以 function BoxMove() { local j i x y xTest yTest yTest=$1 xTest=$2 for ((j = 0; j < 8; j += 2)) do ((i = j + 1)) ((y = ${boxCur[$j]} + yTest)) ((x = ${boxCur[$i]} + xTest)) if (( y < 0 || y >= iTrayHeight | | x
< 0 || x >= iTrayWidth))
Then
# hit the wall
Return 1
Fi
If ((${iMap [y * iTrayWidth + x]}! =-1))
Then
# bumped into other existing squares
Return 1
Fi
Done
Return 0
}
# put the currently moving square into the background box
# and calculate the new score and speed level. (that is, once the square falls to the bottom)
Function Box2Map ()
{
Local j i x y xp yp line
# put the currently moving square into the background box
For ((j = 0; j)
< 8; j += 2)) do ((i = j + 1)) ((y = ${boxCur[$j]} + boxCurY)) ((x = ${boxCur[$i]} + boxCurX)) ((i = y * iTrayWidth + x)) iMap[$i]=$cBoxCur done #消去可被消去的行 line=0 for ((j = 0; j < iTrayWidth * iTrayHeight; j += iTrayWidth)) do for ((i = j + iTrayWidth - 1; i >= j; iMurt -))
Do
If ((${iMap [$I]} =-1)); then break; fi
Done
If ((I > = j)); then continue; fi
((line++))
For ((I = j-1; I > = 0; iMel -))
Do
((X = I + iTrayWidth))
IMap [$x] = ${iMap [$I]}
Done
For ((I = 0; I)
< iTrayWidth; i++)) do iMap[$i]=-1 done done if ((line == 0)); then return; fi #根据消去的行数line计算分数和速度级 ((x = iLeft + iTrayWidth * 2 + 7)) ((y = iTop + 11)) ((iScore += line * 2 - 1)) #显示新的分数 echo -ne "\033[1m\033[3${cScoreValue}m\033[${y};${x}H${iScore} " if ((iScore % iScoreEachLevel < line * 2 - 1)) then if ((iLevel < 20)) then ((iLevel++)) ((y = iTop + 14)) #显示新的速度级 echo -ne "\033[3${cScoreValue}m\033[${y};${x}H${iLevel} " fi fi echo -ne "\033[0m" #重新显示背景方块 for ((y = 0; y < iTrayHeight; y++)) do ((yp = y + iTrayTop + 1)) ((xp = iTrayLeft + 1)) ((i = y * iTrayWidth)) echo -ne "\033[${yp};${xp}H" for ((x = 0; x < iTrayWidth; x++)) do ((j = i + x)) if ((${iMap[$j]} == -1)) then echo -ne " " else echo -ne "\033[1m\033[7m\033[3${iMap[$j]}m\033[4${iMap[$j]}m[]\033[0m" fi done done } #下落一行 function BoxDown() { local y s ((y = boxCurY + 1)) #新的y坐标 if BoxMove $y $boxCurX #测试是否可以下落一行 then s="`DrawCurBox 0`" #将旧的方块抹去 ((boxCurY = y)) s="$s`DrawCurBox 1`" #显示新的下落后方块 echo -ne $s else #走到这儿, 如果不能下落了 Box2Map #将当前移动中的方块贴到背景方块中 RandomBox #产生新的方块 fi } #左移一列 function BoxLeft() { local x s ((x = boxCurX - 1)) if BoxMove $boxCurY $x then s=`DrawCurBox 0` ((boxCurX = x)) s=$s`DrawCurBox 1` echo -ne $s fi } #右移一列 function BoxRight() { local x s ((x = boxCurX + 1)) if BoxMove $boxCurY $x then s=`DrawCurBox 0` ((boxCurX = x)) s=$s`DrawCurBox 1` echo -ne $s fi } #下落到底 function BoxAllDown() { local k j i x y iDown s iDown=$iTrayHeight #计算一共需要下落多少行 for ((j = 0; j < 8; j += 2)) do ((i = j + 1)) ((y = ${boxCur[$j]} + boxCurY)) ((x = ${boxCur[$i]} + boxCurX)) for ((k = y + 1; k < iTrayHeight; k++)) do ((i = k * iTrayWidth + x)) if (( ${iMap[$i]} != -1)); then break; fi done ((k -= y + 1)) if (( $iDown >$k)); then iDown=$k; fi
Done
S = `DrawCurBox 0` # erase the old square
((boxCurY + = iDown))
Slots $s`DrawCurBox 1` # shows the square after the new drop
Echo-ne $s
Box2Map # pastes the currently moving square to the background square
RandomBox # generates new squares
}
# rotate the square
Function BoxRotate ()
{
Local iCount iTestRotate boxTest j i s
ICount=$ {countBox [$iBoxCurType]} # the number of styles that the current square can be rotated to produce
# calculate the new style after rotation
((iTestRotate = iBoxCurRotate + 1))
If ((iTestRotate > = iCount))
Then
((iTestRotate = 0))
Fi
# Update to the new style and save the old style (but not shown)
For ((j = 0, I = (${offsetBox [$iBoxCurType]} + $iTestRotate) * 8; j
< 8; j++, i++)) do boxTest[$j]=${boxCur[$j]} boxCur[$j]=${box[$i]} done if BoxMove $boxCurY $boxCurX #测试旋转后是否有空间放的下 then #抹去旧的方块 for ((j = 0; j < 8; j++)) do boxCur[$j]=${boxTest[$j]} done s=`DrawCurBox 0` #画上新的方块 for ((j = 0, i = (${offsetBox[$iBoxCurType]} + $iTestRotate) * 8; j < 8; j++, i++)) do boxCur[$j]=${box[$i]} done s=$s`DrawCurBox 1` echo -ne $s iBoxCurRotate=$iTestRotate else #不能旋转,还是继续使用老的样式 for ((j = 0; j < 8; j++)) do boxCur[$j]=${boxTest[$j]} done fi } #DrawCurBox(bDraw), 绘制当前移动中的方块, bDraw为1, 画上, bDraw为0, 抹去方块。 function DrawCurBox() { local i j t bDraw sBox s bDraw=$1 s="" if (( bDraw == 0 )) then sBox="\040\040" else sBox="[]" s=$s"\033[1m\033[7m\033[3${cBoxCur}m\033[4${cBoxCur}m" fi for ((j = 0; j < 8; j += 2)) do ((i = iTrayTop + 1 + ${boxCur[$j]} + boxCurY)) ((t = iTrayLeft + 1 + 2 * (boxCurX + ${boxCur[$j + 1]}))) #\033[y;xH, 光标到(x, y)处 s=$s"\033[${i};${t}H${sBox}" done s=$s"\033[0m" echo -n $s } #更新新的方块 function RandomBox() { local i j t #更新当前移动的方块 iBoxCurType=${iBoxNewType} iBoxCurRotate=${iBoxNewRotate} cBoxCur=${cBoxNew} for ((j = 0; j < ${#boxNew[@]}; j++)) do boxCur[$j]=${boxNew[$j]} done #显示当前移动的方块 if (( ${#boxCur[@]} == 8 )) then #计算当前方块该从顶端哪一行"冒"出来 for ((j = 0, t = 4; j < 8; j += 2)) do if ((${boxCur[$j]} < t)); then t=${boxCur[$j]}; fi done ((boxCurY = -t)) for ((j = 1, i = -4, t = 20; j < 8; j += 2)) do if ((${boxCur[$j]} >I)); then iTunes ${boxCur [$j]}; fi
If ((${boxCur [$j]} < t)); then tasking ${boxCur [$j]}; fi
Done
((boxCurX = (iTrayWidth-1-I-t) / 2))
# display the currently moved square
Echo-ne `DrawCurBox 1`
# if there is no place to put the square as soon as it comes out, Game over!
If! BoxMove $boxCurY $boxCurX
Then
Kill-$sigExit ${PPID}
ShowExit
Fi
Fi
# clear the pre-displayed square on the right
For ((j = 0; j < 4; jacks +))
Do
((I = iTop + 1 + j))
((t = iLeft + 2 * iTrayWidth + 7))
Echo-ne "\ 033 [${I}; ${t} H"
Done
# randomly generate new squares
((iBoxNewType = RANDOM% ${# offsetBox [@]}))
((iBoxNewRotate = RANDOM% ${countBox [$iBoxNewType]}))
For ((j = 0, I = (${offsetBox [$iBoxNewType]} + $iBoxNewRotate) * 8; j < 8; jacks, iTunes +)
Do
BoxNew [$j] = ${box [$I]}
Done
((cBoxNew = ${colorTable [RANDOM% ${# colorTable [@]}]}))
# display the pre-displayed square on the right
Echo-ne "\ 033 [1m\ 033 [7m\ 033 [3 ${cBoxNew} m\ 033 [4 ${cBoxNew} m"
For ((j = 0; j < 8; j + = 2))
Do
((I = iTop + 1 + ${boxNew [$j]}))
((t = iLeft + 2 * iTrayWidth + 7 + 2 * ${boxNew [$j + 1]}))
Echo-ne "\ 033 [${I}; ${t} H []"
Done
Echo-ne "\ 033 [0m"
}
# initial drawing
Function InitDraw ()
{
Clear
RandomBox # randomly generates squares, and the square in the right preview window is faster.
RandomBox # randomly generates squares, the squares in the right pre-display window are updated, and the original squares will begin to fall
Local i t1 t2 t3
# display border
Echo-ne "\ 033 [1m"
Echo-ne "\ 033 [3 ${cBorder} m\ 033 [4 ${cBorder} m"
((T2 = iLeft + 1))
(T3 = iLeft + iTrayWidth * 2 + 3))
For ((I = 0; I < iTrayHeight; iTunes +))
Do
(T1 = I + iTop + 2))
Echo-ne "\ 033 [${T1}; ${T2} H | |"
Echo-ne "\ 033 [${T1}; ${T3} H | |"
Done
((T2 = iTop + iTrayHeight + 2))
For ((I = 0; I < iTrayWidth + 2; iTunes +))
Do
(T1 = I * 2 + iLeft + 1))
Echo-ne "\ 033 [${iTrayTop}; ${T1} hinge ="
Echo-ne "\ 033 [${T2}; ${T1} hinge ="
Done
Echo-ne "\ 033 [0m"
# display the words "Score" and "Level"
Echo-ne "\ 033 [1m"
(T1 = iLeft + iTrayWidth * 2 + 7))
(T2 = iTop + 10))
Echo-ne "\ 033 [3 ${cScore} m\ 033 [${T2}; ${T1} HScore"
(T2 = iTop + 11))
Echo-ne "\ 033 [3 ${cScoreValue} m\ 033 [${T2}; ${T1} H$ {iScore}"
(T2 = iTop + 13)
Echo-ne "\ 033 [3 ${cScore} m\ 033 [${T2}; ${T1} HLevel"
(T2 = iTop + 14)
Echo-ne "\ 033 [3 ${cScoreValue} m\ 033 [${T2}; ${T1} H$ {iLevel}"
Echo-ne "\ 033 [0m"
}
# display GameOVer when exiting!
Function ShowExit ()
{
Local y
((y = iTrayHeight + iTrayTop + 3))
Echo-e "\ 033 [${y}; 0HGameOver!\ 033 [0m"
Exit
}
# display usage.
Function Usage
{
Cat
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.