shell版俄罗斯方块最终源码

#!/bin/bash#Pargram tetris game#History Walker 2015-07-27 version:firstAPP_NAME="${0##*[\\/]}"APP_VERSION="1.0"#颜色定义iSumColor=7 #颜色总数cRed=1#红色cGreen=2cYellow=3cBlue=4cFuchSia=5cCyan=6cWhite=7#位置定义marginLeft=10marginTop=10((mapLeft=marginLeft+2))((mapTop=marginTop+1))mapWidth=10mapHeight=15#信号定义sigRotate=25sigLeft=26sigRight=27sigDown=28sigAllDown=29sigExit=30#颜色设置cBorder=$cGreencScore=$cFuchsiacScoreValue=$cCyan#方块类型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)iSumType=7#方块总数boxStyle=(1 2 2 2 4 4 4) #每种方块对应的变化数iScoreEachLevel=50#运行时数据sig=0iScore=0iLevel=0boxNext=() #下一个方块iboxNextColor=0iboxNextType=0iboxNextStyle=0boxCur=()iBoxCurColor=0iBoxCurType=0iBoxCurStyle=0#显示进程PIDpidDisplayer=0#这两个是相对于边框的坐标boxCurX=-1boxCurY=-1#背景数组,用颜色表示,没有方块则为-1map=()for (( i = 0; i < mapHeight * mapWidth ; i++ ))domap[$i]=-1doneMyExitNoSub(){local ystty $sTTY#恢复终端((y = marginTop + mapHeight + 10 ))echo -e "\033[?25h\033[${y};0H"exit}MyExit(){kill -$sigExit $pidDisplayer#关闭显示进程MyExitNoSub} #显示退出ShowExit(){local y(( y = marginTop + mapHeight + 3 ))echo -e "\033[${y};1HGameOver!\033[0m"exit}#绘制方块函数DrawCurBox(){local i x y bErase sBoxbErase=$1if (( ${bErase} == 0 ))#根据参数不同,选择擦除方块或绘制方块thensBox="\040\040"elsesBox="[]"echo -ne "\033[1m\033[3${iBoxCurColor}m\033[4${iBoxCurColor}m"fifor (( i = 0; i < 8; i += 2))do(( y = mapTop + 1 + ${boxCur[$i]} + boxCurY ))#方块刚出现时就会全部绘制在棋盘中(( x = mapLeft + 1 + 2 * (boxCurX + ${boxCur[$i+1]}) ))echo -ne "\033[${y};${x}H${sBox}"doneecho -ne "\033[0m"}#接收命令RunAsKeyReceiver(){local Key aKey sig cESC sTTYpidDisplayer=$1aKey=(0 0 0)cESC=`echo -ne "\033"`cSpace=`echo -ne "\040"`sTTY=`stty -g`#保存终端trap "MyExit;" INT QUITtrap "MyExitNoSub;" $sigExitecho -ne "\033[?25l"while :do#始终在等待信号read -s -n 1 KeyaKey[0]=${aKey[1]}aKey[1]=${aKey[2]}aKey[2]=$Keysig=0if [[ $Key == $cESC && {aKey[1]} == $cESC ]]thenMyExitelif [[ ${aKey[0]} == $cESC && ${aKey[1]} == "[" ]]thenif [[ $Key == "A" ]]; then sig=$sigRotate#判断上下左右输入elif [[ $Key == "B" ]]; then sig=$sigDownelif [[ $Key == "C" ]]; then sig=$sigRightelif [[ $Key == "D" ]]; then sig=$sigLeftfielif [[ $Key == "W" || $Key == "w" ]]; then sig=$sigRotateelif [[ $Key == "S" || $Key == "s" ]]; then sig=$sigDownelif [[ $Key == "A" || $Key == "a" ]]; then sig=$sigLeftelif [[ $Key == "D" || $Key == "d" ]]; then sig=$sigRightelif [[ [$Key] == "[]" ]]; then sig=$sigAllDownelif [[ $Key == "Q" || $Key == "q" ]]thenMyExitfiif [[ $sig != 0 ]]thenkill -$sig $pidDisplayerfidone}#绘制边界DrawBorder(){clearlocal i y x1 x2echo -ne "\033[1m\033[3${cBorder}m\033[4${cBorder}m"((x1 = marginLeft + 1))((x2 = x1 + 2 + mapWidth * 2))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))((upBorder = marginTop +1))for ((i =0 ;i < mapWidth + 2;i++))do((y = i * 2 + marginLeft + 1))echo -ne "\033[${upBorder};${y}H=="echo -ne "\033[${x1};${y}H=="doneecho -ne "\033[0m"echo -ne "\033[1m"((y = marginLeft + mapWidth *2 + 7))((x1 = marginTop + 10))echo -ne "\033[3${cScore}m\033[${x1};${y}HScore"((x1 = marginTop + 11))echo -ne "\033[3${cScoreValue}m\033[${x1};${y}H${iScore}"((x1 = marginTop + 13))echo -ne "\033[3${cScore}m\033[${x1};${y}HLevel"((x1 = marginTop + 14))echo -ne "\033[3${cScoreValue}m\033[${x1};${y}H${iLevel}"echo -ne "\033[0m"}#用于判断是否可以移动BoxMove(){local i x y xPos yPosyPos=$1xPos=$2for (( i = 0 ; i < 8 ; i += 2 ))do(( y = yPos + ${boxCur[$i]} ))(( x = xPos + ${boxCur[$i+1]} ))if (( y < 0 || y >= mapHeight || x < 0 || x >= mapWidth ))thenreturn 1fiif (( ${map[y * mapWidth + x]} != -1 ))thenreturn 1fidonereturn 0}#准备下一方块PrepareNextBox(){local i x y#擦除已有的预显示方块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#随机生成下一方块(( iBoxNextType = RANDOM % iSumType))(( iBoxNextStyle = RANDOM % ${boxStyle[$iBoxNextType]} ))(( iBoxNextColor = RANDOM % ${iSumColor} + 1 ))boxNext=( `eval 'echo ${box'$iBoxNextType'_'$iBoxNextStyle'[@]}'` )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(( iBoxCurType = RANDOM % iSumType))(( iBoxCurStyle = RANDOM % ${boxStyle[$iBoxCurType]} ))(( iBoxCurColor = RANDOM % $iSumColor + 1 ))elseiBoxCurType=$iBoxNextTypeiBoxCurStyle=$iBoxNextStyleiBoxCurColor=$iBoxNextColorfiboxCur=( `eval 'echo ${box'$iBoxCurType'_'$iBoxCurStyle'[@]}'` )boxCurY=boxCur[8]boxCurX=boxCur[9]#创建后开始绘制DrawCurBox 1if ! BoxMove $boxCurY $boxCurXthen#kill -$sigExit $PPIDMyExit#ShowExitfi#同时开始准备下一方块PrepareNextBox}#初始化InitDraw(){clearDrawBorderCreateBox}#将方块写入背景当中Box2Map(){local i j x y line#填充背景色for ((i = 0 ; i < 8 ; i += 2))do((y = ${boxCur[$i]} + boxCurY ))((x = ${boxCur[$i+1]} + boxCurX ))map[y*mapWidth+x]=$iBoxCurColordoneline=0#判断每一行for (( i = 0 ; i < mapHeight ; i++))dofor (( j = 0; j < mapWidth; j++ ))do[[ ${map[i * mapWidth + j]} -eq -1 ]] && breakdone[ $j -lt $mapWidth ] && continue(( line++ ))#删除第i行,并将第0行到i-1行全部下移一行,移动行的下限(0)可以进一步简化for (( j = i * mapWidth – 1; j >= 0; j– ))do((x = j + mapWidth))map[$x]=${map[$j]}done#将第0行置空for ((i = 0; i<mapWidth;i++))domap[$i]=-1donedone#写入背景结束后,开始计算分数[ $line -eq 0 ] && return(( x = marginLeft + mapWidth * 2 + 7))(( y = marginTop + 11 ))(( iScore += line * 2 ))#显示新的分数echo -ne "\033[1m\033[3${cScoreValue}m\033[${y};${x}H${iScore}"#显示速度等级if ((iScore % iScoreEachLevel < line * 2 – 1))thenif ((iLevel < 20))then(( iLevel++ ))(( y = marginTop + 14 ))echo -ne "\033[3${cScoreValue}m\033[${y};${x}H${iLevel}"fifiecho -ne "\033[0m"#重新绘制界面for (( i = 0; i < mapHeight ; i++))do#棋盘相对于屏幕的坐标((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}#直接下落到底BoxAllDown(){local y iDowniDown=0(( y = boxCurY + 1 ))while BoxMove $y $boxCurXdo(( y++ ))(( iDown++ ))doneDrawCurBox 0(( boxCurY += iDown ))DrawCurBox 1Box2MapCreateBox}#上方向键,,旋转BoxRotate(){[ ${boxStyle[$iBoxCurType]} -eq 1 ] && return(( rotateStyle = (iBoxCurStyle +1) % ${boxStyle[$iBoxCurType]} ))boxTmp=( `eval 'echo ${boxCur[@]}'` )boxCur=( `eval 'echo ${box'$iBoxCurType'_'$rotateStyle'[@]}'` )if BoxMove $boxCurY $boxCurXthenboxCur=( `eval 'echo ${boxTmp[@]}'` )DrawCurBox 0boxCur=( `eval 'echo ${box'$iBoxCurType'_'$rotateStyle'[@]}'` )DrawCurBox 1iBoxCurStyle=$rotateStyleelseboxCur=( `eval 'echo ${boxTmp[@]}'` )fi}BoxLeft(){local x((x = boxCurX – 1))if BoxMove $boxCurY $xthenDrawCurBox 0((boxCurX = x))DrawCurBox 1fi}BoxRight(){local x((x = boxCurX + 1))if BoxMove $boxCurY $xthenDrawCurBox 0((boxCurX = x))DrawCurBox 1fi}BoxDown(){local y(( y = boxCurY + 1 ))if BoxMove $y $boxCurX#如果可移动则移动,不能则写入背景当中thenDrawCurBox 0(( boxCurY = y ))DrawCurBox 1elseBox2Map#写入背景当中,并创建下一方块CreateBoxfi}RunAsDisplayer(){#显示进程运行这一函数local sigThisInitDraw#初始化操作trap "sig=$sigRotate;" $sigRotatetrap "sig=$sigLeft;" $sigLefttrap "sig=$sigRight;" $sigRighttrap "sig=$sigDown;" $sigDowntrap "sig=$sigAllDown;" $sigAllDowntrap "ShowExit;" $sigExitwhile :#始终在循环等待do#本循环用于接收信号,for循环中有个睡眠时间,for循环之后有个BoxDown函数#for循环睡眠时间越长,自动下落延迟越长,所以for循环的次数决定了下落速度for ((i = 0; i < 21 – iLevel; i++))dosleep 0.02sigThis=$sigsig=0if (( sigThis == sigRotate )); then BoxRotate;elif (( sigThis == sigLeft )); then BoxLeft;elif (( sigThis == sigRight )); then BoxRight;elif (( sigThis == sigDown )); then BoxDown;elif (( sigThis == sigAllDown )); then BoxAllDown;fidoneBoxDowndone}#helpusage(){echo "tetris.sh [option]"echo "option:"echo " –version:for version information"echo " –help:for help information"echo "no option to run game"}#游戏主程序,以上是函数定义if [[ "$1" == "–version" ]]; thenecho "$APP_NAME $APP_VERSION"elif [[ "$1" == "–help" || "$1" == "–h" ]];thenusageelif [[ "$1" == "–show" || "$1" == "–v" ]]; thenRunAsDisplayer#只运行显示进程elsebash $0 –show&#启动显示进程,并放入后台开始执行RunAsKeyReceiver $!#获取最后一个后台进程fi其实,每个人都是幸福的。只是,你的幸福,常常在别人眼里。

shell版俄罗斯方块最终源码

相关文章:

你感兴趣的文章:

标签云: