用shell脚本写的一个简单的俄罗斯方块

用shell脚本写的一个简单的俄罗斯方块


代码

代码

#!/bin/bash
#version 1.2,若非正常退出,请使用附带的killel.sh脚本杀死进程
#定义用于显示的地图map和背景全地图mapback
    map=(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) #游戏共有20行,16列,此处定义行数,而每行是否有方块由数组中的元素决定(二进制的0为没有方块,1为有方块)
mapback=(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) #(0 0 0 0 0 0 65534 65534 65534 65534 65534 65534 65534 65534 65534 65534 65534 65534 65534 65534 )  #用于临时存放包含当前方块的背景地图
zongtime=10
sleeptime=0.1
downtime=0

#存放当前方块的相关参数
curx=7
cury=0
curtype=0
curstat=0
curfk=(0 0 0 0)        #用于表示当前方块的数组

#预制方块参数
yutype=0
yustat=0
yufk=(0 0 0 0)

#分数和行数
zongfen=0
zonghang=0
dancifen=0
dangqianhang=0
qiancihang=0
dengji=1

#用于存放fGetfk生成的方块
scfk=(0 0 0 0)

#游戏参数
cyzfc="左移a 右移d 变形j 落地k 加速s 退出q 暂停p 存档c 取档l 重新开始r"
zhuangtai=$cyzfc
fangkuai="@"
beijing=" "
gameover=0

#难度相关参数
nanduline=0  #存放底部随机产生的行
nandutime=0  #在时间难度模式下的计时器
nanduzongtime=100 #在时间难度模式下的产生底部随机行的时间间隔
nandutimeflag=0  #是否打开时间难度的标志位
nandudengji=1  
nanduzonghang=12 #在行数难度模式下的消除多少行产生底部随机行
nanduhang=0  #在行数难度模式下的行数计数器
nanduhangflag=0  #是否带开行数难度的标志位

#以后要修改的:定义当前方块和临时方块############################################
#      (3 3|0 15,2 2 2 2|2 7,2 3 2,0 7 2,2 6 2|1 7,2 2 3,7 4,3 1 1|4 7,3 2 2,7 1,1 1 3|6 3,1 3 2|3 6,2 3 1)
#allfk=(3 3 0 15 2 2 2 2 2 7 2 3 2 0 7 2 2 6 2 1 7 2 2 3 7 4 3 1 1 4 7 3 2 2 7 1 1 1 3 6 3 1 3 2 3 6 2 3 1)
#        (2|2 4|2 3 3 3|2 3 2 3|2 3 2 3|2 3|2 3)
#afkstat=(2 2 4 2 3 3 3 2 3 2 3 2 3 2 3 2 3 2 3)
#afktype=(1 2 4 4 4 2 2)
#################################################################################



#定义各类方块,(各类方块对应数字:1、田字形 2、长条形 3、山字形 4、左勾形 5、右勾形 6、左之形 7、右之形)
function fGetfk(){ #参数1:方块类型  #参数2:方块状态
 case $1 in
  1)
   scfk=(3 3)
  ;;
  2)
   case $2 in
    1)
     scfk=(0 15)
    ;;
    2)
     scfk=(1 1 1 1)
    ;;
    3)
     scfk=(0 15)
    ;;
    4)
     scfk=(1 1 1 1)
    ;;
   esac 
  ;; 
  3)
   case $2 in
    1)
     scfk=(2 7)
    ;;
    2)
     scfk=(2 3 2)
    ;;
    3)
     scfk=(0 7 2)
    ;;
    4)
     scfk=(1 3 1)
    ;;
   esac
  ;;
  4)
   case $2 in
    1)
     scfk=(1 7)
    ;;
    2)
     scfk=(2 2 3)
    ;;
    3)
     scfk=(7 4)
    ;;
    4)
     scfk=(3 1 1)
    ;;
   esac
  ;;
  5)
   case $2 in
    1)
     scfk=(4 7)
    ;;
    2)
     scfk=(3 2 2)
    ;;
    3)
     scfk=(7 1)
    ;;
    4)
     scfk=(1 1 3)
    ;;
   esac
  ;;
  6)
   case $2 in
    1)
     scfk=(6 3)
    ;;
    2)
     scfk=(1 3 2)
    ;;
    3)
     scfk=(6 3)
    ;;
    4)
     scfk=(1 3 2)
    ;;
   esac
  ;;
  7)
   case $2 in
    1)
     scfk=(3 6)
    ;;
    2)
     scfk=(2 3 1)
    ;;
    3)
     scfk=(3 6)
    ;;
    4)
     scfk=(2 3 1)
    ;;
   esac
  ;;
 esac
}

