Created
August 3, 2014 15:43
-
-
Save programus/c2dbb5c9f3d6b10a61e0 to your computer and use it in GitHub Desktop.
Hit plane game in shell script
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/sh | |
HIT="X" | |
BLANK="." | |
function printBanner() | |
{ | |
echo "****************************" | |
echo "* PLANE *" | |
echo "****************************" | |
} | |
function generatePlanes() | |
{ # 随机生成飞机位置 | |
local num=$1 | |
if [[ ! -n $num ]] || echo $num | grep '[^0-9]' > /dev/null | |
then | |
num=3 | |
fi | |
# 准备一个池,包含了00-99的所有数字 | |
local pool=($(seq -w 0 99)) | |
unset plane[@] | |
for ((i = 0; i < $num; i++)) | |
do | |
# 随机抽取一个数字作为飞机坐标 | |
let local pick=${RANDOM}%${#pool[@]} | |
local plane[$i]=${pool[$pick]} | |
# 删除抽取走的数字,重新构建池 | |
pool=(${pool[@]:0:$pick} ${pool[@]:$((pick+1))}) | |
done | |
echo ${plane[@]} | |
} | |
function generateSky() | |
{ # 生成空白天空 | |
yes $BLANK|head -100|tr '\n' ' ' | |
} | |
function getIndex() | |
{ # 根据二维坐标计算一维数组序号 | |
if [[ -n $3 ]] | |
then | |
local w=$3 | |
else | |
local w=10 | |
fi | |
local x=$1 | |
local y=$2 | |
echo $((x+y*w)) | |
} | |
function showSky() | |
{ # 显示天空状况 | |
local sky=($*) | |
# 打印y坐标值 | |
echo " $(seq 0 9|tr '\n' ' ')" | |
# 打印分割线 | |
echo " +$(yes "-"|head -19|tr -d '\n')+" | |
for y in $(seq 0 9) | |
do | |
for x in $(seq 0 9) | |
do | |
# 取得每行数据 | |
local i=$(getIndex $x $y) | |
local line[$x]=${sky[$i]} | |
done | |
# 打印每行内容 | |
printf "$y |%s|\n" "${line[*]}" | |
done | |
# 打印分割线 | |
echo " +$(yes "-"|head -19|tr -d '\n')+" | |
} | |
function split2Char() | |
{ # 将字符串分离为空格分隔的字符 | |
echo $*|sed 's/./& /g' | |
} | |
function isValidPosition() | |
{ # 检查位置信息是否合法 | |
# 必须为两个一位数 | |
[[ $# -eq 2 ]] && echo $*|grep '^[0-9] [0-9]$' > /dev/null | |
} | |
function readPosition() | |
{ # 从stdin读取坐标数据,数据合法时返回坐标数据 | |
read -p 'You hit: ' input | |
local pos=$(split2Char $input) | |
isValidPosition $pos && echo $pos | |
} | |
function abs() | |
{ | |
local result=$1 | |
if [[ $1 -lt 0 ]] | |
then | |
result=$((-result)) | |
fi | |
echo $result | |
} | |
function updateSky() | |
{ # 更新天空数据 | |
local x=${101} | |
local y=${102} | |
local sky=($(echo $*|cut -d ' ' -f 1-100)) | |
local planes=($(echo $*|cut -d ' ' -f 103-)) | |
local i=$(getIndex $x $y) | |
local index=0 | |
for plane in ${planes[@]} | |
do | |
# 抽取飞机坐标 | |
local px=${plane:0:1} | |
local py=${plane:1:2} | |
# 计算距离:距离=max(dx, dy) | |
local distance[$((index++))]=$(echo $(abs $((px-x))) $(abs $((py-y)))|tr ' ' '\n'|sort -n|tail -1) | |
done | |
# 取得最近飞机距离 | |
local r=$(echo ${distance[@]}|tr ' ' '\n'|sort -n|head -1) | |
if [[ r -eq 0 ]] | |
then | |
r=$HIT | |
fi | |
sky[$i]=$r | |
echo ${sky[@]} | |
} | |
function game() | |
{ # 开始一次游戏 | |
# 从参数取得飞机数,默认为3 | |
if [[ -n $1 ]] && echo $1|grep '^[0-9]\{1,2\}$' > /dev/null | |
then | |
local num=$1 | |
else | |
local num=3 | |
fi | |
local planes=$(generatePlanes $num) | |
local sky=$(generateSky) | |
local step=0 | |
# 要羞辱中途退出的懦夫 | |
trap 'echo;echo "You lose because you aborted!";exit' INT | |
# 正式开始游戏,给出信息提示 | |
echo "There are $num planes. " | |
echo "Shoot them down!" | |
while [[ 1 = 1 ]] | |
do | |
((step++)) | |
showSky ${sky} | |
printf "[%3d]" $step | |
# 让玩家输入坐标 | |
until pos=$(readPosition) | |
do | |
# 格式错误时给出提示 | |
echo "Position format wrong!" | |
echo "Please input a valid position in format x y." | |
done | |
# 输出分割线 | |
echo $(yes "="|head -23|tr -d '\n') | |
# 根据玩家输入更新天空信息 | |
sky=$(updateSky $sky $pos $planes) | |
# 统计击落飞机数 | |
hitCount=$(echo $sky|tr ' ' '\n'|grep -c $HIT) | |
if [[ hitCount -eq $num ]] | |
then | |
# 全部击落时,宣告胜利 | |
showSky ${sky} | |
echo "You Win after $step steps!" | |
break | |
fi | |
done | |
trap - INT | |
} | |
printBanner | |
until [[ $exit ]] | |
do | |
game $1 | |
echo "-----" | |
select sel in "Play again?" "Exit" | |
do | |
case $sel in | |
Exit) | |
exit=1 | |
break;; | |
*) | |
echo "=====" | |
break;; | |
esac | |
done | |
done | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment