温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

如何使用shell实现俄罗斯方块脚本

发布时间:2021-05-23 16:01:17 来源:亿速云 阅读:264 作者:小新 栏目:开发技术

这篇文章给大家分享的是有关如何使用shell实现俄罗斯方块脚本的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。

具体内容如下

draw 是画出图形界面,keytest是获取键盘,tetris是整个游戏

tetris.sh

#!/bin/bash    APP_NAME="${0##*[\\/]}"  APP_VERSION="1.0"    #颜色定义  iSumColor=7     #颜色总数  cRed=1       #红色  cGreen=2      #绿色  cYellow=3      #黄色  cBlue=4       #蓝色  cFuchsia=5     #紫红色  cCyan=6       #青色(蓝绿色)  cWhite=7      #白色    #位置与大小  marginLeft=3      #边框左边距  marginTop=2     #边框上边距  ((mapLeft=marginLeft+2))  #棋盘左边距  ((mapTop=$marginTop+1))   #棋盘上边距  mapWidth=10     #棋盘宽度  mapHeight=15      #棋盘高度    #颜色设置  cBorder=$cGreen  cScore=$cFuchsia  cScoreValue=$cCyan    #控制信号  #游戏使用两个进程,一个用于接收输入,一个用于游戏流程和显示界面;  #当前者接收到上下左右等按键时,通过向后者发送signal的方式通知后者。  sigRotate=25    #向上键  sigLeft=26  sigRight=27  sigDown=28  sigAllDown=29    #空格键  sigExit=30    #方块定义,7大类19种样式  #前8位为方块坐标,后2位为方块刚出现的时候的位置  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=0      #接收到的signal  iScore=0    #总分  iLevel=0    #速度级  boxNext=()   #下一个方块  iboxNextColor=0   #下一个方块的颜色  iboxNextType=0   #下一个方块的种类  iboxNextStyle=0   #下一个方块的样式  boxCur=()    #当前方块的位置定义  iBoxCurColor=0   #当前方块的颜色  iBoxCurType=0    #当前方块的种类  iBoxCurStyle=0   #当前方块的样式  boxCurX=-1   #当前方块的x坐标位置  boxCurY=-1   #当前方块的y坐标位置  map=()     #棋盘图表    #初始化所有背景方块为-1, 表示没有方块  for ((i = 0; i < mapHeight * mapWidth; i++))  do    map[$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 QUIT    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  }    #退出前的恢复  MyExitNoSub()  {    local y      #恢复终端属性    stty $sTTY    ((y = marginTop + mapHeight + 4))      #显示光标    echo -e "\033[?25h\033[${y};0H"    exit  }    MyExit()  {    #通知显示进程需要退出    kill -$sigExit $pidDisplayer      MyExitNoSub  }    #处理显示和游戏流程的主函数  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  }    #绘制当前方块,传第一个参数,0表示擦除当前方块,1表示绘制当前方块  DrawCurBox()  {    local i x y bErase sBox    bErase=$1    if (( bErase == 0 ))    then      sBox="\040\040"   #用两个空格擦除    else      sBox="[]"      echo -ne "\033[1m\033[3${iBoxCurColor}m\033[4${iBoxCurColor}m"    fi      for ((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}"    done    echo -ne "\033[0m"  }    #移动方块  #BoxMove(y, x), 测试是否可以把移动中的方块移到(y, x)的位置, 返回0则可以, 1不可以  BoxMove()  {    local i x y xPos yPos    yPos=$1    xPos=$2    for ((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))      then        #撞到墙壁了        return 1      fi            if (( ${map[y * mapWidth + x]} != -1 ))      then        #撞到其他已经存在的方块了        return 1      fi    done    return 0;  }    #将方块贴到棋盘上  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]=$iBoxCurColor #将方块颜色赋给地图    done      line=0    for ((i = 0; i < mapHeight; i++))    do      for ((j = 0; j < mapWidth; j++))      do        #如果棋盘上有空隙,跳出循环        [[ ${map[i*mapWidth+j]} -eq -1 ]] && break      done        [ $j -lt $mapWidth ] && continue      #说明当前行可消去,可消去行数加一      (( line++ ))        #第i行可被消除,将0行至第i-1行全部下移一行,从第i-1行开始移动      for ((j = i*mapWidth-1; j >= 0; j--))      do        ((x = j + mapWidth))        map[$x]=${map[$j]}      done        #因为下移一行,第0行置空      for ((i = 0; i < mapWidth; i++))      do        map[$i]=-1      done    done        [ $line -eq 0 ] && return      #根据消去的行数line计算分数和速度级    ((x = marginLeft + mapWidth * 2 + 7))    ((y = marginTop + 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 = marginTop + 14))        #显示新的速度级        echo -ne "\033[3${cScoreValue}m\033[${y};${x}H${iLevel}    "      fi    fi    echo -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))        then          echo -ne " "        else          echo -ne "\033[1m\033[3${map[$tmp]}m\033[4${map[$tmp]}m[]\033[0m"        fi      done    done  }    #左移一格  BoxLeft()  {    local x    ((x = boxCurX - 1))    if BoxMove $boxCurY $x    then      DrawCurBox 0      ((boxCurX = x))      DrawCurBox 1    fi  }    #右移一格  BoxRight()  {    local x    ((x = boxCurX + 1))    if BoxMove $boxCurY $x    then      DrawCurBox 0      ((boxCurX = x))      DrawCurBox 1    fi  }    #向下移一格  BoxDown()  {    local y    ((y = boxCurY + 1)) #新的y坐标    if BoxMove $y $boxCurX #测试是否可以下落一行    then      DrawCurBox 0  #将旧的方块抹去      ((boxCurY = y))      DrawCurBox 1  #显示新的下落后方块    else      #走到这儿, 如果不能下落了      Box2Map   #将当前移动中的方块贴到背景方块中      CreateBox  #产生新的方块    fi  }    #下落到底  BoxAllDown()  {    local y iDown      #计算能够下落的行数    iDown=0    (( y = boxCurY + 1 ))    while BoxMove $y $boxCurX    do      (( y++ ))      (( iDown++ ))    done      DrawCurBox 0  #将旧的方块抹去    ((boxCurY += iDown))    DrawCurBox 1  #显示新的下落后的方块    Box2Map   #将当前移动中的方块贴到背景方块中    CreateBox  #产生新的方块  }    #翻转  BoxRotate()  {    [ ${boxStyle[$iBoxCurType]} -eq 1 ] && return    ((rotateStyle = (iBoxCurStyle + 1) % ${boxStyle[$iBoxCurType]}))    #将当前方块保存到boxTmp    boxTmp=( `eval 'echo ${boxCur[@]}'` )    boxCur=( `eval 'echo ${box'$iBoxCurType'_'$rotateStyle'[@]}'` )      if BoxMove $boxCurY $boxCurX  #测试旋转后是否有空间放的下    then      #抹去旧的方块      boxCur=( `eval 'echo ${boxTmp[@]}'` )      DrawCurBox 0        boxCur=( `eval 'echo ${box'$iBoxCurType'_'$rotateStyle'[@]}'` )      DrawCurBox 1      iBoxCurStyle=$rotateStyle    else      #不能旋转,还是继续使用老的样式      boxCur=( `eval 'echo ${boxTmp[@]}'` )    fi  }    #准备下一个方块  PrepareNextBox()  {    local i x y    #清除右边预显示的方块    if (( ${#boxNext[@]} != 0 )); then      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\040\040"      done    fi      #随机生成预显式方块    (( 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[]"    done      echo -ne "\033[0m"    }    #显示新方块  CreateBox()  {    if (( ${#boxCur[@]} == 0 )); then      #当前方块不存在      (( iBoxCurType = RANDOM % iSumType ))      (( iBoxCurStyle = RANDOM % ${boxStyle[$iBoxCurType]} ))      (( iBoxCurColor = RANDOM % $iSumColor + 1 ))    else      #当前方块已存在, 将下一个方块赋给当前方块      iBoxCurType=$iBoxNextType;      iBoxCurStyle=$iBoxNextStyle;      iBoxCurColor=$iBoxNextColor    fi      #当前方块数组    boxCur=( `eval 'echo ${box'$iBoxCurType'_'$iBoxCurStyle'[@]}'` )    #初始化方块起始坐标    boxCurY=boxCur[8];    boxCurX=boxCur[9];      DrawCurBox 1    #绘制当前方块    if ! BoxMove $boxCurY $boxCurX    then      kill -$sigExit $PPID      ShowExit    fi      PrepareNextBox      }    #绘制边框  DrawBorder()  {    clear      local i y x1 x2    #显示边框    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 -ne "\033[${mapTop};${y}H=="  #绘制上边框      echo -ne "\033[${x1};${y}H=="    #绘制下边框    done    echo -ne "\033[0m"      #显示"Score"和"Level"字样    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"  }    InitDraw()  {    clear      #清屏    DrawBorder   #绘制边框    CreateBox    #创建方块  }    #退出时显示GameOVer!  ShowExit()  {    local y    ((y = mapHeight + mapTop + 3))    echo -e "\033[${y};1HGameOver!\033[0m"    exit  }    #游戏主程序在这儿开始.  if [[ "$1" == "--version" ]]; then    echo "$APP_NAME $APP_VERSION"  elif [[ "$1" == "--show" ]]; then    #当发现具有参数--show时,运行显示函数    RunAsDisplayer  else    bash $0 --show& #以参数--show将本程序再运行一遍    RunAsKeyReceiver $! #以上一行产生的进程的进程号作为参数  fi