#刷背景地图的函数,也即是把当前方块融入背景地图
function fMaptemp(){
 local i
 for ((i=0;i<20;i++))
 do
  ((mapback[i]=map[i]))
 done
}

#刷显示地图的函数
function fMap(){
 local i
 for ((i=0;i<20;i++))
 do
  ((map[i]=mapback[i]))
 done
}


#绘制当前方块
function fDrawfk(){  #参数1:给定的y坐标
 local curfktemp cH i
 for ((i=0;i<4;i++))
 do
  ((curfktemp=curfk[i]<< curx))
  ((map[$1+i]=mapback[$1+i]|curfktemp))
 done
}


#方块左移的函数
function fLeft(){
 if fPeng $((curx+1)) $cury $curtype $curstat
 then
  ((curx++))
  fDrawfk $cury
 fi
}

#方块右移的函数
function fRight(){
 if fPeng $((curx-1)) $cury $curtype $curstat
 then
  ((curx--))
  fDrawfk $cury
 fi
}

#方块变形的函数
function fChange(){
 local cH i tempx j peng
 fGetfk $curtype $curstat
 for j in 0 -1 -2 -3 
 do
  ((tempx=curx+j))
  if fPeng $tempx $cury $curtype $((curstat%4+1))
  then
   ((curstat=curstat%4+1))
   curx=$tempx
   for ((i=0;i<4;i++))
   do
    ((curfk[i]=scfk[i]))
   done
   fDrawfk $cury
   return 0
  fi
 done
}


#方块下移的函数
function fDown(){
 local a
 if fPeng $curx $((cury+1)) $curtype $curstat
 then
  ((map[cury]=mapback[cury]))
  ((cury++))
  fDrawfk $cury
 else
  fMaptemp
  fZhengli
  fInit
  return 0
 fi
}


#方块直接落底的函数
function fDownbottom(){
 local a i1 i2
 for ((i1=cury;i1<19;i1++))
 do
  fPeng $curx $(($i1+1)) $curtype $curstat;a=$?
  if [ $a -eq 1 ]
  then
   for ((i2=0;i2<4;i2++))
   do
    ((map[cury+i2]=mapback[cury+i2]))
   done
   ((cury=$i1))
   fDrawfk $cury
   fMaptemp
   fZhengli
   fInit
   #fDown
   return 0
  fi
 done
}


#判断是否出边界或与其他方块碰撞的函数
function fPeng(){ #参数1:移动后的x坐标   #参数2:移动后的y坐标 #参数3:方块的类型 #参数4:方块的状态
 local cH chazhi
 fGetfk $3 $4
 cH=${#scfk[@]}
# fRemovefk $cury
 for ((i=0;i<4;i++))
 do
  if (( $1<0 || ((scfk[i]<<$1))>65535 || (($2+$cH))>20 || ((((scfk[i]<<$1))&mapback[$2+i]))>0))
  then
   return 1
  fi
 done
 return 0
}

#检查函数
function fCheck(){
 local i
 for ((i=0;i<4;i++))
 do
  if [ ${map[cury+i]} -eq 65535 ]
  then
   return 0
  fi
 done
 return 1
}

#整理及记分函数
function fZhengli(){
 local i j k cH mapbottom
 j=19
 if fCheck
 then
  fGetfk $curtype $curstat 
  cH=${#scfk[@]}
  for i in {0..3}
  do
   for ((k=0;k<cH;k++))
   do
    if [ ${mapback[cury+k]} -eq 65535 ]
    then
     if [ ${map[cury+k]} -eq 65535 ]
     then
      map[cury+k]=0
     elif [ ${map[cury+k]} -eq 0 ]
     then
      map[cury+k]=65535
     fi
    fi
   done
   fDisplay
   sleep 0.3
  done
  for ((i=19;i>=0;i--))
  do
   if [ ${mapback[i]} -ne 65535 ]
   then
    map[j]=${mapback[i]}
    ((j--))
   fi
  done
  ((dangqianhang=j+1))
  for ((j=$j;j>=0;j--))
  do
   map[j]=0
  done 
  fMaptemp
  #计分方法
  if [ $dangqianhang -eq $qiancihang -a $dangqianhang -ne 1 ]
  then
   ((dancifen=dancifen+5*dangqianhang*dangqianhang*(dengji+9)/10*(10+nanduhangflag*2)/10)) #若与上次消除行数相同,则分数加成
  else
   ((dancifen=(10*dangqianhang)*(dengji+9)/10*(10+nanduhangflag*2)/10))  #若与上次消除行数不相同,则分数加成消失
  fi
    
  ((zongfen=zongfen+dancifen))
  ((zonghang=zonghang+dangqianhang))
  qiancihang=$dangqianhang
  ((nanduhang=nanduhang+dangqianhang))
  if ((((zonghang/50+1))>dengji))
  then 
   ((dengji=zonghang/50+1)) 
   for i in {1..4}
   do
    zhuangtai="升级了!准备进入下一级"
    fDisplay
    sleep 0.2
    zhuangtai=""
    fDisplay
    sleep 0.2
   done
   zhuangtai=$cyzfc
  fi
  if ((zongtime<11))
  then
   ((zongtime=11-dengji))
  fi
  if ((nanduhangflag==1&&nanduhang>=nanduzonghang))
  then
   fHangnandu
   nanduhang=0
   #mapbottom=map[19]
   for i in {1..3}
   do
    map[19]=0
    fDisplay
    sleep 0.3
    map[19]=$nanduline
    fDisplay
    sleep 0.3
   done
  fi
 fi 
}


#新方块初始化函数
function fInit(){
 local cH i
 curtype=$yutype
 curstat=$yustat
 ((yutype=$RANDOM%7+1))
 ((yustat=$RANDOM%4+1))
 fGetfk $yutype $yustat
 for i in {0..3}
 do
  ((yufk[i]=scfk[i]))
 done
 #curtype=2
 #curstat=1
 curx=7
 cury=0
 fGetfk $curtype $curstat
 for ((i=0;i<4;i++))
 do
  ((curfk[i]=scfk[i]))
 done
 downtime=0
 fDrawfk $cury
 #测试新出方块是否一出来就和背景方块重合,是则代表游戏结束
 fPeng $curx $cury $curtype $curstat;a=$?
 if [ $a -ne 0 ]
 then
  gameover=1
 # echo "o" > ctrl.txt
 # cat ctrl.txt>>debug
  #return 1
 fi
}

#时间难度
function fTimenandu(){
 local i
 fPeng $curx $((cury+1)) $curtype $curstat
 if [ $? -ne 0 ]
 then
  fMaptemp
  fZhengli
  fInit
 fi

 ((nanduline=$RANDOM%32767+$RANDOM%32766+1))
 for i in {0..18}
 do
  mapback[i]=${mapback[i+1]}
 done
 mapback[19]=$nanduline
 fMap
 fDrawfk $cury
 fPeng $curx $((cury+1)) $curtype $curstat
 if [ $? -ne 0 ]
 then
  fMap
  fDrawfk $cury
  fMaptemp
  fZhengli
  fInit
 fi
}

#行数难度
function fHangnandu(){
 local i
 ((nanduline=$RANDOM%32767+$RANDOM%32766+1))
 for i in {0..18}
 do
  mapback[i]=${mapback[i+1]}
 done
 mapback[19]=$nanduline
 fMap
 #fDrawfk $cury
}


#输出调试数据的函数,此函数仅用于调试
function fTiaoshi(){ #参数1:接收调试数据的文件
 echo "map   ${map[@]}" >$1
 echo "mapba ${mapback[@]}" >> $1
 echo -n "curx  $curx" >> $1
 echo -n "cury  $cury" >> $1
 echo -n "curtype $curtype" >> $1
 echo -n "curstat $curstat" >> $1
 echo -n "yutype $yutype" >> $1
 echo -n "yustat $yustat" >> $1
 echo -n "zongfen  $zongfen" >> $1
 echo -n "zonghang $zonghang" >> $1
 echo -n "dancifen $dancifen" >> $1
 echo -n "dangqianhang $dangqianhang" >> $1
 echo -n "qiancihang $qiancihang" >> $1
 echo "dengji $dengji" >> $1
 echo "" >> $1  
}

#存档
function fSave(){
 echo "${map[@]}" >> save.txt        #显示地图
 echo "${mapback[@]}" >> save.txt    #背景地图
 echo "${curx}" >> save.txt          #当前x坐标
 echo "${cury}" >> save.txt          #当前y坐标
 echo "${curtype}" >> save.txt       #当前方块类型
 echo "${curstat}" >> save.txt       #当前方块状态
 echo "${yutype}" >> save.txt        #预制方块类型  
 echo "${yustat}" >> save.txt        #预制方块状态  
 echo "${zongfen}" >> save.txt       #总分  
 echo "${zonghang}" >> save.txt      #总行数
 echo "${dancifen}" >> save.txt      #单次得分   
 echo "${dangqianhang}" >> save.txt  #当前消除行数
 echo "${qiancihang}" >> save.txt    #前次消除行数
 echo "${dengji}" >> save.txt        #等级
 echo "a${fangkuai}" >> save.txt     #用于代表方块的字符 
 echo "a${beijing}" >> save.txt      #用于代表背景的字符
 echo "${nanduhangflag}" >> save.txt #是否开启难度的标志
 echo "${nanduhang}" >> save.txt     #底部出现的随机行计数器
}

#读档
function fLoad(){
 local j=0
 map=()
 mapback=()
 for i in `sed -n "1p" save.txt`
 do
  map[j]=$i
  ((j++))
 done

 j=0
 for i in `sed -n "2p" save.txt`
 do
  mapback[j]=$i
  ((j++))
 done
 
 curx=`sed -n "3p" save.txt`
 cury=`sed -n "4p" save.txt`
 curtype=`sed -n "5p" save.txt`
 curstat=`sed -n "6p" save.txt`
 yutype=`sed -n "7p" save.txt`
 yustat=`sed -n "8p" save.txt`
 zongfen=`sed -n "9p" save.txt`
 zonghang=`sed -n "10p" save.txt`
 dancifen=`sed -n "11p" save.txt`
 dangqianhang=`sed -n "12p" save.txt`
 qiancihang=`sed -n "13p" save.txt`
 dengji=`sed -n "14p" save.txt`

 fangkuai=`sed -n "15p" save.txt`
 if [ "$fangkuai" == "a" ]
 then
  fangkuai=" "
 else
  fangkuai=${fangkuai:1:1}
 fi

 beijing=`sed -n "16p" save.txt`
 if [ "$beijing" == "a" ]
 then
  beijing=" "
 else
  beijing=${beijing:1:1}
 fi

 curfk=()
 scfk=()
 yufk=()

 fGetfk $curtype $curstat

 for ((i=0;i<4;i++))
 do
  curfk[i]=${scfk[i]}
 done
 
 fGetfk $yutype $yustat
 for ((i=0;i<4;i++))
 do
  yufk[i]=${scfk[i]}
 done
 
 if ((zongtime<11))
 then
  ((zongtime=11-dengji))
 fi
 
 nanduhangflag=`sed -n "17p" save.txt`
 nanduhang=`sed -n "18p" save.txt`
}

#读取配置文件
function fConf(){
 beijing=`sed -n "/beijing=/p" peizhi.conf`
 if [ "$beijing" == "beijing=" ]
 then
  beijing=" "
 else
  beijing=${beijing:${#beijing}-1:1}
 fi

 fangkuai=`sed -n "/fangkuai=/p" peizhi.conf`
 if [ "$fangkuai" == "fangkuai=" ]
 then
  fangkuai=" "
 else
  fangkuai=${fangkuai:${#fangkuai}-1:1}
 fi
}

#退出函数
function fExit(){
 local ctkey i
 zhuangtai="确定要退出吗?(y/n)"
 fDisplay
 :>ctrl.txt

 while true
 do
  ctkey=$(cat ctrl.txt)
  if [ "$ctkey" == "n" ]
  then
   zhuangtai=$cyzfc
   :>ctrl.txt
   return
  elif [ "$ctkey" == "y" ]
  then
   break 
  fi
  sleep 0.2
 done

 rm -fr ctrl.txt fk.disp start.txt
 clear
 for i in $(ps -aux |grep -E "fk.disp"|grep -Ev "vim|grep"|awk '{print $2}')
 do
  kill -9 $i &>/dev/null
 done
 clear

 for i in $(ps -aux |grep -E "elsfk|start.txt"|grep -Ev "vim|grep"|awk '{print $2}')
 do
  kill -9 $i &>/dev/null
 done
 clear
 exit
}


#根据参数修改显示文件fk.disp,然后根据fk.disp文件显示游戏画面
function fDisplay(){
 local x y i j
 :> fk.disp

 x=65536;y=${map[0]}
 echo -n "|" >> fk.disp
 for j in {1..16}
 do
  x=$((x>>1))
  if [ $((x&y)) -ne 0 ]
  then
   echo -n "${fangkuai}" >> fk.disp
  else
   echo -n "${beijing}" >> fk.disp
  fi   
 done
 echo -n "|" >> fk.disp
 echo "总  分:$zongfen" >>fk.disp

 x=65536;y=${map[1]}
 echo -n "|" >> fk.disp
 for j in {1..16}
 do
  x=$((x>>1))
  if [ $((x&y)) -ne 0 ]
  then
   echo -n "${fangkuai}" >> fk.disp
  else
   echo -n "${beijing}" >> fk.disp
  fi 
 done
 echo -n "|" >> fk.disp
 echo "总  行:$zonghang" >>fk.disp

 x=65536;y=${map[2]}
 echo -n "|" >> fk.disp
 for j in {1..16}
 do
  x=$((x>>1))
  if [ $((x&y)) -ne 0 ]
  then
   echo -n "${fangkuai}" >> fk.disp
  else
   echo -n "${beijing}" >> fk.disp
  fi 
 done
 echo -n "|" >> fk.disp
 echo "单次分:$dancifen" >>fk.disp

 x=65536;y=${map[3]}
 echo -n "|" >> fk.disp
 for j in {1..16}
 do
  x=$((x>>1))
  if [ $((x&y)) -ne 0 ]
  then
   echo -n "${fangkuai}" >> fk.disp
  else
   echo -n "${beijing}" >> fk.disp
  fi
 done
 echo -n "|" >> fk.disp
 echo "等  级:$dengji" >>fk.disp

 for i in {4..7}
 do
  echo -n "|" >> fk.disp
  x=65536
  y=${map[$i]}
  for j in {1..16}
  do
   x=$((x>>1))
   if [ $((x&y)) -ne 0 ]
   then
    echo -n "${fangkuai}" >> fk.disp
   else
    echo -n "${beijing}" >> fk.disp
   fi
  done
  echo -n "|" >> fk.disp
  x=8
  y=${yufk[i-4]} 
  for j in {0..3}
  do 
   if [ $((x&y)) -ne 0 ]
   then
    echo -n $fangkuai >> fk.disp
   else
    echo -n " " >> fk.disp
   fi
   x=$((x>>1))
  done
 echo "" >> fk.disp
 done

 for i in {8..19}
 do
  echo -n "|" >> fk.disp
  x=65536
  y=${map[$i]}
  for j in {1..16}
  do
   x=$((x>>1))
   if [ $((x&y)) -ne 0 ]
   then
    echo -n "${fangkuai}" >> fk.disp
   else
    echo -n "${beijing}" >> fk.disp
   fi	
  done
  echo "|" >> fk.disp
 done
 echo "~~~~~~~~~~~~~~~~~~" >> fk.disp
 echo $zhuangtai >>fk.disp
}

#得到键盘输入并修改ctrl.txt文件以传参给fMain函数
function fGetKey(){
 local key i ctrlkey #tshang=12
 while true
 do

  read -n 1 -s  key &>/dev/null
  echo "::outkey" >>debug
  ctrlkey=$(cat ctrl.txt)
  
  if [ "$ctrlkey" == "beijing" ]
  then
   if [ "$key" == "" ]
   then 
    sed -i "/beijing=/cbeijing=" peizhi.conf
    sed -i  "12c|请输入一个字符作为背景:         |" start.txt
    sed -i  "13c|(回车为空格):空格               |" start.txt
   else
    sed -i "/beijing=/cbeijing=${key}" peizhi.conf
    sed -i  "12c|请输入一个字符作为背景:         |" start.txt
    sed -i  "13c|(回车为空格):$key                  |" start.txt
   fi
   key=""
   :>ctrl.txt
  fi
  
  if [ "$ctrlkey" == "fangkuai" ]
  then
   if [ "$key" == "" ]
   then
    sed -i "/fangkuai=/cfangkuai=" peizhi.conf
    sed -i  "12c|请输入一个字符作为方块:         |" start.txt
    sed -i  "13c|(回车为空格):空格               |" start.txt
   else
    sed -i "/fangkuai=/cfangkuai=${key}" peizhi.conf
    sed -i  "12c|请输入一个字符作为方块:         |" start.txt
    sed -i  "13c|(回车为空格):$key                  |" start.txt
   fi
   key=""
   :>ctrl.txt
  fi
 
  if [ "$key" == "a" -o "$key" == "A" ]
  then
   echo "l" > ctrl.txt           #l=左移
  elif [ "$key" == "d" -o "$key" == "D" ]
  then
   echo "r" > ctrl.txt           #r=右移  
  elif [ "$key" == "j" -o "$key" == "J" ]
  then
   echo "c" > ctrl.txt           #c=变形
  elif [ "$key" == "k" -o "$key" == "K" ]
  then
   echo "d" > ctrl.txt       #d=落到底部
  elif [ "$key" == "q" -o "$key" == "Q" ]
  then
   echo "e" > ctrl.txt           #e=退出
  elif [ "$key" == "p" -o "$key" == "P" ]
  then
   echo "p" > ctrl.txt           #p=暂停
  elif [ "$key" == "r" -o "$key" == "R" ]
  then
   echo "s" > ctrl.txt       #r=重新开始
  elif [ "$key" == "y" -o "$key" == "Y" ]
  then
   echo "y" > ctrl.txt            #y=yes
  elif [ "$key" == "n" -o "$key" == "N" ]
  then
   echo "n" > ctrl.txt             #y=no
  elif [ "$key" == "c" -o "$key" == "C" ]
  then
   echo "w" > ctrl.txt           #w=存档
  elif [ "$key" == "l" -o "$key" == "L" ]
  then
   echo "a" > ctrl.txt           #a=取档
  elif [ "$key" == "s" -o "$key" == "S" ]
  then
   echo "h" > ctrl.txt           #a=取档
  elif [ "$key" == "1" ]
  then
   echo "1" > ctrl.txt       #1=开始游戏
  elif [ "$key" == "2" ]
  then
   echo "2" > ctrl.txt       #2=读取存档
  elif [ "$key" == "3" ]
  then
   echo "3" > ctrl.txt       #3=改变背景
  elif [ "$key" == "4" ]
  then
   echo "4" > ctrl.txt       #4=改变方块
  elif [ "$key" == "5" ]
  then
   echo "5" > ctrl.txt       #5=退出游戏
  elif [ "$key" == "6" ]
  then
   echo "6" > ctrl.txt       #6=显示帮助
  elif [ "$key" == "7" ]
  then
   echo "7" > ctrl.txt       #7=启用难度
  elif [ "$key" == "0" ]
  then
   echo "0" > ctrl.txt       #0=退出帮助
  fi
 done
}

#制作开始画面文件
function fStartfile(){
 echo "-----------------------------------" >start.txt
 echo "|         连消俄罗斯方块          |" >>start.txt
 echo "|            版本:1.1             |" >>start.txt
 echo "-----------------------------------" >>start.txt
 echo "|   1、开始游戏     7、启用难度   |" >>start.txt
 echo "|   2、读取存档                   |" >>start.txt
 echo "|   3、改变背景                   |" >>start.txt
 echo "|   4、改变方块                   |" >>start.txt
 echo "|   5、退出游戏                   |" >>start.txt
 echo "|   6、显示帮助                   |" >>start.txt
 echo "-----------------------------------" >>start.txt
 echo "|                                 |" >>start.txt
 echo "|                                 |" >>start.txt
 echo "-----------------------------------" >>start.txt
 echo "|     Copyright © 2017 洪 超      |" >>start.txt
 echo "|      All rights reserved        |" >>start.txt
 echo "-----------------------------------" >>start.txt
}

#制作帮助文件
function fHelpfile(){
 echo -n "           " >start.txt
 echo "游戏帮助" >>start.txt
 echo "退出帮助请按0" >>start.txt
 echo "1.各个键的使用:" >>start.txt
 echo -e "左移:a 右移:d 变形:j 落地:k 加速:s 退出:q\n暂停:p 存档:c 取档:l 重新开始:r" >>start.txt 
 echo -e "2.游戏计分方法:\n消除1行得到10分,连续消除相同行数将会有分\n数加成,具体计分方法如下:" >>start.txt 
 echo -e "1)连续消除1行无加成;\n2)连续消除2行以上将在上次单次得分的基础上\n加消除行数的平方;" >>start.txt 
 echo -e "3)连续消除相同行数后若有一次消除不同行数\n加成将消失;" >>start.txt 
 echo -e "4)等级加成,等级1无加成,等级2单次得分加\n消除行数的平方乘1.1,等级3单次得分加消除\n行数的平方乘1.2.....以此类推" >>start.txt 
 echo -e "3.每消除50行升一等级" >>start.txt 
 echo -e "4.若开启难度,每消除12行底部出现一行方块" >>start.txt 
 echo -e "5.以后将有更多新玩法,敬请期待" >>start.txt 
}

#显示开始画面
function fStart(){
 local ctrlkey
 :>ctrl.txt
 fStartfile
 watch -n 0.2 "cat start.txt"& 
 startid=$!
 while true
 do
  ctrlkey=`cat ctrl.txt`
  if [ "$ctrlkey" == "1" ]
  then
   kill -9 $startid
   fConf
   :>ctrl.txt
   return
  fi

  if [ "$ctrlkey" == "2" ]
  then
   if [ -a save.txt ]  #检查是否有存档文件
   then
    kill -9 $startid &>/dev/null
    fLoad
    :>ctrl.txt
    return
   else
    sed -i "12c|          (当前无存档)           |" start.txt
    :>ctrl.txt
   fi
  fi

  if [ "$ctrlkey" == "3" ] 
  then
   echo "beijing"> ctrl.txt
   sed -i  "12c|请输入一个字符作为背景:         |" start.txt
   sed -i  "13c|(回车为空格):                   |" start.txt
  fi

  if [ "$ctrlkey" == "4" ]
  then
   echo "fangkuai"> ctrl.txt
   sed -i  "12c|请输入一个字符作为方块:         |" start.txt
   sed -i  "13c|(回车为空格):                   |" start.txt
  fi

  if [ "$ctrlkey" == "5" ]
  then
   kill -9 $startid &>/dev/null
   rm -fr ctrl.txt fk.disp start.txt
   clear
   for i in $(ps -aux |grep -E "fk.disp"|grep -Ev "vim|grep"|awk '{print $2}')
   do
    kill -9 $i
   done
   clear
   for i in $(ps -aux |grep -E "elsfk|start.txt"|grep -Ev "vim|grep"|awk '{print $2}')
   do
    kill -9 $i
   done
   clear
   exit
  fi

  if [ "$ctrlkey" == "6" ]
  then
   fHelpfile
   :>ctrl.txt
  fi
  
  if [ "$ctrlkey" == "7" ]
  then
   #nandutimeflag=1  #是否打开时间难度
   nanduhangflag=1
   sed -i  "12c|已开启难度模式                   |" start.txt
   :>ctrl.txt
  fi
  
  if [ "$ctrlkey" == "0" ]
  then 
   fStartfile
   :>ctrl.txt
  fi
 sleep 0.2
 done 
}

#主程序
function fMain(){
 local i
 :>fk.disp
 :>ctrl.txt
 if ! [ -a peizhi.conf ]
 then
  echo "beijing=" > peizhi.conf
  echo "fangkuai=@" >>peizhi.conf
 fi
# fConf
 ((yutype=$RANDOM%7+1))
 ((yustat=$RANDOM%4+1))
 fInit
 fStart
 watch -n 0.1 "cat fk.disp"&

 while :
 do
  if [ $gameover -eq 1 ]
  then
   echo "你的总分是:$zongfen" >> chengji.txt
   echo "你的总消除行数是:$zonghang" >> chengji.txt
   zhuangtai="游戏结束!若要重新开始请按r,退出请按q"
   fDisplay
   map=(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)
   mapback=(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)
   zongfen=0
   zonghang=0
   dancifen=0
   dangqianhang=0
   qiancihang=0
   dengji=1
   nanduhang=0
   :>ctrl.txt
   while true
   do
    ctrlkey=$(cat ctrl.txt)
    if [ "$ctrlkey" == "s" ]
    then
     fInit
     zhuangtai=$cyzfc
     gameover=0
     break
    fi
    if [ "$ctrlkey" == "e" ]
    then
     fExit
    fi
    sleep 0.2
   done
  fi

  ctrlkey=$(cat ctrl.txt)
  case $ctrlkey in
   l)
    fLeft
   ;;
   r)
    fRight
   ;;
   c)
    fChange
   ;;
   h)
    fDown
   ;;
   d)
    fDownbottom
   ;;
   e)
    fExit
   ;;
   p)
    zhuangtai="暂停中...若要开始请按p"
    fDisplay
    :>ctrl.txt
    while true
    do
     ctrlkey=$(cat ctrl.txt)
     if [ "$ctrlkey" == "p" ]
     then
      zhuangtai=$cyzfc
      :>ctrl.txt
      break
     fi
     sleep 0.2
    done
   ;;
   s)
    zhuangtai="要重新开始游戏吗?(y/n)"
    fDisplay
    :>ctrl.txt
    while true
    do
     ctrlkey=$(cat ctrl.txt)
     if [ "$ctrlkey" == "n" ]
     then
      zhuangtai=$cyzfc
      :>ctrl.txt
      break
     elif [ "$ctrlkey" == "y" ]
     then
      map=(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)
      mapback=(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)
      zongfen=0
      zonghang=0
      dancifen=0
      dangqianhang=0
      qiancihang=0
      dengji=1
      zhuangtai=$cyzfc
      :>ctrl.txt
      break
     fi
     sleep 0.2
    done
    fInit
   ;;
   w)
    zhuangtai="是否要存档?(y/n)"
    fDisplay
    :>ctrl.txt
    while true
    do
     ctrlkey=$(cat ctrl.txt)
     if [ "$ctrlkey" == "n" ]
     then
      zhuangtai=$cyzfc
      break
     elif [ "$ctrlkey" == "y" ]
     then
      :>save.txt
      fSave 
      zhuangtai=$cyzfc
      break
     fi
     sleep 0.2
    done
   ;;  
   a)
    zhuangtai="是否要取档?(y/n)"
    fDisplay
    :>ctrl.txt
    while true
    do
     ctrlkey=$(cat ctrl.txt)
     if [ "$ctrlkey" == "n" ]
     then
      zhuangtai=$cyzfc
      break
     elif [ "$ctrlkey" == "y" ]
     then
      if [ -a save.txt ]
      then
       fLoad
       zhuangtai=$cyzfc
       break
      else
       zhuangtai=$cyzfc
       break
      fi
     fi
     sleep 0.2
    done
   ;;
  esac
  :> ctrl.txt
  if [ $nandutimeflag -eq 1 -a $nandutime -ge $nanduzongtime ]
  then
   fTimenandu
   nandutime=0
  fi
  if [ $downtime -ge $zongtime ]
  then
   fDown
   downtime=0
  fi
  fDisplay
  sleep $sleeptime
  ((downtime++))
  ((nandutime++))
 done
}

