shell实现贪吃蛇的示例代码

 更新时间:2023年05月09日 09:42:47   作者:不识君  
本文主要介绍了shell实现贪吃蛇的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

前言

这是几年前刚接触shell,用bash shell写的一个贪吃蛇。刚才看见了,试了一下之前写的代码,在mac os上效果不在理想,放到linux服务器,看起来运行着还行。

给大家再分享一下。

下面是我当时发的时候写的背景信息,我就不改了,直接粘过来了。

背景

最近想系统看下base shell的基本语法知识,可是看了这些if else之后还是不知道做什么就想到写了个贪吃蛇,我还以为我是第一个想到用shell写贪吃蛇的呢,可是后来看到已经有人写过了,不过我也是懒的看别人代码的人,所以就用自己的思路实现了下,熟练下这些基本的shell语法。

写这个重点是想练习下shell语法,所以贪吃蛇的实现算法倒不是重点,况且以前大学的时候各类小游戏用什么语言都写过,这些小算法如果不考虑性能确实没什么意思。

当然了贪吃蛇最好用的数据结构自然是stack,可是我真的不想花时间考虑用shell实现一个栈,所以就用一个静态的一维数组和一个动态的一维数组实现的(shell中的数组本来就是动态的,我这样说只是说我的实现的效果是这样)。

环境

win10内嵌的Linux beta版本(ubuntu14.0)带的bash

如果有小伙伴复制下面代码跑不动,请考虑下运行环境。

源码

下面的中文注释是刚才添加的,用的这个bash是不支持中文的,我的英文真的比较烂,所以刚才把中文注释加了下

玩的时候使用上下左右键就行(本想用hjkl这四键控制上下左右的,觉得不太习惯)

主要思路就是:贪吃蛇运行界面使用一个后台进程,用另一个进程来监听输入(我最初的想法是一个shell进程就行,在贪吃蛇运行中的等待时间来监听输入,后来发现还有这种玩法,我就改用这种实现,通过传递一个信号来处理)

#! /bin/bash
#下面是游戏界面的宽和高
# the width
with=42
# the height
height=22
#这个是游戏运行区域
# area
area=(
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 9
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 9
)
#bool
false=0
true=1
#贪吃蛇的一些信息
#snake info
head=47
tail=45
originPos=(45 46 47)
snakeBody=2
snakeFood=3
curPos=(${originPos[*]})
#game logic val
speed=0.2
foodPos=50
left=2
right=-2
up=3
down=-3
moveDirection=$right
eat=$true
#game info
side=$$
main=$!
#这个是开始时的界面
#start show interface
function startShowInterface()
{
    seconds=$1
    printf "\e[1;42m"
    printf "******************************************\n"
    for ((i=0; i<10; i++))
    do
        printf "*                                        *\n"
    done
    printf "*******\e[1;31msnake start after: $seconds seconds\e[0m\e[1;42m*******\n"
    for ((i=0; i<10; i++))
    do
        printf "*                                        *\n"
    done
    printf "******************************************\n"
    printf "\e[0m"
}
#start show 
function startShow()
{
    seconds=1;
    while [[ $seconds -gt -1 ]];
    do
        clear;
        startShowInterface $seconds;
        sleep 1;
        let seconds--;
    done
}
startShow;
#这个是游戏显示界面
# game main inteface
function gameMainInterface
{
    clear;
    pos=0
    echo -e "\e[1;42m"
    for data in ${area[@]};
    do
        case $data in
        [9])
            printf "\n"
        ;;
        [1])
            printf "#"
        ;;
        [0])
            printf " "
        ;;
        [$snakeBody])
            printf "\e[1;31m"
            if [[ $pos = $head ]]; then
                printf "@"
            else
                printf "*"
            fi
            printf "\e[0m\e[1;42m"
        ;;
        [$snakeFood])
            printf "\e[1;34m&\e[0m\e[1;42m"
        ;;
        esac
        let pos++
    done
    echo -e "\e[0m"
}
#initinal snake body and pos
function initSnake()
{
    for data in ${originPos[@]};
    do
        area[$data]=$snakeBody
    done
}
initSnake;
#绘制贪吃蛇
#draw snake
function drawSnake()
{
    for data in ${originPos[@]};
    do
        area[$data]=0
    done
    for data in ${curPos[@]};
    do
        area[$data]=$snakeBody
    done
}
#随机生成食物位置
#generate food
function generateFood()
{
    if [[ $eat = $false ]]; then
        return
    fi
    done=$false
    while [[ $done = $false ]];
    do
        newFoodPos=$(( RANDOM%$(( $(( $with-1 ))*$(( $height-1 )) )) ))
        [[ ${area[$newFoodPos]} = 0 ]] && area[$foodPos]=0 && foodPos=$newFoodPos && (( area[$foodPos]=$snakeFood )) && done=$true && eat=$false
    done
}
#贪吃蛇移动的算法,用的一维数组,我也就这样来实现了
#move
function snakeMove()
{
    originPos=(${curPos[*]})
    length=${#curPos[*]}
    head=${curPos[$(( $length-1 ))]}
    case $moveDirection in
    $left)
        let head--
        [[ $(( $(( $head-2 ))%$with )) -eq 0 ]] && kill -35 $side
    ;;
    $right)
        let head++
        [[ $(( $head%$with )) -eq 0 ]] && kill -35 $side
    ;;
    $up)
        let head=head-with
        let head--
        [[ $head -lt $with ]] && kill -35 $side
    ;;
    $down)
        let head=head+with
        let head++
        [[ $head -gt $(( $with*$(( $height-1 )) )) ]] && kill -35 $side
    ;;
    esac
    if [[ $head -eq $foodPos ]];    then
        curPos[length]=$head
        eat=$true
    else
        for ((i=0; i<$((length-1)); i++));
        do
            curPos[i]=${curPos[$((i+1))]}
        done
        curPos[$((length-1))]=$head
    fi
}
#游戏运行的进程,游戏主逻辑都在这里了
#main interface
function mainInterface
{
    trap "moveDirection=$left" 36
    trap "moveDirection=$right" 37
    trap "moveDirection=$up" 38
    trap "moveDirection=$down" 39
    run=$true
    while [[ $run -eq $true ]];
    do
        generateFood;
        snakeMove;
        drawSnake;
        clear;
        gameMainInterface;
        sleep $speed
    done
}
mainInterface &
main=$!
# move snake
function moveDirectionUpdate()
{
    if [[ $(( $1+$2 )) -eq 0 || $1 -eq $2 ]];then   
        return;
    fi
    case $2 in
    $left)
        kill -36 $main
    ;;
    $right)
        kill -37 $main
    ;;
    $up)
        kill -38 $main
    ;;
    $down)
        kill -39 $main
    ;;
    esac
}
#监听上下左右键的输入
#watch input
function watchInput()
{
    curDirection=$left
    preDirection=$curDirection
    while :;
    do
        read -s -n 1 op;
        [[ $op = "q" ]] && kill -9 $! && return;
        [[ $op = "A" ]] && preDirection=$curDirection && curDirection=$up && moveDirectionUpdate $preDirection $curDirection;
        [[ $op = "B" ]] && preDirection=$curDirection && curDirection=$down && moveDirectionUpdate $preDirection $curDirection;
        [[ $op = "C" ]] && preDirection=$curDirection && curDirection=$right && moveDirectionUpdate $preDirection $curDirection;
        [[ $op = "D" ]] && preDirection=$curDirection && curDirection=$left && moveDirectionUpdate $preDirection $curDirection;
    done
}
watchInput;
#game over
function gameOver()
{
    kill -9 $main
    echo "game over."
}
trap "gameOver" 35