keytest.sh

#!/bin/bash    GetKey()  {    aKey=(0 0 0) #定义一个数组来保存3个按键      cESC=`echo -ne "\033"`    cSpace=`echo -ne "\040"`      while :    do      read -s -n 1 key #读取一个字符,将读取到的字符保存在key中      #echo $key      #echo XXX         aKey[0]=${aKey[1]} #第一个按键      aKey[1]=${aKey[2]} #第二个按键      aKey[2]=$key    #第三个按键        if [[ $key == $cESC && ${aKey[1]} == $cESC ]]      then        MyExit      elif [[ ${aKey[0]} == $cESC && ${aKey[1]} == "[" ]]      then        if [[ $key == "A" ]]; then echo KEYUP        elif [[ $key == "B" ]]; then echo KEYDOWN        elif [[ $key == "D" ]]; then echo KEYLEFT        elif [[ $key == "C" ]]; then echo KEYRIGHT        fi      fi    done  }    GetKey

draw.sh

#!/bin/bash    #位置与大小  marginLeft=8      #边框左边距  marginTop=6     #边框上边距  ((mapLeft=marginLeft+2))  #棋盘左边距  ((mapTop=$marginTop+1))   #棋盘上边距  mapWidth=10     #棋盘宽度  mapHeight=15      #棋盘高度      #方块定义,7大类19种样式  #前8位为方块坐标,后2位为方块刚出现的时候的位置  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()  {    clear      local i y x1 x2    #显示边框    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=="    #绘制下边框    done    echo -ne "\033[0m"  }    DrawBox()  {    local i x y xPos yPos    yPos=${box0_0[8]}    xPos=${box0_0[9]}    echo -ne "\033[1m\033[35m\033[45m"    for ((i = 0; i < 8; i += 2))    do      (( y = mapTop + 1 + ${box0_0[$i]} + yPos ))      (( x = mapLeft + 1 + 2 * (${box0_0[$i + 1]} + xPos) ))      echo -ne "\033[${y};${x}H[]"    done    echo -ne "\033[0m"  }    InitDraw()  {    clear      #清屏    DrawBorder   #绘制边框    DrawBox    while :    do      sleep 1    done  }    InitDraw

如何使用shell实现俄罗斯方块脚本

感谢各位的阅读!关于“如何使用shell实现俄罗斯方块脚本”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI