Create a shell script for the Tetris game

Source: Internet
Author: User

The following script is powerful, make by xhchen, and add it to favorites.

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917 0171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303 3043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364 3743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957 0571572573574575576577578579580581582583584585586587588 #! /Bin/bash # Tetris Game #10.21.2003 xhchen & amp; lt; [email] xhchen@winbond.com.tw [/email] & amp; gt; # APP declarationAPP_NAME = & quot; ${0 # * [/]} & quot; APP_VERSION = & quot; 1.0 & quot; # color definition cRed = 1 cGreen = 2 cYellow = 3 cBlue = 4 cFuchsia = 5 cCyan = 6 cWhite = 7 colorTable = ($ cRed $ cGreen $ cYellow $ cBlue $ cFuchsia $ cCyan $ cWhite) # position and size iLeft = 3 iTop = 2 (iTrayLeft = iLeft + 2) (iTrayTop = iTop + 1) (iTrayWidth = 10 )) (iTrayHeight = 15 ))# Color settings cBorder = $ cGreencScore = $ cFuchsiacScoreValue = $ cCyan # control signal # change the game to use two processes, one for receiving input and the other for the game process and display interface; # When the former receives buttons such as upper, lower, and left buttons, it sends a signal notification to the latter. SigRotate = 25 sigLeft = 26 sigRight = 27 sigDown = 28 sigAllDown = 29 sigExit = 30 # definitions of different squares in seven # by rotation, there may be several kinds of box0 = (0 0 0 1 1 0 1) box1 = (0 2 1 2 2 2 2 2 1 1 1 1 1 2 1 3) box2 = (0 0 0 1 1 1 1 1 2 0 1 1 1 1 1 1 2 0) box3 = (0 1 0 2 1 0 1 1 0 1 0 1 1 1 2 1) box4 = (0 1 0 2 1 1 1 1 1 1 1 1 1 2 2 2 2 0 1 1 2 0 2 1 0 1 0 1 1 1 1 1 2) box5 = (0 1 1 1 1 2 2 2 1 1 1 1 1 2 2 0 0 0 0 1 1 1 2 1 0 2 1 1 1 1 2) box6 = (0 1 1 1 1 2 2 1 1 0 1 1 1 2 2 1 0 1 1 1 1 1 2 1 0 1 1 1 1 2) # Put all the definitions of squares 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 offsetBox = (0 1 3 5 7 11 15) in the box array of various squares) # The score iScoreEachLevel = 50 # be greater than 7 # runtime data sig = 0 # received signaliScore = 0 # Total iLevel = 0 # speed level boxNew = () # cBoxNew = 0 # iBoxNewType = 0 # iBoxNewRotate = 0 # BoxCur = () # define the position of the current square cBoxCur = 0 # the color of the current square iBoxCurType = 0 # the type of the current square iBoxCurRotate = 0 # The Rotation Angle of the current square boxCurX =-1 # The x of the current square coordinate Position boxCurY =-1 # y coordinate position of the current square iMap = () # # Initialize all the background blocks as-1, indicating that there is no square for (I = 0; I & amp; lt; iTrayHeight * iTrayWidth; I ++ )); doiMap [$ I] =-1; done # Main Function functionRunAsKeyReceiver () {localpidDisplayer key aKey sig cESC sTTYpidDisplayer = $1 aKey = (0 0 0) cESC = 'echo-ne & quot; & #92; & #48; 33 & quot; 'cspace = 'echo -Ne & quot; & #92; & #48; 40 & quot; '# Save terminal properties. When read-s reads the terminal key, the properties of the terminal are temporarily changed. # If the program is killed unfortunately during read-s, terminal confusion may occur. # restore terminal attributes when the program exits. STTY = 'stty-G' # capture exit signal trap & quot; MyExit; & quot; INT TERMtrap & quot; MyExitNoSub; & quot; $ sigExit # Hide the cursor echo-ne & quot; & #92; & #48; 33 [? 25l & quot; while: do # reads the input. Note-s does not show back, -n returns read-s-n 1 keyaKey [0] =$ {aKey [1]} aKey [1] =$ {aKey [2]} aKey [2] = $ keysig = 0 # determine the Input key if [[$ key = $ cESC & amp; amp; & amp; $ {aKey [1] }=ccesc] then # ESC key MyExitelif [[$ {aKey [0] }== $ cESC & amp; amp; $ {aKey [1] }=& quot; [& quot;] thenif [[$ key ==& quot; A & quot;]; thensig = $ sigRotate # & amp; lt; up key & amp; gt; elif [[$ key = & quot; B & quot;]; thensig = $ sigDown # & amp; lt; down key & amp; gt; elif [[$ key = & Quot; D & quot;]; thensig = $ sigLeft # & amp; lt; left arrow & amp; gt; elif [[$ key = & quot; C & quot;]; thensig = $ sigRight # & amp; lt; right-click & amp; gt; fielif [[$ key = & quot; W & quot; | $ key ==& quot; w & quot;]; thensig = $ sigRotate # W, welif [[$ key ===& quot; S & quot; | $ key ==& quot; s & quot;]; thensig = $ sigDown # S, selif [[$ key ==& quot; A & quot; | $ key ==& quot; a & quot;]; thensig = $ sigLeft # A, aelif [[$ key ==& quot; D & quot; | $ key = & Quot; d & quot;]; thensig = $ sigRight # D, delif [[& quot; [$ key] & quot ;== & quot; [] & quot;]; thensig = $ sigAllDown # Space key elif [[$ key = & quot; Q & quot; | $ key = & quot; q & quot;] # Q, qthenMyExitfiif [[$ sig! = 0] then # send the message kill-$ sig $ pidDisplayerfidone} to another process # restore functionMyExitNoSub () before exiting () {localy # restore terminal attributes stty $ sTTY (y = iTop + iTrayHeight + 4) # display the cursor echo-e & quot; & #92; & #48; 33 [? 25 h & #92; & #48; 33 [$ {y}; 0 H & quot; exit} functionMyExit () {# The Notification display process needs to exit kill-$ sigExit $ pidDisplayerMyExitNoSub} # Main Function functionRunAsDisplayer () {localsigThisInitDraw # handler trap for mounting various signals; sig = $ sigRotate; & quot; $ sigRotatetrap & quot; sig = $ sigLeft; & quot; $ sigLefttrap & quot; sig = $ sigRight; & quot; $ sigRighttrap & quot; sig = $ sigDown; & quot; $ sigDowntrap & quot; sig = $ sigAllDown; & quot; $ sigAllDowntrap & quot; ShowExit; & quot; $ SigExitwhile: do # set the number of cycles for (I = 0; I & amp; lt; 21-iLevel; I ++) based on the current iLevel of speed )) dosleep0.02sigThis = $ sigsig = 0 # determine whether to receive the corresponding signal if (sigThis = sigRotate) based on the sig variable); thenBoxRotate; # rotating elif (sigThis = sigLeft); thenBoxLeft; # moving the left column of elif (sigThis = sigRight); thenBoxRight; # shift a column to the right of elif (sigThis = sigDown); thenBoxDown; # Drop a row of elif (sigThis = sigAllDown); thenBoxAllDown; # Drop to the end of fidone # kill-$ sigDown $ BoxDown # Drop a row of done} # BoxMove (y, x) to test whether to move the square in the movement to the position (x, y). If 0 is returned, yes. 1 cannot functionBoxMove () {localj I x y xTest yTestyTest = $1 xTest = $ 2for (j = 0; j & amp; lt; 8; j ++ = 2 )) do (I = j + 1) (y =$ {boxCur [$ j]} + yTest )) (x =$ {boxCur [$ I]} + xTest) if (y & amp; lt; 0 | y & amp; gt; = iTrayHeight | x & amp; lt; 0 | x & amp; gt; = iTrayWidth )) then # Hit the wall with return1fiif ($ {iMap [y * iTrayWidth + x]}! =-1) then # hits another existing square and return1fidonereturn0;} # places the currently moving square in the background square. # calculates the new score and speed level. (That is, once the square falls to the bottom) functionBox2Map () {localj I x y xp yp line # Put the square in the current movement in the background square for (j = 0; j & amp; lt; 8; j + = 2) do (I = j + 1) (y =$ {boxCur [$ j]} + boxCurY )) (x =$ {boxCur [$ I]} + boxCurX) (I = y * iTrayWidth + x )) iMap [$ I] = $ cBoxCurdone # Delete the line that can be deleted = 0for (j = 0; j & amp; lt; iTrayWidth * iTrayHeight; j + = iTrayWidth )) dofor (I = j + iTrayWidth-1; I & amp; gt; = j; I --)) doif ($ {iMap [$ I] }=- 1); thenbreak; fidon Eif (I & amp; gt; = j); thencontinue; fi (line ++) for (I = j-1; I & amp; gt; = 0; I --) do (x = I + iTrayWidth) iMap [$ x] =$ {iMap [$ I]} donefor (I = 0; I & amp; lt; iTrayWidth; I ++) doiMap [$ I] =-1 donedoneif (line = 0); thenreturn; fi # Calculate the score and speed level based on the line of the deleted rows (x = iLeft + iTrayWidth * 2 + 7) (y = iTop + 11 )) (iScore + = line * 2-1) # display the new score echo-ne & quot; & #92; & #48; 33 [1 m & #92; & #48; 33 [3 $ {cScoreValue} m & #92; & #48; 33 [$ {y}; $ {X} H $ {iScore} & quot; if (iScore % iScoreEachLevel & amp; lt; line * 2-1) thenif (iLevel & amp; lt; 20) then (iLevel ++) (y = iTop + 14) # display the new speed echo-ne & quot; & #92; & #48; 33 [3 $ {cScoreValue} m & #92; & #48; 33 [$ {y}; $ {x} H $ {iLevel} & quot; incluiecho-ne & quot; & #92; & #48; 33 [0 m & quot; # re-display the background square for (y = 0; y & amp; lt; iTrayHeight; y ++) do (yp = y + iTrayTop + 1) (xp = iTrayLeft + 1) (I = y * iTrayWidth )) echo-ne & quot; & #92 ;& #48; 33 [$ {yp}; $ {xp} H & quot; for (x = 0; x & amp; lt; iTrayWidth; x ++ )) do (j = I + x) if ($ {iMap [$ j] }==-1) thenecho-ne & quot; elseecho-ne & quot; & #92; & #48; 33 [1 m & #92; & #48; 33 [7 m & #92; & #48; 33 [3 $ {iMap [$ j]} m & #92; & #48; 33 [4 $ {iMap [$ j]} m [] & #92; & #48; 33 [0 m & quot; fidonedone} # Drop a row functionBoxDown () {localy s (y = boxCurY + 1 )) # New y coordinate ifBoxMove $ y $ boxCurX # test whether a row can be dropped by thens = & quot; 'drawcurbox 0' & quot; # erase the old square (boxCurY = Y) s = & quot; $ s 'drawcurbox 1' & quot; # display the new lower-left box echo-ne $ selse # Go here, if Box2Map cannot be dropped # paste the box in the current movement to the background box, RandomBox # generate a new box fi} # Move the left column to functionBoxLeft () {localx s (x = boxCurX-1) ifBoxMove $ boxCurY $ xthens = 'drawcurbox 0' (boxCurX = x )) s = $ s 'drawcurbox 1' echo-ne $ sfi} # Right Shift a column functionBoxRight () {localx s (x = boxCurX + 1 )) ifBoxMove $ boxCurY $ xthens = 'drawcurbox 0' (boxCurX = x) s = $ s' DrawCurBox 1 'echo-ne $ sfi} # Fall to functionB OxAllDown () {localk j I x y iDown siDown = $ iTrayHeight # calculate the total number of rows to be dropped for (j = 0; j & amp; lt; 8; j + = 2) do (I = j + 1) (y =$ {boxCur [$ j]} + boxCurY )) (x =$ {boxCur [$ I]} + boxCurX) for (k = y + 1; k & amp; lt; iTrayHeight; k ++ )) do (I = k * iTrayWidth + x) if ($ {iMap [$ I]}! =-1); thenbreak; fidone (k-= y + 1) if ($ iDown & amp; gt; $ k); theniDown = $ k; fidones = 'drawcurbox 0' # erase the old square (boxCurY + = iDown )) s = $ s 'drawcurbox 1' # display the new backward box echo-ne $ sBox2Map # paste the square in the current movement to the background box RandomBox # generate a new box} # rotate box functionBoxRotate () {localiCount iTestRotate boxTest j I siCount =$ {countBox [$ iBoxCurType]} # Number of styles generated by rotation of the current square # Calculate the new style after rotation (iTestRotate = iBoxCurRotate + 1 )) if (iTestRotate & amp; gt; = iCount) th En (iTestRotate = 0) fi # update to a new style and save the old style (but not displayed) for (j = 0, I = ($ {offsetBox [$ iBoxCurType]} + $ iTestRotate) * 8; j & amp; lt; 8; j ++, I ++ )) doboxTest [$ j] =$ {boxCur [$ j]} boxCur [$ j] =$ {box [$ I]} doneifBoxMove $ boxCurY $ boxCurX # test whether there is space after rotation put down then # erase the old square for (j = 0; j & amp; lt; 8; j ++ )) doboxCur [$ j] =$ {boxTest [$ j]} dones = 'drawcurbox 0' # draw a new square for (j = 0, I = ($ {offsetBox [$ iBoxCurType]} + $ iTestRotate) * 8; j & amp; lt; 8; J ++, I ++ )) doboxCur [$ j] =$ {box [$ I]} dones = $ s 'drawcurbox 1' echo-ne $ siBoxCurRotate = $ iTestRotateelse # It cannot be rotated, continue to use the old style for (j = 0; j & amp; lt; 8; j ++ )) doboxCur [$ j] =$ {boxTest [$ j]} donefi} # DrawCurBox (bDraw), draw the square in the current movement, set bDraw to 1, draw, and bDraw to 0, erase the square. FunctionDrawCurBox () {locali j t bDraw sBox sbDraw = $1 s = & quot; if (bDraw = 0) thensBox = & quot; & #92; & #48; 40 & #92; & #48; 40 & quot; elsesBox = & quot; [] & quot; s = $ s & quot; & #92; & #48; 33 [1 m & #92; & #48; 33 [7 m & #92; & #48; 33 [3 $ {cBoxCur} m & #92; & #48; 33 [4 $ {cBoxCur} m & quot; primary or (j = 0; j & amp; lt; 8; j ++ = 2 )) do (I = iTrayTop + 1 + $ {boxCur [$ j]} + boxCurY )) (t = iTrayLeft + 1 + 2 * (boxCurX + $ {boxCur [$ j + 1]}) # & #92; & #48; 3 3 [y; xH, cursor to (x, y) s =$ s & quot; & #92; & #48; 33 [$ {I }; $ {t} H $ {sBox} & quot; dones = $ s & quot; & #92; & #48; 33 [0 m & quot; echo-n $ s} # update the new box functionRandomBox () {locali j t # update the currently moved box iBoxCurType =$ {iBoxNewType} iBoxCurRotate =$ {iBoxNewRotate} cBoxCur =$ {cBoxNew} for (j = 0; j & amp; lt ;$ {# boxNew [@]}; j ++ )) doboxCur [$ j] =$ {boxNew [$ j]} done # display the currently moved box if ($ {# boxCur [@] }== 8 )) then # calculates the top row of the current square & quot; for (j = 0, t = 4; j & amp; lt; 8; j + = 2) doif ($ {boxCur [$ j]} & amp; lt; t); thent =$ {boxCur [$ j]}; fidone (boxCurY =-t) for (j = 1, I =-4, t = 20; j & amp; lt; 8; j + = 2 )) doif ($ {boxCur [$ j]} & amp; gt; I); theni =$ {boxCur [$ j]}; fiif ($ {boxCur [$ j]} & amp; lt; t); thent =ent {boxCur [$ j]}; fidone (boxCurX = (iTrayWidth-1-I-t)/2 )) # display the currently moved square echo-ne 'drawcurbox 1' # If the square is displayed, it will not be placed. Game over! If! BoxMove $ boxCurY $ boxCurXthenkill-$ sigExit $ {PPID} ShowExitfifi # Clear the pre-displayed block on the right for (j = 0; j & amp; lt; 4; j ++ )) do (I = iTop + 1 + j) (t = iLeft + 2 * iTrayWidth + 7) echo-ne & quot; & #92; & #48; 33 [$ {I };$ {t} H & quot; done # randomly generate new blocks (iBoxNewType = RANDOM % $ {# offsetBox [@]}) (iBoxNewRotate = RANDOM % $ {countBox [$ iBoxNewType]}) for (j = 0, I = ($ {offsetBox [$ iBoxNewType]} + $ iBoxNewRotate) * 8; j & amp; lt; 8; j ++, I ++) DoboxNew [$ j] =$ {box [$ I]}; done (cBoxNew =$ {colorTable [RANDOM % $ {# colorTable [@]}) # display the pre-displayed block echo-ne & quot; & #92; on the right; & #48; 33 [1 m & #92; & #48; 33 [7 m & #92; & #48; 33 [3 $ {cBoxNew} m & #92; & #48; 33 [4 $ {cBoxNew} m & quot; for (j = 0; j & amp; lt; 8; j ++ = 2 )) do (I = iTop + 1 + $ {boxNew [$ j]}) (t = iLeft + 2 * iTrayWidth + 7 + 2 * $ {boxNew [$ j + 1]}) echo-ne & quot; & #92; & #48; 33 [$ {I}; $ {t} H [] & quot; doneecho-ne & quot; & #92; & #48; 33 [0 m & Quot ;}# initially draw functionInitDraw () {clearRandomBox # randomly generate squares. Then, there is a square in the pre-display window on the right that is faster than RandomBox # Then randomly generate squares. the squares in the pre-display window on the right are updated, the original square will start to fall down locali t1 t2 t3 # display the border echo-ne & quot; & #92; & #48; 33 [1 m & quot; echo-ne & quot; & #92; & #48; 33 [3 $ {cBorder} m & #92; & #48; 33 [4 $ {cBorder} m & quot; (t2 = iLeft + 1) (t3 = iLeft + iTrayWidth * 2 + 3) for (I = 0; I & amp; lt; iTrayHeight; I ++) do (t1 = I + iTop + 2) echo-ne & quot; & #92; & #48; 33 [$ {t1 }; $ {t2} H | & quot; echo- Ne & quot; & #92; & #48; 33 [$ {t1 };$ {t3} H | & quot; done (t2 = iTop + iTrayHeight + 2) for (I = 0; I & amp; lt; iTrayWidth + 2; I ++ )) do (t1 = I * 2 + iLeft + 1) echo-ne & quot; & #92; & #48; 33 [$ {iTrayTop }; $ {t1} H ==& quot; echo-ne & quot; & #92; & #48; 33 [$ {t2 }; $ {t1} H ==& quot; doneecho-ne & quot; & #92; & #48; 33 [0 m & quot; # Show & quot; Score & quot; and & quot; Level & quot; echo-ne & quot; & #92; & #48; 33 [1 m & quot; (t1 = iLeft + iTrayWidth * 2 + 7) (t2 = ITop + 10) echo-ne & quot; & #92; & #48; 33 [3 $ {cScore} m & #92; & #48; 33 [$ {t2 };; {t1} HScore & quot; (t2 = iTop + 11) echo-ne & quot; & #92; & #48; 33 [3 $ {cScoreValue} m & #92; & #48; 33 [$ {t2} ;$ {t1} H $ {iScore} & quot; (t2 = iTop + 13) echo-ne & quot; & #92; & #48; 33 [3 $ {cScore} m & #92; & #48; 33 [$ {t2}; $ {t1} HLevel & quot; (t2 = iTop + 14) echo-ne & quot; & #92; & #48; 33 [3 $ {cScoreValue} m & #92; & #48; 33 [$ {t2} ;$ {t1} H $ {iLevel} & quot; echo-ne & quot; & #92; & #48; 33 [0 m & quot;} # GameOVer displayed when exiting! FunctionShowExit () {localy (y = iTrayHeight + iTrayTop + 3) echo-e & quot; & #92; & #48; 33 [$ {y}; 0 HGameOver! & #92; & #48; 33 [0 m & quot; exit} # display usage. functionUsage {cat & amp; lt; EOFUsage: $ APP_NAMEStart tetris game. -h, -- help display this help andexit -- version output version information andexitEOF} # The main game program starts here. if [[& quot; $1 & quot ;=& quot;-h & quot ;||& quot; $1 & quot ;=& quot; -- help & quot;]; thenUsageelif [[& quot; $1 & quot ;==& quot; -- version & quot;]; thenecho & quot; $ APP_NAME $ APP_VERSION & quot; elif [[& quot; $1 & quot ;=& Quot; -- show & quot;]; then # When the -- show parameter is found, run the display function RunAsDisplayerelsebash $0 -- show & amp; # Run the program again with the -- show parameter runaskeycycler $! # The process ID generated by the preceding line is used as the parameter fi

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.