fMain  2>debug&
#fMain& 2>/dev/null
fGetKey 

测试

在centos命令行下运行得比较流畅,没有画面闪烁现象,但在centos GNOME界面下终端中运行会有画面闪烁现象

下载链接

代码下载



在这里插入图片描述

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
使用Shell脚本编写俄罗斯方块并不是很方便,因为Shell脚本主要用于自动化任务和系统管理,不是最适合编写游戏的语言。如果您想学习如何用Shell脚本编写俄罗斯方块,我可以给您提供一些指导。 首先,您需要了解Shell脚本的基本语法和命令。然后,您可以使用Shell脚本中的ASCII图形字符来绘制游戏界面,并使用循环和条件语句来控制方块的移动和旋转。还需要使用随机数生成器来随机生成方块。 下面是一个简单的示例代码,该代码使用Shell脚本实现了俄罗斯方块的基本功能: ``` #!/bin/bash # 游戏区域大小 ROWS=20 COLS=10 # 初始化游戏区域 for ((i=0; i<$ROWS; i++)); do for ((j=0; j<$COLS; j++)); do board[$i,$j]='.' done done # 定义方块的形状和颜色 shapes=('O' 'I' 'S' 'Z' 'L' 'J' 'T') colors=('31' '32' '33' '34' '35' '36' '37') # 随机生成方块 shape=${shapes[$((RANDOM % ${#shapes[@]}))]} color=${colors[$((RANDOM % ${#colors[@]}))]} # 方块初始位置 row=0 col=$((($COLS-4)/2)) # 绘制游戏界面 function draw_board() { clear for ((i=0; i<$ROWS; i++)); do for ((j=0; j<$COLS; j++)); do echo -ne "\033[${i};${j}H\033[${colors[@]}m${board[$i,$j]}\033[0m" done done } # 绘制方块 function draw_shape() { for ((i=0; i<4; i++)); do for ((j=0; j<4; j++)); do if [[ ${shape:i*4+j:i*4+j+1} == '*' ]]; then echo -ne "\033[$((${row}+${i}));$((${col}+${j}))H\033[${color}m*\033[0m" fi done done } # 判断方块是否可以向下移动 function can_move_down() { for ((i=0; i<4; i++)); do for ((j=0; j<4; j++)); do if [[ ${shape:i*4+j:i*4+j+1} == '*' ]]; then if [[ $((row+i)) -ge $ROWS || ${board[$((row+i)),$((col+j))]} != '.' ]]; then return 1 fi fi done done return 0 } # 将方块固定在游戏区域中 function fix_shape() { for ((i=0; i<4; i++)); do for ((j=0; j<4; j++)); do if [[ ${shape:i*4+j:i*4+j+1} == '*' ]]; then board[$((row+i)),$((col+j))]=${shape} fi done done } # 消除已经填满的行 function clear_lines() { for ((i=$ROWS-1; i>=0; i--)); do if [[ "${board[$i,$(seq -s , 0 $(($COLS-1)))]}" == *"."* ]]; then continue fi for ((j=i; j>0; j--)); do board[$j]="${board[$((j-1))]}" done for ((j=0; j<$COLS; j++)); do board[0,$j]="." done ((i++)) done } # 主循环 while true; do draw_board draw_shape # 方块可以向下移动则向下移动,否则固定在游戏区域中并生成新方块 if can_move_down; then ((row++)) else fix_shape clear_lines shape=${shapes[$((RANDOM % ${#shapes[@]}))]} color=${colors[$((RANDOM % ${#colors[@]}))]} row=0 col=$((($COLS-4)/2)) fi # 按键控制方块移动和旋转(待实现) done ``` 以上代码只是一个简单的示例,还有很多细节需要根据自己的需求和想象力进行调整和实现。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hongccsdn

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值