shell實(shí)現(xiàn)貪吃蛇的示例代碼
前言
這是幾年前剛接觸shell,用bash shell寫(xiě)的一個(gè)貪吃蛇。剛才看見(jiàn)了,試了一下之前寫(xiě)的代碼,在mac os上效果不在理想,放到linux服務(wù)器,看起來(lái)運(yùn)行著還行。
給大家再分享一下。
下面是我當(dāng)時(shí)發(fā)的時(shí)候?qū)懙谋尘靶畔?,我就不改了,直接粘過(guò)來(lái)了。
背景
最近想系統(tǒng)看下base shell的基本語(yǔ)法知識(shí),可是看了這些if else之后還是不知道做什么就想到寫(xiě)了個(gè)貪吃蛇,我還以為我是第一個(gè)想到用shell寫(xiě)貪吃蛇的呢,可是后來(lái)看到已經(jīng)有人寫(xiě)過(guò)了,不過(guò)我也是懶的看別人代碼的人,所以就用自己的思路實(shí)現(xiàn)了下,熟練下這些基本的shell語(yǔ)法。
寫(xiě)這個(gè)重點(diǎn)是想練習(xí)下shell語(yǔ)法,所以貪吃蛇的實(shí)現(xiàn)算法倒不是重點(diǎn),況且以前大學(xué)的時(shí)候各類小游戲用什么語(yǔ)言都寫(xiě)過(guò),這些小算法如果不考慮性能確實(shí)沒(méi)什么意思。
當(dāng)然了貪吃蛇最好用的數(shù)據(jù)結(jié)構(gòu)自然是stack,可是我真的不想花時(shí)間考慮用shell實(shí)現(xiàn)一個(gè)棧,所以就用一個(gè)靜態(tài)的一維數(shù)組和一個(gè)動(dòng)態(tài)的一維數(shù)組實(shí)現(xiàn)的(shell中的數(shù)組本來(lái)就是動(dòng)態(tài)的,我這樣說(shuō)只是說(shuō)我的實(shí)現(xiàn)的效果是這樣)。
環(huán)境
win10內(nèi)嵌的Linux beta版本(ubuntu14.0)帶的bash
如果有小伙伴復(fù)制下面代碼跑不動(dòng),請(qǐng)考慮下運(yùn)行環(huán)境。
源碼
下面的中文注釋是剛才添加的,用的這個(gè)bash是不支持中文的,我的英文真的比較爛,所以剛才把中文注釋加了下
玩的時(shí)候使用上下左右鍵就行(本想用hjkl這四鍵控制上下左右的,覺(jué)得不太習(xí)慣)
主要思路就是:貪吃蛇運(yùn)行界面使用一個(gè)后臺(tái)進(jìn)程,用另一個(gè)進(jìn)程來(lái)監(jiān)聽(tīng)輸入(我最初的想法是一個(gè)shell進(jìn)程就行,在貪吃蛇運(yùn)行中的等待時(shí)間來(lái)監(jiān)聽(tīng)輸入,后來(lái)發(fā)現(xiàn)還有這種玩法,我就改用這種實(shí)現(xiàn),通過(guò)傳遞一個(gè)信號(hào)來(lái)處理)
#! /bin/bash #下面是游戲界面的寬和高 # the width with=42 # the height height=22 #這個(gè)是游戲運(yùn)行區(qū)域 # 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=$! #這個(gè)是開(kāi)始時(shí)的界面 #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; #這個(gè)是游戲顯示界面 # 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 } #隨機(jī)生成食物位置 #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 } #貪吃蛇移動(dòng)的算法,用的一維數(shù)組,我也就這樣來(lái)實(shí)現(xiàn)了 #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 } #游戲運(yùn)行的進(jìn)程,游戲主邏輯都在這里了 #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 } #監(jiān)聽(tīng)上下左右鍵的輸入 #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
到此這篇關(guān)于shell實(shí)現(xiàn)貪吃蛇的示例代碼的文章就介紹到這了,更多相關(guān)shell 貪吃蛇內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
shell參數(shù)換行與shell輸出換行的方法實(shí)例
這篇文章主要給大家介紹了關(guān)于shell參數(shù)換行與shell輸出換行的方法實(shí)例,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2023-02-02Shell腳本定時(shí)備份清除運(yùn)行系統(tǒng)日志的代碼
寫(xiě)備份并清除老日志Shell腳本,并附帶一個(gè)清除日志(log)的shell腳本代碼,需要的朋友可以參考下2013-02-02linux shell腳本對(duì)未定義變量的判斷以及if的用法詳解
今天小編就為大家分享一篇linux shell腳本對(duì)未定義變量的判斷以及if的用法詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-07-07linux shell 邏輯運(yùn)算符、邏輯表達(dá)式詳細(xì)介紹
shell的邏輯運(yùn)算符 涉及有以下幾種類型,因此只要適當(dāng)選擇,可以解決我們很多復(fù)雜的判斷,達(dá)到事半功倍效果2014-02-02linux上配置jdk時(shí),java命令提示沒(méi)有此文件或文件夾的解決方法
下面小編就為大家?guī)?lái)一篇linux上配置jdk時(shí),java命令提示沒(méi)有此文件或文件夾的解決方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-05-05Shell中實(shí)現(xiàn)字符串反轉(zhuǎn)方法分享
這篇文章主要介紹了Shell中實(shí)現(xiàn)字符串反轉(zhuǎn)方法分享,本文同時(shí)提供了多種語(yǔ)言的實(shí)現(xiàn)方法,如awk、python、bash、C語(yǔ)言等,需要的朋友可以參考下2014-12-12通過(guò)Spring Shell 開(kāi)發(fā) Java 命令行應(yīng)用
這篇文章主要介紹了通過(guò)Spring Shell 開(kāi)發(fā) Java 命令行應(yīng)用的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2017-11-11