当前位置: 技术问答>linux和unix
AIX下工作的选手们辛苦了,来玩会游戏(微雷)
来源: 互联网 发布时间:2016-11-19
本文导语: 代码(snake.sh): #!/usr/bin/ksh ############################################################################# # 程序名: snake.sh # # 时 间: 2011.03.03 ...
代码(snake.sh):
配置(snake.ini):
foodColor=GREEN
wallColor=CYAN
bodyColor=RED
#!/usr/bin/ksh
#############################################################################
# 程序名: snake.sh #
# 时 间: 2011.03.03 #
# 作 者: hiroyukki #
# 用 途: 贪食蛇游戏 #
#############################################################################
# 从 ini 文件里获取配置项
function getProperty {
local INIFILE=$1
local KEY=$2
grep "${KEY}" ${INIFILE} | awk -F= '{print $2}'
}
# 读取程序配置
function getConfig {
if [ ! -f "${CFGFILE}" ]
then
echo "未找到配置文件: ${CFGFILE}"
if [ -f "${SINGLEFILE}" ]
then
rm -f ${SINGLEFILE}
fi
return -1
fi
getProperty ${CFGFILE} "bodyColor" | read color
if [ -z "${color}" ]
then
color=BLACK
fi
case ${color} in
RED)
BDCOLOR=31;;
GREEN)
BDCOLOR=32;;
BLACK)
BDCOLOR=30;;
YELLOW)
BDCOLOR=33;;
CYAN)
BDCOLOR=36;;
*)
echo "Invalid color: ${color}"
return -1
esac
getProperty ${CFGFILE} "foodColor" | read color
if [ -z "${color}" ]
then
color=BLACK
fi
case ${color} in
RED)
FDCOLOR=31;;
GREEN)
FDCOLOR=32;;
BLACK)
FDCOLOR=30;;
YELLOW)
FDCOLOR=33;;
CYAN)
FDCOLOR=36;;
*)
echo "Invalid color: ${color}"
return -1
esac
return 0
}
# 移动到目标坐标并输出第三个参数
function moveTo {
echo "[$1;$2H$3"
}
# 该函数接受3个参数,第一个是下限,第二个是上限,第三个传1生成奇数
function random {
# 如果参数少于3个,返回0
if [ $# -lt 3 ]
then
return 0
fi
curSec=`date "+%M%S" | cut -c3-4`
curMin=`date "+%M%S" | cut -c1-2`
tmp=`expr $2 - $1`
sec=`expr ${curMin} * 60 + ${curSec}`
result=`expr ${sec} % ${tmp}`
result=`expr ${result} + $1 + 1`
# 如果参数3传的是1,则生成奇数
if [ $3 -eq "1" ]
then
tmp=`expr ${result} % 2`
if [ ${tmp} -eq 0 ]
then
result=`expr ${result} - 1`
fi
fi
echo $result
}
# 绘制墙壁
function drawWall {
moveTo 1 1 "■■■■■■■■■■■■■■■■"
for i in 2 3 4 5 6 7 8 9 10 11 12 13 14 15
do
moveTo ${i} 1 "■ ■"
done
moveTo 16 1 "■■■■■■■■■■■■■■■■"
}
# 输出蛇身
function drawBody {
moveTo $1 $2 "[${BDCOLOR}m■[40m[0m"
}
# 画食物
function drawFood {
moveTo $1 $2 "[${FDCOLOR}m■[40m[0m"
}
# 绘制分数
function drawScore {
local SCORE=$1
moveTo 18 13 "[41m得分:${SCORE}[40m[0m"
}
# 绘制死亡通知,这里不用再取SCORE了,能执行至此,前面肯定取过至少一次
# 死亡,其实名字起的不对,应该是结束,包含胜利结束和撞墙(撞自己)结束
# 传参数1表示死亡,0表示胜利
function drawDie {
local REASON=$1
if [ "${REASON}" = "0" ]
then
moveTo 18 6 "[41m您胜利了!您的得分:${SCORE}[40m[0m"
return
fi
moveTo 18 6 "[41m游戏结束,您的得分:${SCORE}[40m[0m"
}
# 退出时通知子进程退出
function onExit {
echo "exit" > ${CTLFILE}
if [ -f "${TMPFILE}" ]
then
rm -f ${TMPFILE} > /dev/null
fi
if [ -f "${DRCTFILE}" ]
then
rm -f ${DRCTFILE} > /dev/null
fi
if [ -f "${SINGLEFILE}" ]
then
rm -f ${SINGLEFILE} > /dev/null
fi
# 让子进程退出的权宜之计……
# 似乎不需要,虽然子进程是后台,但是他爹在活着,杀他爹时他也死?
# 就是说子进程根本来不及清理,因为他没捕获信号,没关系,他爹死前清理就行了
# 事实上,只有用户正常退出(输入Q)后,才会由子进程清理控制文件
echo "等待子进程退出..."
sleep 2
if [ -f "${CTLFILE}" ]
then
rm -f ${CTLFILE} > /dev/null
fi
clear
exit 0
}
# 吃掉一个食物,吃的时候比较简单,就是把食物标志变成身体标志而已,但要放在其他所有
# 身体结点前,因为食物的位置已经是新的头了
function eat {
grep "score" ${CTLFILE} | awk -F':' '{print $2}' | read SCORE
if [ -z "${SCORE}" ]
then
SCORE=0
fi
SCORE=`expr ${SCORE} + 10`
grep "food" ${CTLFILE} > ${TMPFILE}
grep "body" ${CTLFILE} >> ${TMPFILE}
echo "score:${SCORE}" >> ${TMPFILE}
sed 's/food/body/g' ${TMPFILE} > ${CTLFILE}
nextFood
}
# 生成下一个食物,没考虑生成到蛇身上的情况,管它呢
function nextFood {
FOODX=`random 2 15 0`
FOODY=`random 2 28 1`
grep -v "food" ${CTLFILE} > ${TMPFILE}
echo "food:${FOODX}:${FOODY}" >> ${TMPFILE}
cp ${TMPFILE} ${CTLFILE}
}
# 是否在下一步能吃到食物,返回0表示能,返回1表示正常,
# 返回2表示我被自己撞了一下腰或我被石头撞了一下头
function isPieFromSky {
# 取当前蛇头位置,根据方向计算出下一个要走的位置
HEADX=`grep "body" ${CTLFILE} | head -n1 | awk -F':' '{print $2}'`
HEADY=`grep "body" ${CTLFILE} | head -n1 | awk -F':' '{print $3}'`
NEXTX=${HEADX}
NEXTY=${HEADY}
DIRECTION=`cat ${DRCTFILE}`
if [ "${DIRECTION}" = "${UP}" ]
then
NEXTX=`expr ${NEXTX} - 1`
elif [ "${DIRECTION}" = "${LEFT}" ]
then
NEXTY=`expr ${NEXTY} - 2`
elif [ "${DIRECTION}" = "${DOWN}" ]
then
NEXTX=`expr ${NEXTX} + 1`
elif [ "${DIRECTION}" = "${RIGHT}" ]
then
NEXTY=`expr ${NEXTY} + 2`
fi
# X Y都不能越墙,否则是撞
if [ ${NEXTX} -gt 15 -o ${NEXTX} -lt 2 -o ${NEXTY} -gt 30 -o ${NEXTY} -lt 2 ]
then
return 2
fi
# 撞自己了
LINES=`grep "body:${NEXTX}:${NEXTY}" ${CTLFILE} | wc | awk '{print $1}'`
if [ ${LINES} -ne 0 ]
then
return 2
fi
FOODX=`grep "food" ${CTLFILE} | awk -F':' '{print $2}'`
FOODY=`grep "food" ${CTLFILE} | awk -F':' '{print $3}'`
if [ "${NEXTX}" = "${FOODX}" -a "${NEXTY}" = "${FOODY}" ]
then
return 0
fi
return 1
}
# 生成蛇头,初始化调用
function genHead {
grep -v "body" ${CTLFILE} > ${TMPFILE}
echo "body:2:3" >> ${TMPFILE}
cp ${TMPFILE} ${CTLFILE}
}
# 蛇移动,所谓蛇移动,其实是把蛇尾放到蛇头的下一个位置如有10个身体结点
# 则前9个不动,第十个放到第一个的下一个位置,这个位置和方向有关系
# 如此,至少在视觉上,他在移动……
# 这里有个取巧的地方,已知只有在判断是否天上掉馅饼后才做此调用,故可用天上掉馅饼
# 函数中已经得到的数据,如 NEXTX
function goGoGo {
# 先获取身体结点个数
LINES=`grep "body" ${CTLFILE} | wc | awk '{print $1}'`
# 直接生成一个新的放前面
echo "body:${NEXTX}:${NEXTY}" > ${TMPFILE}
HEADLINE=`expr ${LINES} - 1`
grep "body" ${CTLFILE} | head -n${HEADLINE} >> ${TMPFILE}
grep -v "body" ${CTLFILE} >> ${TMPFILE}
cp ${TMPFILE} ${CTLFILE}
}
# 死的时候,杀自己爹,伦理丧失啊,通过杀自己爹,让自己爹清理部分东西,
# 并且自己爹临死时会给自己交待后事
# 我好像理解错误,对函数使用 & 这个函数还是在同一个进程里?也就是说父的说法不成立?
# 其实应该 kill ${PID} 而不是 kill ${PPID}?
# 在AIX下, 两者竟然都通过, redhat下,两者都不能成功杀
# 如果是同一个进程,意思是说,exit就行了?
function die {
drawDie $1
kill -2 $$
}
# 分数过200就算赢了,赢了程序退出,同样杀爹……
function win {
die 0
}
# 这是独立的一个进程,用来检测当前游戏状态并绘制
function moveThread {
# 先生成下一个食物
nextFood
# 生成蛇头
genHead
THREADID=`echo $$`
echo "${RIGHT}" > ${DRCTFILE}
while true
do
# 先查看是否有退出标志
grep "exit" ${CTLFILE} | wc | read LINE DISCARD
if [ "${LINE}" = "1" ]
then
rm -f ${CTLFILE} > /dev/null
return
fi
# 画上墙
drawWall
# 画分数
SCORE=`grep "score" ${CTLFILE} | awk -F':' '{print $2}'`
if [ -z "${SCORE}" ]
then
SCORE=0
fi
drawScore ${SCORE}
if [ ${SCORE} -gt 190 ]
then
win
fi
# 画食物
X=`grep "food" ${CTLFILE} | awk -F':' '{print $2}'`
Y=`grep "food" ${CTLFILE} | awk -F':' '{print $3}'`
if [ -z "${X}" -o -z "${Y}" ]
then
echo "Food not found!"
die
continue
fi
drawFood ${X} ${Y}
# 如果撞上食物,吃!,如果撞上墙,死!否则正常走
isPieFromSky
RETVAL=$?
if [ ${RETVAL} -eq 0 ]
then
eat
elif [ ${RETVAL} -eq 2 ]
then
die
else
goGoGo
fi
# 没死的话,画身体吧
grep "body" ${CTLFILE} | awk -F':' '{print $2" "$3}' | while read X Y
do
drawBody ${X} ${Y}
done
sleep 1
done
}
# 获取当前蛇的前进方向
function getCurDrct {
cat ${DRCTFILE} | read DIRECTION
if [ -z "${DIRECTION}" ]
then
DIRECTION=0
fi
return ${DIRECTION}
}
# 游戏开始
function gameStart {
clear
touch ${CFGFILE} ${CTLFILE} ${DRCTFILE}
moveThread &
# 循环读用户输入来改变蛇的方向,有个需要注意的是,比如,当前方向是右,则不能直接转向左
while true
do
read INPUT
case ${INPUT} in
a|A)
getCurDrct
if [ $? -ne ${RIGHT} ]
then
echo "${LEFT}" > ${DRCTFILE}
fi
;;
s|S)
getCurDrct
if [ $? -ne ${UP} ]
then
echo "${DOWN}" > ${DRCTFILE}
fi
;;
d|D)
getCurDrct
if [ $? -ne ${LEFT} ]
then
echo "${RIGHT}" > ${DRCTFILE}
fi
;;
w|W)
getCurDrct
if [ $? -ne ${DOWN} ]
then
echo "${UP}" > ${DRCTFILE}
fi
;;
q|Q)
onExit;;
*)
continue;;
esac
done
return 0
}
SINGLEFILE=${HOME}/.snake.flag
if [ -f "${SINGLEFILE}" ]
then
echo "已经有一个实例在运行!"
exit 0
fi
touch ${SINGLEFILE}
MAXX=8
MAXY=17
LEFT=1
DOWN=2
RIGHT=3
UP=4
CFGFILE=snake.ini
TMPFILE=.snake.tmp
CTLFILE=.snake.ctl
DRCTFILE=.snake.drct
USER=`whoami`
trap "onExit" 2 3
getConfig
[ $? -ne 0 ] && exit 0
gameStart
配置(snake.ini):
foodColor=GREEN
wallColor=CYAN
bodyColor=RED
|
支持支持
|
支持楼主,这样也能玩
|
好牛x
|
|
那好像只是个网盘~
支持楼主~!~
支持楼主~!~
您可能感兴趣的文章:
本站(WWW.)旨在分享和传播互联网科技相关的资讯和技术,将尽最大努力为读者提供更好的信息聚合和浏览方式。
本站(WWW.)站内文章除注明原创外,均为转载、整理或搜集自网络。欢迎任何形式的转载,转载请注明出处。
本站(WWW.)站内文章除注明原创外,均为转载、整理或搜集自网络。欢迎任何形式的转载,转载请注明出处。