当前位置: 代码迷 >> AIX >> AIX下工作的选手们辛苦了,来玩会游戏(微雷)解决办法
  详细解决方案

AIX下工作的选手们辛苦了,来玩会游戏(微雷)解决办法

热度:3194   发布时间:2013-02-26 00:00:00.0
AIX下工作的选手们辛苦了,来玩会游戏(微雷)
代码(snake.sh):
Perl code
#!/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■"}# 画食物function drawFood {    moveTo $1 $2 "[${FDCOLOR}m■"}# 绘制分数function drawScore {    local SCORE=$1    moveTo 18 13 "得分:${SCORE}"}# 绘制死亡通知,这里不用再取SCORE了,能执行至此,前面肯定取过至少一次# 死亡,其实名字起的不对,应该是结束,包含胜利结束和撞墙(撞自己)结束# 传参数1表示死亡,0表示胜利function drawDie {    local REASON=$1    if [ "${REASON}" = "0" ]    then        moveTo 18 6 "您胜利了!您的得分:${SCORE}"        return    fi    moveTo 18 6 "游戏结束,您的得分:${SCORE}"}# 退出时通知子进程退出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个不动,第十个放到第一个的下一个位置,这个位置和方向有关系# 如此,至少在视觉上,他在移动……# 这里有个取巧的地方,已知只有在判断是否天上掉馅饼后才做此调用,故可用天上掉馅饼# 函数中已经得到的数据,如 NEXTXfunction 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.flagif [ -f "${SINGLEFILE}" ]then    echo "已经有一个实例在运行!"    exit 0fitouch ${SINGLEFILE}MAXX=8MAXY=17LEFT=1DOWN=2RIGHT=3UP=4CFGFILE=snake.iniTMPFILE=.snake.tmpCTLFILE=.snake.ctlDRCTFILE=.snake.drctUSER=`whoami`trap "onExit" 2 3getConfig[ $? -ne 0 ] && exit 0gameStart
  相关解决方案