首页 > 代码库 > bash版2048

bash版2048

bash 脚本小游戏 2048 

通过方向键玩游戏 q键退出 不支持撤销操作 不判断游戏是否game over (玩家自觉按q键退出)

默认4x4矩阵 可通过命令行参数(第1个参数)设置为NxN矩阵  (4<=N && N<=9)

#!/bin/bash
set -e

N=${1:-4}
(( 3 < N && N < 10 )) || exit

do_exit() {
  echo -ne "\e[?1049l"
  exit
}

init_draw() {
  echo -ne "\e[?1049h"

  stty -echo
  echo -ne "\e[?25l"
  trap ‘stty echo; echo -ne "\e[?25h"‘ exit

  trap do_exit INT
}

skip() {
  local a=($*)
  local j=0
  local i

  for ((i=0; i<N; i++)); do
    if ((a[i] != 0)); then
      echo ${a[i]}
      ((++j))
    fi
  done

  for ((; j<N; j++)); do
    echo 0
  done
}

merge() {
  local a=($*)
  local j=0
  local i

  for ((i=0; i<N; i++)); do
    if ((i!=N-1 && a[i]==a[i+1])); then
      echo $((a[i] * 2))
      ((++i))
      ((++j))
    else
      echo ${a[i]}
    fi
  done

  for ((; j>0; j--)); do
    echo 0
  done
}

move() {
  local a=($*)
  local i

  for ((i=0; i<N; i++)); do
    local list=
    for ((j=0; j<N; j++)); do
      list="$list ${a[i*N+j]}" 
    done
    merge $(skip $list)
  done
}

rotate_left() {
  local a=($*)
  local i
  local j

  for ((i=N-1; i>=0; i--)); do
    for ((j=0; j<N; j++)); do
      echo ${a[N*j+i]}
    done
  done
}

rotate_right() {
  local a=($*)
  local i
  local j

  for ((i=0; i<N; i++)); do
    for ((j=N-1; j>=0; j--)); do
      echo ${a[N*j+i]}
    done
  done
}

flip() {
  local a=($*)
  local i
  local j

  for ((i=0; i<N; i++)); do
    for ((j=N-1; j>=0; j--)); do
      echo ${a[N*i+j]}
    done
  done
}

add() {
  local a=($*)
  local j=0
  local i

  for ((i=0; i<N*N; i++)); do
    ((a[i] || ++j))
  done

  while ((j != 0)); do
    i=$((RANDOM % (N*N)))
    if ((a[i] == 0)); then
      a[i]=$((RANDOM % 10 ? 2 : 4))
      j=0
    fi
  done

  echo ${a[*]} 
}

matrix=

init_matrix() {
  local s=
  local i

  for ((i=0; i<N*N; i++)); do
    s="$s 0"
  done

  matrix=$(add $s)
}

draw() {
  local a=($*)
  local i
  local j
  local k

  printf "\e[2J\e[1;1H\n"

  for ((i=0; i<N; i++)); do
    for ((k=0; k<3; k++)); do
      for ((j=0; j<N; j++)); do
        local v=${a[i*N+j]}

        if ((v==0)); then
          printf " "
        elif ((v==2 || v==32 || v==512)); then
          printf " \e[46;37;1m"
        elif ((v==4 || v==64 || v==1024)); then
          printf " \e[42;37;1m"
        elif ((v==8 || v==128)); then
          printf " \e[44;37;1m"
        elif ((v==16 || v==256)); then
          printf " \e[45;37;1m"
        else
          printf " \e[41;37;1m"
        fi

        if ((k==1 && v!=0)); then
          if ((v > 99)); then
            printf "  %-5s\e[0m" $v
          else
            printf "   %-4s\e[0m" $v
          fi
        else
          printf "       \e[0m"
        fi
      done
      printf "\n"
    done
    printf "\n"
  done
}

draw2() {
  draw $*
  sleep 0.1
  matrix=$(add $*)
  draw $matrix
}

left() {
  draw2 $(move $matrix)
}

right() {
  draw2 $(flip $(move $(flip $matrix)))
}

up() {
  draw2 $(rotate_right $(move $(rotate_left $matrix)))
}

down() {
  draw2 $(rotate_left $(move $(rotate_right $matrix)))
}

init_matrix
init_draw
draw $matrix

while true; do
  read -n1 C
  case $C in
    A) up; ;;
    B) down; ;;
    C) right; ;;
    D) left; ;;
    q) do_exit; ;;
  esac
done


bash版2048