到此这篇关于shell实现贪吃蛇的示例代码的文章就介绍到这了,更多相关shell 贪吃蛇内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家! 

相关文章

  • linux中ps -ef和ps -aux的区别

    linux中ps -ef和ps -aux的区别

    ps -ef和ps -aux均为Linux中的ps命令,是Process Status的缩写,ps命令用来列出系统中当前运行的那些进程,这篇文章主要介绍了linux中ps -ef和ps -aux的区别,需要的朋友可以参考下
    2023-10-10
  • Linux/Nginx如何查看搜索引擎蜘蛛爬虫的行为

    Linux/Nginx如何查看搜索引擎蜘蛛爬虫的行为

    本文给大家介绍Linux/Nginx如何查看搜索引擎蜘蛛爬虫的行为,清楚蜘蛛的爬行情况对做SEO优化有很大的帮助。需要的朋友通过本篇文章学习下吧
    2015-10-10
  • 详解Linux 中五个重启命令

    详解Linux 中五个重启命令

    这篇文章给大家介绍了linux中的五个重启命名及重启命令的具体说明,需要的朋友参考下吧
    2017-03-03
  • shell编程基础之认识与学习BASH

    shell编程基础之认识与学习BASH

    本文介绍下,shell基础编程中有关bash的相关知识,有需要的朋友参考学习下
    2013-11-11
  • linux shell 中 2>&1的含义

    linux shell 中 2>&1的含义

    对于&1 更准确的说应该是文件描述符 1,而1 一般代表的就是STDOUT_FILENO,实际上这个操作就是一个dup2(2)调用
    2013-02-02
  • Linux shell知识点汇总

    Linux shell知识点汇总

    从程序员的角度来看, Shell本身是一种用C语言编写的程序,从用户的角度来看,Shell是用户与Linux操作系统沟通的桥梁。用户既可以输入命令执行,又可以利用 Shell脚本编程,完成更加复杂的操作。
    2015-08-08
  • 解决centos7 开机/etc/rc.local 不执行的问题

    解决centos7 开机/etc/rc.local 不执行的问题

    下面小编就为大家带来一篇解决centos7 开机/etc/rc.local 不执行的问题。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-03-03
  • 利用shell获取指定日期前N天的日期

    利用shell获取指定日期前N天的日期

    最近因为项目的需要对比2015年10月的数据,因为一年来的数据经过了很多次调整和处理,遇到的最直接的问题是很多数据需要重新计算。只好写脚本刷数据。在准备脚本的过程中,就需要根据给定的日期处理数据,所以就有了这篇文章,下面有需要的朋友们一起学习学习。
    2016-11-11
  • Linux shell 获得字符串所在行数及位置的方法

    Linux shell 获得字符串所在行数及位置的方法

    这篇文章主要介绍了Linux shell 获得字符串所在行数及位置的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-08-08
  • linux下实现ftp自动备份shell脚本

    linux下实现ftp自动备份shell脚本

    ftp命令把远程计算机上的文件传输到本地计算机时,需要和用户交互。怎样使交互过程自动化呢
    2013-01-01

最新评论