preface

This is a gluttonous snake written by bash shell a few years ago. I just saw it. I tried the code I wrote earlier. It didn’t work well on MAC OS.

Let me share with you one more time.

Below is the background information I wrote when I posted it, so I didn’t change it and just pasted it in.

background

Recently, I wanted to systematically read the basic syntax of base shell, but AFTER reading these if and else, I still didn’t know what to do, so I thought of writing snake. I thought I was the first one who thought of writing Snake with shell, but later I saw that someone had already written snake, but I am also lazy to read others’ code. So I used my own ideas to achieve the next, proficient in these basic shell syntax.

Write this focus is to practice the shell grammar, so the implementation of snake algorithm is not the focus, and before the university of all kinds of small games in what language have written, these small algorithms if not considering the performance is really not interesting.

Of course, the best data structure to use is the stack, but I really didn’t want to spend time thinking about implementing a stack in shell, so I used a static one-dimensional array and a dynamic one-dimensional array. (Arrays in shell are dynamic by nature, I’m just saying that my implementation is like this.)

The environment

Windows 10 Embedded Linux Beta (Ubuntu14.0) with bash

If you can’t copy the following code, please consider the runtime environment.

The source code

The following Chinese annotation was added just now, the bash I used does not support Chinese, my English is really poor, so I added the Chinese annotation just now

Use the up and down keys when playing (I want to use the HJKL four keys to control the up and down keys, feel not used to)

The main idea is: Snake interface uses a background process and another process to listen for input (my initial idea was a shell process to listen for input while snake is running, but later I found that there is still a way to do this, SO I switched to this implementation and sent a signal to process).

#! /bin/bash

#Below is the width and height of the game interface
# the width
with=42
# the height
height=22
#This is the game run area
# areaarea=( 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 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 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

#Some information about the snake
#snake info
head=47
tail=45
originPos=(45 46 47)
snakeBody=2
snakeFood=3
curPos=(${originPos[*]})

#game logic valSpeed =0.2 foodPos=50 left=2 right=-2 up=3 down=-3 moveDirection=$right eat=$true
#game info
side=$$
main=$!

#So this is the initial interface
#start show interfacefunction 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;

#This is the game display
# game main intefacefunction 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 the snake
#draw snake
function drawSnake()
{
    for data in ${originPos[@]};
    do
        area[$data]=0
    done
    for data in ${curPos[@]};
    do
        area[$data]=$snakeBody
    done
}

#Randomly generate food locations
#generate foodfunction 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 }
#Snake moving algorithm, with a one-dimensional array, I also so to achieve
#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
    
}

#The progression of the game, the main logic of the game is all there
#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 snakefunction 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 }
#Monitor the input of the left and right keys
#watch inputfunction 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
Copy the code