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