Draw is to draw out the graphical interface keytest is to get the keyboard Tetris is the whole game
tetris.sh
#!/bin/bashapp_name= "${0##*[\\/]}" app_version= "1.0" #颜色定义iSumColor =7# total colors cred=1# red cgreen=2# green cyellow=3# Yellow cblue= 4# Blue cfuchsia=5# Magenta ccyan=6# cyan (bluish green) cwhite=7# White # position and size marginleft=3# border left margin margintop=2# border top margin ((mapleft=marginleft+2)) # Checkerboard Left margin ((maptop= $marginTop + 1) #棋盘上边距mapWidth =10# checkerboard width mapheight=15# Checkerboard Height # color setting cborder= $cGreencScore =$ cfuchsiacscorevalue= $cCyan # Control Signal # game uses two processes, one for receiving input, one for game flow and display interface, #当前者接收到上下左右等按键时 to notify the latter by sending signal to the latter. sigrotate=25# up key sigleft=26sigright=27sigdown=28sigalldown=29# space bar sigexit=30# block definition, 7 Big class 19 styles # The first 8 bits are square coordinates, The Post 2 position is the place where the box just appeared box0_0= (0 0 0 1 1 0 1 1 0 4) box1_0= (0 1 1 1 2 1 3 1 0 3) box1_1= (1 0 1 1 1 2 1 3-1 3) box2_0= (0 0 1 0 1 1 2 1 0 4) box2_1= (0 1 0 2 1 0 1 1 0 3) box3_0= (0 1 1 0 1 1 2 0 0 4) box3_1= (0 0 0 1 1 1 1 2 0 4) box4_0= (0 2 1 0 1 1 1 2 0 3) box4 _1= (0 1 1 1 2 1 2 2 0 3) box4_2= (1 0 1 1 1 2 2 0-1 3) box4_3= (0 0 0 1 1 1 2 1 0 4) box5_0= (0 0 1 0 1 1 1 2 0 3) box5_1= (0 1 0 2 1 1 2 1 0 3) box5_2= (1 0 1 1 1 2 2 2-1 3) box5_3= (0 1 1 1 2 0 2 1 0 4) box6_0= (0 1 1 0 1 1 1 2 0 3) box6_1= (0 1 1 1 1 22 1 0 3) box6_2= (1 0 1 1 1 2 2 1-1 3) box6_3= (0 1 1 0 1 1 2 1 0 4) isumtype=7# block type Total boxstyle= (1 2 2 2 4 4 4) #各种方块旋转后可能的样式数目i scoreeachlevel=50# boost A level required score # run time Data sig=0# received signaliscore=0# score ilevel=0# speed Level boxnext= () #下一个方块iboxNextColor =0# The color of the next block iboxnexttype=0# the next block type iboxnextstyle=0# the next block style boxcur= () #当前方块的位置定义iBoxCurColor =0# The color of the current block iboxcurtype=0# The type of the current block iboxcurstyle=0# the current square's style boxcurx=-1# the current square's x-coordinate position boxcury=-1# the current square's y-coordinate position map= () #棋盘图表 # initializes all background squares to 1, indicating no block for (i = 0 ; I < mapheight * MAPWIDTH; i++)) domap[$i]=-1done# The main function of the process receiving the input functions Runaskeyreceiver () {local Piddisplayer key Akey Sig Cesc sttypiddisplayer=$ 1akey= (0 0 0) cesc= ' echo-ne "\033" ' cspace= ' Echo-ne "\040" ' #保存终端属性. When Read-s reads the terminal key, the terminal's properties are temporarily changed. #如果在read-S program is unfortunately killed, may cause terminal confusion, #需要在程序退出时恢复终端属性. stty= ' stty-g ' #捕捉退出信号trap "myexit;" INT quittrap "myexitnosub;" $sigExit # Hide cursor Echo-ne "\033[?25l" while:d o# read input. Note-S does not echo,-N reads a character immediately returns READ-S-N 1 keyakey[0]=${akey[1]}akey[1]=${akey[2]}akey[2]= $keysig =0# determines what key is entered if [[$key = = $cESC & amp;& ${akey[1]} = = $cESC]]then#esc key Myexitelif [[${akey[0]} = = $cESC && ${akey[1]} = = "["]]thenif [[$key = = "A"]]; Then sig= $sigRotate #< up key >elif [[$key = = "B"]]; Then sig= $sigDown #< down key >elif [[$key = = "D"]]; Then sig= $sigLeft #< left arrow >elif [[$key = = "C"]]; Then sig= $sigRight #< right arrow >fielif [[$key = = "W" | | $key = = "W"]]; Then sig= $sigRotate #w, welif [[$key = = "S" | | $key = = "S"]]; Then sig= $sigDown #s, selif [[$key = = "a" | | $key = = "a"]]; Then sig= $sigLeft #a, aelif [[$key = = "D" | | $key = = "D"]]; Then sig= $sigRight #d, Delif [["[$key]" = = "[]"]; Then sig= $sigAllDown # SPACEBAR elif [[$key = = ' Q ' | | $key = = ' Q ']] #Q, qthenmyexitfiif [[$sig! = 0]]then# Send a message to another process kill-$sig $ Piddisplayerfidone} #退出前的恢复MyExitNoSub () {Local y# restore terminal properties STTY $sTTY ((y = margintop + mapheight + 4) #显示光标echo-E "\033[?25h \033[${y};0h "Exit}myexit () {#通知显示进程需要退出kill-$sigExit $pidDisplayerMyExitNoSub} #处理显示和游戏流程的主函数RunAsDisplayer () { Local sigthisinitdraw# mount a variety of signal processing function trap "sig= $sigRotate;" $sigRotatetrap "sig= $siGleft, "$sigLefttrap" sig= $sigRight, "$sigRighttrap" sig= $sigDown; "$sigDowntrap" sig= $sigAllDown; "$sigAllDowntrap" showexit; "$sigExitwhile:d o# depending on the current speed level ilevel, set the number of times for the corresponding loop for ((i = 0; i < 21-ilevel; i++)) dosleep 0.02sigthis= $sigsig = 0# according to the SIG variable to determine whether to accept the corresponding signal 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; #下落到底fidone #kill-$sigDown $ $BoxDown # drop Line done} #绘制当前方块, pass the first argument, 0 means erase the current block, 1 means draw the current square drawcurbox () { Local I x y bErase sboxberase=$1if ((bErase = = 0)) thensbox= "\040\040" #用两个空格擦除elsesBox = "[]" Echo-ne "\033[1m\033[3${iboxc Urcolor}m\033[4${iboxcurcolor}m "Fifor ((i = 0; i < 8; i + = 2)) do ((y = maptop + 1 + ${boxcur[$i]} + Boxcury)) ((x = MapLe FT + 1 + 2 * (Boxcurx + ${boxcur[$i + 1]})) Echo-ne "\033[${y};${x}h${sbox}" Doneecho-ne "\033[0m"} #移动方块 #boxmove (y, x), test Try to move the block to (y, x) position, return 0, 1 can not BoxmovE () {Local I x y xPos yposypos=$1xpos=$2for ((i = 0; i < 8; i + 2)) do# block relative to checkerboard coordinates ((y = YPos + ${boxcur[$i]})) ((x = XPos + ${boxcur[$i + 1]})) if ((Y < 0 | | y >= mapheight | | x < 0 | | x >= mapwidth)) then# hit the wall, return 1fiif (${map[y * mapwidth + x]} =-1)) then# hit another existing block, return 1fidonereturn 0; #将方块贴到棋盘上Box2Map () {Local i J x y line# the current moving block to the corresponding area for the chessboard for ((i = 0; i < 8; i + 2)) do# calculates the coordinates of the block relative to the chessboard (y = ${boxcur[$i]} + Boxcury)) ((x = ${boxcur[$i + 1]} + Boxcurx)) map[y*mapwidth+x]= $iBoxCurColor # assigns the block color to the map doneline=0for ((i = 0; i < Maphe ight; i++) dofor ((j = 0; J < Mapwidth; J + +)) do# If there is a gap on the board, jump out of the loop [[${map[i*mapwidth+j]}-eq-1]] && breakdone[$j-lt $ Mapwidth] && continue# The current line can be eliminated, can eliminate the number of rows plus one ((line++)) #第i行可被消除, 0 lines to the i-1 row all down one line, starting from the first i-1 line to move for (j = i*mapwidth-1; j >= 0; j--) do ((x = j + mapwidth) map[$x]=${map[$j]}done# because a row is moved down, the No. 0 line is empty for ((i = 0; i < mapwidth; i++)) domap[$i]=-1donedone[$li Ne-eq 0] && return# calculates fractions and speed levels based on the number of rows eliminated (x = MarginLeft + Mapwidth * 2 + 7)) ((y = margintop + one)) ((Iscore + = line * 2-1)) #显示新的分数echo-ne "\033[1m\033[3${cscorevalue}m\033[${y}; ${x}h${iscore} "if ((iscore% Iscoreeachlevel < line * 2-1)) thenif ((Ilevel <) and then ((ilevel++)) ((y = ma Rgintop +)) #显示新的速度级echo-ne "\033[3${cscorevalue}m\033[${y};${x}h${ilevel}" Fifiecho-ne "\033[0m" #重新显示背景方块for ( (i = 0; i < mapheight; i++)) do# the checkerboard's coordinates with respect to the screen ((y = i + maptop + 1)) ((x = mapleft + 1)) Echo-ne "\033[${y};${x}h" for ((j = 0; J < Mapwidth; J + +))-Do ((TMP = i * mapwidth + j)) if ((${map[$tmp]} = =-1)) Thenecho-ne "Elseecho-ne" \033[1m\033[3${map[$tmp]}m\033[4${map[$tmp]}m []\033[0m "Fidonedone} #左移一格BoxLeft () {local x ((x = boxCurX-1)) If Boxmove $boxCurY $xthenDrawCurBox 0 ((Boxcurx = x)) DRAWCU Rbox 1fi} #右移一格BoxRight () {local x ((x = Boxcurx + 1)) if Boxmove $boxCurY $xthenDrawCurBox 0 ((Boxcurx = x)) Drawcurbox 1fi} #向下 Move one grid Boxdown () {Local Y ((y = Boxcury + 1)) #新的y坐标if boxmove $y $boxCurX # Test If you can drop a row thendrawcurbox 0# erase the old block ((Boxcury = y)Drawcurbox # shows the new whereabouts of the rear block else# come here, if you can't fall box2map# the current moving block is pasted into the background box createbox# generate a new block fi} #下落到底BoxAllDown () {Local Y idown# calculates the number of rows that can fall idown=0 ((y = Boxcury + 1)) while Boxmove $y $boxCurXdo ((y++)) ((idown++)) Donedrawcurbox 0# erase the old block (boxc UrY + = Idown)) Drawcurbox # shows the new falling block box2map# the current moving block to the background box createbox# create a new block} #翻转BoxRotate () {[${boxstyle[$ Iboxcurtype]}-eq 1] && return ((Rotatestyle = (iboxcurstyle + 1)% ${boxstyle[$iBoxCurType]}) #将当前方块保存到boxTmpbox tmp= (' eval ' echo ${boxcur[@]} ') boxcur= (' eval ' echo ${box ' $iBoxCurType ' _ ' $rotateStyle ' [@]} ') if Boxmove $boxCurY $box curx# Test if there is space after rotation then# erase the old block boxcur= (' eval ' echo ${boxtmp[@]} ') Drawcurbox 0boxcur= (' eval ' echo ${box ' $iBoxCurType ' _ ' $rotateStyle ' [@]} ') Drawcurbox 1iboxcurstyle= $rotateStyleelse # cannot rotate, or continue to use the old style boxcur= (' eval ' echo ${boxtmp[@]} ' ) fi} #准备下一个方块PrepareNextBox () {Local I x y# clears the right pre-displayed block if (${#boxNext [@]}! = 0)), thenfor ((i = 0; i < 8; i + = 2)) do ((Y = margintop + 1 + ${boxnext[$i]})) ((x = marginleft + 2 * mapwidTh + 7 + 2 * ${boxnext[$i + 1]})) Echo-ne "\033[${y};${x}h\040\040" donefi# randomly generate pre-explicit squares (Iboxnexttype = random% Isumtype) ( (Iboxnextstyle = RANDOM% ${boxstyle[$iBoxNextType]})) ((Iboxnextcolor = RANDOM% $iSumColor + 1)) boxnext= (' eval ' echo ${box ' $iBoxNextType ' _ ' $iBoxNextStyle ' [@]} ') #显示右边预显示的方 Block Echo-ne "\033[1m\033[3${iboxnextcolor}m\033[4${iboxnextcolor}m" for ((i = 0; i < 8; i + = 2)) do ((y = margintop + 1 + ${ boxnext[$i])) ((x = marginleft + 2 * mapwidth + 7 + 2 * ${boxnext[$i + 1]})) Echo-ne "\033[${y};${x}h[" "Doneecho-ne" \033 [0m} #显示新方块CreateBox () {if ((${#boxCur [@]} = = 0); then# current block does not exist ((Iboxcurtype = RANDOM% Isumtype)) ((Iboxcurstyle = RAN DOM% ${boxstyle[$iBoxCurType]}) ((Iboxcurcolor = RANDOM% $iSumColor + 1)) else# the current block already exists and assigns the next block to the current block iboxcurtype= $iBoxN exttype;iboxcurstyle= $iBoxNextStyle; iboxcurcolor= $iBoxNextColorfi # current block array boxcur= (' eval ' echo ${box ' $iBoxCurType ' _ ' $iBoxCurStyle ' [@]} ') #初始化方块起始坐标boxCurY =boxcur[8];boxcurx=boxcur[9];D Rawcurbox # Draw the current square if! BoxmovE $boxCurY $boxCurXthenkill-$sigExit $PPIDShowExitfiPrepareNextBox} #绘制边框DrawBorder () {clearlocal I y x1 x2# display Border Echo-ne "\033[1m\033[3${cborder}m\033[4${cborder}m" ((x1 = marginleft + 1)) #左边框x坐标 ((x2 = x1 + 2 + mapwidth * 2)) #右边框x坐标for ((i = 0; i < mapheight; i++)) do ((y = i + margintop + 2)) Echo-ne "\033[${y};${x1}h| |" #绘制左边框echo-ne "\033[${y};${x2}h| |" #绘制右边框done ((x1 = margintop + mapheight + 2)) for ((i = 0; i < Mapwidth + 2; i++)) do ((y = i * 2 + marginleft + 1)) Echo-n E "\033[${maptop};${y}h==" #绘制上边框echo-ne "\033[${x1};${y}h==" #绘制下边框doneecho-ne "\033[0m" #显示 "score" and "level" the words echo- Ne "\033[1m" ((y = marginleft + mapwidth * 2 + 7)) ((x1 = margintop +)) Echo-ne "\033[3${cscore}m\033[${x1};${y}hscore" (( X1 = margintop + one)) Echo-ne "\033[3${cscorevalue}m\033[${x1};${y}h${iscore}" ((x1 = margintop +) Echo-ne "\033[3${cSc Ore}m\033[${x1};${y}hlevel "((x1 = margintop +)) Echo-ne" \033[3${cscorevalue}m\033[${x1};${y}h${ilevel} "Echo-ne" \ 033[0m "}initdraw () {clear# clear screen drawborder# Draw border Createbox# Create block} #退出时显示GameOVer! Showexit () {Local Y ((y = mapheight + maptop + 3)) echo-e "\033[${y};1hgameover!\033[0m" Exit} #游戏主程序在这儿开始. if [[[] "= ="--ve Rsion "]; Thenecho "$APP _name $APP _version" Elif [["$" = = "--show"]]; then# when a parameter--show is found, run the display function Runasdisplayerelsebash $--show& #以参数--show Run the program again Runaskeyreceiver $!# The process number of the process generated by the above line as the parameter fi
keytest.sh
#!/bin/bashgetkey () {akey= (0 0 0) #定义一个数组来保存3个按键cESC = ' Echo-ne ' \033 ' cspace= ' echo-ne ' \040 ' while:d oread-s-N 1 key
#读取一个字符, read the word characters in key #echo $key #echo XXX akey[0]=${akey[1]} #第一个按键aKey [1]=${akey[2]} #第二个按键aKey [2]= $key # Third key if [[$key = = $cESC && ${akey[1]} = = $cESC]]thenmyexitelif [[${akey[0]} = = $cESC && ${akey[1]} = = " [" ]] thenif [[$key = = "A"]]; then echo keyupelif [[$key = = "B"]]; then echo keydownelif [[$key = = "D"]]; then echo keyleftelif [[$key = = "C"]]; Then Echo Keyrightfifidone}getkey
draw.sh
#!/bin/bash# position and size marginleft=8# border left margin margintop=6# border top margin ((mapleft=marginleft+2)) #棋盘左边距 ((maptop= $marginTop + 1)) # Checkerboard Top margin mapwidth=10# checkerboard width mapheight=15# Checkerboard Height # block definition, 7 categories 19 Styles # The first 8 bits are square coordinates, the last 2 bits is the position of the box when it first appeared box0_0= (0 0 0 1 1 0 1 1 0 4) box1_0= (0 1 1 1 2 1 3 1 0 3) box1_1= (1 0 1 1 1 2 1 3-1 3) box2_0= (0 0 1 0 1 1 2 1 0 4) box2_1= (0 1 0 2 1 0 1 1 0 3) box3_0= (0 1 1 0 1 1 2 0 0 4) box3_1= (0 0 0 1 1 1 1 2 0 4) box4_0= (0 2 1 0 1 1 1 2 0 3) box4_1= (0 1 1 1 2 1 2 2 0 3) box4_2= (1 0 1 1 1 2 2 0-1 3) box4_3= (0 0 0 1 1 1 2 1 0 4) box5_0= (0 0 1 0 1 1 1 2 0 3) box5_1= (0 1 0 2 1 1 2 1 0 3) box5_2= (1 0 1 1 1 2 2 2-1 3) box5_3= (0 1 1 1 2 0 2 1 0 4) box6_0= (0 1 1 0 1 1 1 2 0 3) box6_1= (0 1 1 1 1 2 2 1 0 3) box6_2= (1 0 1 1 1 2 2 1-1 3) box6_3= (0 1 1 0 1 1 2 1 0 4) #绘制边框DrawBorder () {clearlocal I y x1 x2# display border Echo-ne "\033[1m\033[32m\033[42m" ((x1 = marginleft + 1)) #左边框x坐标 ((x2 = x1 + 2 + mapwidth * 2)) #右边框x坐标for ((i = 0; i < mapheight; i++)) do ((y = i + margintop + 2)) Echo-ne "\033[${y};${x1}h| |" #绘制左边框echo-ne "\033[${y};${x2}h| |" #绘制右边框done((x1 = margintop + mapheight + 2)) for ((i = 0; i < Mapwidth + 2; i++))-do ((y = i * 2 + marginleft + 1)) Echo-ne "\033[${ maptop};${y}h== "#绘制上边框echo-ne" \033[${x1};${y}h== "#绘制下边框doneecho-ne" \033[0m "}drawbox () {Local I x y xPos yposypos=${ Box0_0[8]}xpos=${box0_0[9]}echo-ne "\033[1m\033[35m\033[45m" for ((i = 0; i < 8; i + = 2)) does ((y = maptop + 1 + ${box0_0 [$i]} + YPos)) ((x = mapleft + 1 + 2 * (${box0_0[$i + 1]} + XPos))) Echo-ne "\033[${y};${x}h[" Doneecho-ne "\033[0m"}initdraw () {clear# clear screen drawborder# draw Border Drawboxwhile:d Osleep 1done}initdraw
Shell script Implementation Tetris