Topic
[App Sharing] shell小脚本游戏——贪食蛇
Tofloor
poster avatar
callcz
deepin
2022-07-28 13:11
Author

载图:

Screenshot_20220728_203117.jpg

截图:

Screenshot_20220728_203155.jpg


https://github.com/callcz/a-shell-snake-game

./play.sh开始游戏

./play.sh --help 帮助

数字小键盘控制方向,跟诺基亚一样

Q键退出,T键是测试信号,信号不正常将退出(测试专用)

已知问题:

1.在电脑上用数字小键盘操控方向,如果上下方向方向相反需用--turn或-t参数:./play.sh -t

2.mian_gen_snake.sh文件名修改后程序不能运行

3.由于是字符游戏,所以在终端中使用某些字体会导致画面不正常


代码:

main_gen_snake.sh

#!/bin/bash
##
## This is a snake game ,
## Written by callcz in 20220719 .
## Use the number keys to control the direction .
## Use play.sh to play

if [[ $1 = '--turn' || $1 = '-t' ]]
then
	turn=1
fi

##Catch terminal size
while [[ `stty size` == '0 0' ]]
do
	echo -n 'witting stty size'
done
#tty_xy=(`stty size`)
#tty_x=${tty_xy[1]}
#tty_y=${tty_xy[0]}

##Declare global variables
#echo $$ > m_snake.log
logo_head=■
logo_background=□
logo_body=●
logo_star=★
x_max=20
#if [[ $x_max -gt $tty_x ]];then x_max=$tty_x;fi
y_max=20
#if [[ $y_max -gt $tty_y ]];then y_max=$tty_y;fi
score=0
go=right
##catch key
sig_ul=21
sig_ur=22
sig_dl=23
sig_dr=24
sig_up=25
sig_down=26
sig_left=27
sig_right=28
sig_handshake=29
my_exit=10

trap 'key=2' $sig_up
trap 'key=8' $sig_down
trap 'key=4' $sig_left
trap 'key=6' $sig_right
trap 'key=1' $sig_ul
trap 'key=3' $sig_ur
trap 'key=7' $sig_dl
trap 'key=9' $sig_dr
trap 'kill -12 $2' $sig_handshake
trap 'my_exit_l' $my_exit

get_key_l(){
#	speed_s=$speed
#	if [[ ${#speed_s} -lt 4 ]]
#	then
#		for i in `seq 1 $((4-${#speed_s}))`
#		do
#			speed_s=0$speed_s
#		done
#	speed_s=${speed:0:$((${#speed}-3))}.${speed:0-3}
#	fi
#	while [[ ! $go_w && $((time_old+speed)) -ge $((`date +%s%N`/1000000)) ]]
#	do
#		read -s -t "$speed_s" -n 1 key
		if [[ $turn = 1 ]]
		then
			case $key in
				2)
					key=8
					;;
				8)
					key=2
					;;
				1)
					key=7
					;;
				3)
					key=9
					;;
				7)
					key=1
					;;
				9)
					key=3
					;;
			esac
		fi
		case $key in
			2)
				if [[ $go != down ]];then go_w=up;fi
				;;
			8)
				if [[ $go != up ]];then go_w=down;fi
				;;
			4)
				if [[ $go != right ]];then go_w=left;fi
				;;
			6)
				if [[ $go != left ]];then go_w=right;fi
				;;
			1)
				if [[ $go = up || $go = down ]];then go_w=left
				elif [[ $go = left || $go = right ]];then go_w=up;fi
				;;
			3)
				if [[ $go = up || $go = down ]];then go_w=right
				elif [[ $go = left || $go = right ]];then go_w=up;fi
				;;
			7)
				if [[ $go = up || $go = down ]];then go_w=left
				elif [[ $go = left || $go = right ]];then go_w=down;fi
				;;
			9)
				if [[ $go = up || $go = down ]];then go_w=right
				elif [[ $go = left || $go = right ]];then go_w=down;fi
				;;
		esac
		key=null
#	done
}
##open a terminal
#施工中

##some function
my_exit_l(){
echo -e '\033[?25h'
exit
}
cls_l(){
echo -e '\033c'
echo -e '\033[?25l'
}
cls_l
#backgrond
backgrond_l(){
for i in `seq 1 $((x_max*y_max))`;do
	field_x=$((i%x_max))
	if [[ $field_x -eq 0 ]];then
		field_x=$x_max
	fi
	field_y=$(($(($((i-1))/x_max))+1))
	echo -ne "\033[${field_y};${field_x}H${logo_background}"
done
}
#star point
star_l(){
	star_x=$[RANDOM%$x_max+1]
	star_y=$[RANDOM%$y_max+1]
	star_xy="$star_x,$star_y"
	for i in ${body_xy[@]}
	do
		if [[ $star_xy == $i ]]
		then
		star_l
		fi
	done
	echo -ne "\033[${star_y};${star_x}H${logo_star}"
}
#print something
printf_l(){
	printf "\033[$1;$2H""$3"
}
score_l(){
	if [[ $head_xy = $star_xy ]];then
		score=$((score+1))
		if [[ $speed -gt 100 ]]
		then
			speed=$((speed*95/100))
			if [[ $speed -lt 100 ]]
			then
				speed=100
			fi
		fi
		star_l
	fi
}
#snake go
head_x=$[RANDOM%$x_max+1]
head_y=$[RANDOM%$y_max+1]
head_xy="$head_x,$head_y"
snake_l(){
	body_x=($head_x ${body_x[@]})
	body_y=($head_y ${body_y[@]})
		body_x_d=(${body_x[@]:0:$((score+1))})
		body_y_d=(${body_y[@]:0:$((score+1))})
			body_x_d=${body_x_d[@]:0-1:1}
			body_y_d=${body_y_d[@]:0-1:1}
		body_x=(${body_x[@]:0:$score})
		body_y=(${body_y[@]:0:$score})
	body_xy=($head_xy ${body_xy[@]})
	body_xy=(${body_xy[@]:0:$score})
	if [[ $go_w ]]
	then
		go=$go_w
		unset go_w
	fi
		case $go in
			up)
				head_y=$((head_y-1))
				;;
			down)
				head_y=$((head_y+1))
				;;
			left)
				head_x=$((head_x-1))
				;;
			right)
				head_x=$((head_x+1))
				;;
		esac
	if [[ $head_x -lt 1 ]];then head_x=$x_max
	elif [[ $head_x -gt $x_max ]];then head_x=1
	elif [[ $head_y -lt 1 ]];then head_y=$y_max
	elif [[ $head_y -gt $y_max ]];then head_y=1
	fi
	head_xy="$head_x,$head_y"
	echo -ne "\033[${head_y};${head_x}H${logo_head}"
	if [[ $go ]]
	then
		echo -ne "\033[${body_y_d};${body_x_d}H${logo_background}"
	fi
	for i in `seq 0 $((${#body_xy[@]}-1))`
	do
		echo -ne "\033[${body_y[$i]};${body_x[$i]}H${logo_body}"
	done
}

#Hit self game over
game_over_l(){
	for i in ${body_xy[@]}
	do
		if [[ $head_xy == $i ]]
		then
		for i in `seq 0 $((${#body_xy[@]}-1))`
		do
			echo -ne "\033[${body_y[$i]};${body_x[$i]}H${logo_background}"
			sleep 0.1
		done
			echo -ne "\033[${head_y};${head_x}H${logo_background}" 
			sleep 0.5
		printf_l $(($((y_max/2))-2)) $((x_max/4)) '|------------------------|'
		printf_l $(($((y_max/2))-1)) $((x_max/4)) '|     Touch Youself      |'
		printf_l $((y_max/2)) $((x_max/4)) '|       Game over        |'
		printf_l $(($((y_max/2))+1)) $((x_max/4)) '|    You Score is '$score'     |'
		printf_l $(($((y_max/2))+2)) $((x_max/4)) '|------------------------|'
		printf_l $((y_max+2)) 1 '∑三三三⊂ (っゝд・)っ      '
		printf_l $((y_max+3)) 1 '[ PUSH R key to Reset or Q to Quit ]'
		printf_l $((y_max+3)) 1 
		my_exit_l
		fi
	done
}
#speed ms
speed_al=300
speed=$speed_al
time_old=$((`date +%s%N`/1000000))

##drawing anything
backgrond_l
star_l
while [[ $(ps -A |grep $2) ]]
do
#	printf_l $((y_max+3)) 2 $time_old
#	printf_l $((y_max+4)) 2 `date +%s%N`
	get_key_l
#	printf_l $((y_max+5)) 2 go=$go'       '
#	printf_l $((y_max+6)) 2 go_w=${go_w[@]}'         '
#	printf_l $((y_max+7)) 2 $$
	if [[ $((time_old+speed)) -le $((`date +%s%N`/1000000)) ]]
	then
		snake_l
		score_l
		game_over_l
#		printf_l 3 $((x_max+2)) $$
		printf_l $((y_max+2)) 2 score=$score
		printf_l $((y_max+3)) 2 speed=$speed
		#printf_l $((y_max+4)) 2 $$
		#printf_l $((y_max+5)) 2 $test_pid
		time_old=$((`date +%s%N`/1000000))
	fi
done
my_exit_l

play.sh

#!/bin/bash
## This is a snake game ,
## Written by callcz in 20220719 .
## Use the number keys to control the direction .
##
#echo $$>pid.txt
##help
if [[ $1 = help || $1 = --help || $1 = '-h' ]]
then
	head -n5 $0
	echo "  Usage : $0 [ --turn or --help ]
  --turn,-t	Turn flip up and down the keys if you want .
  --help,-h	List this help ."
exit
fi
if [[ $1 == '-t' || $1 == --turn ]]
then
	./main_gen_snake.sh $1 $$ &
elif [[ ! $1 ]]
then
	./main_gen_snake.sh null $$ &
else
	./main_gen_snake.sh $1 $$ &
fi
if [[ $2 ]]
then
	puid=$2
else
	puid=`ps -ef|grep main_gen_snake.sh|grep bash|awk '{print $2}'`
fi
if [[ ! $puid || -z $puid ]]
then
	echo "Can't find './main_gen_snake.sh' PUID"
	exit
fi
trap 'handshake=ok' 12
handshake_l(){
	handshake=null
	kill -29 $puid
	sleep 3
	if [[ $handshake != ok ]]
	then
		echo 'handshake fail'
		exit
fi
}
#handshake_l
#echo $puid >puid.txt
trap "kill -10 $puid;echo -en '\033[?25h';exit" 2
while :
do
	read -n 1 -s key
	case $key in
		2)
			kill -25 $puid
			;;
		8)
			kill -26 $puid
			;;
		4)
			kill -27 $puid
			;;
		6)
			kill -28 $puid
			;;
		1)
			kill -21 $puid
			;;
		3)
			kill -22 $puid
			;;
		7)
			kill -23 $puid
			;;
		9)
			kill -24 $puid
			;;
		r)
			check=`ps $puid|awk 'NR==2{print $1}'`
			if [[ -z $check ]]
			then
				if [[ $1 ]]
				then
		                ./main_gen_snake.sh $1 $$ &
				else
				./main_gen_snake.sh null $$ &
				fi
				if [[ $2 ]]
				then
					puid=$2
				else
					puid=`ps -ef|grep main_gen_snake.sh|grep bash|awk '{print $2}'`
				fi
				#handshake_l
			fi
			;;
		q)
			check=`ps $puid|awk 'NR==2{print $1}'`
			if [[ -n $check ]]
			then
				kill -10 $puid
				exit
			else
				exit
			fi
			;;
		t)
			handshake_l
			;;
	esac
	unset key
done


Reply Favorite View the author
All Replies
神末shenmo
Moderator
2022-07-28 16:27
#1

狠人啊!

Reply View the author
callcz
deepin
2022-07-28 16:59
#2
神末shenmo

狠人啊!

有什么狠的?😂

Reply View the author
特殊字符
deepin
2022-08-04 02:31
#3

大神,有个问题请教下。uos下的sh脚本,怎么让它运行完能显示反馈结果呢?我是想用xdotool获得鼠标当前坐标,最基础方法就是shell中运行命令,但是还要总手动调整鼠标位置,所以编写了一个sh脚本,就只有一句话:
xdotool getmouselocation
,然后设置为可执行权限,又给它设置了系统快捷键,应该是很方便。但是运行后没有出现bash窗口,无法获得反馈信息。
检索到两个办法,脚本最后加sleep 100或者read -n 1或者read -p ,都没有效果,始终不会出现shell窗口。

简单办法获得sh脚本运行结果,能想到的就是保留shell窗口,或者弹出对话框(这个好像需要tkinter,系统没有),或者写入本地文件,这个更繁琐还不如敲命令了,有没有解决办法,望大神不吝赐教。

Reply View the author
特殊字符
deepin
2022-08-04 02:32
#4

大神,有个问题请教下。uos下的sh脚本,怎么让它运行完能显示反馈结果呢?我是想用xdotool获得鼠标当前坐标,最基础方法就是shell中运行命令,但是还要总手动调整鼠标位置,所以编写了一个sh脚本,就只有一句话:

xdotool getmouselocation

,然后设置为可执行权限,又给它设置了系统快捷键,应该是很方便。但是运行后没有出现bash窗口,无法获得反馈信息。

检索到两个办法,脚本最后加sleep 100或者read -n 1或者read -p ,都没有效果,始终不会出现shell窗口。

简单办法获得sh脚本运行结果,能想到的就是保留shell窗口,或者弹出对话框(这个好像需要tkinter,系统没有),或者写入本地文件,这个更繁琐还不如敲命令了,有没有解决办法,望大神不吝赐教。

Reply View the author
callcz
deepin
2022-08-04 03:37
#5
特殊字符

大神,有个问题请教下。uos下的sh脚本,怎么让它运行完能显示反馈结果呢?我是想用xdotool获得鼠标当前坐标,最基础方法就是shell中运行命令,但是还要总手动调整鼠标位置,所以编写了一个sh脚本,就只有一句话:

xdotool getmouselocation

,然后设置为可执行权限,又给它设置了系统快捷键,应该是很方便。但是运行后没有出现bash窗口,无法获得反馈信息。

检索到两个办法,脚本最后加sleep 100或者read -n 1或者read -p ,都没有效果,始终不会出现shell窗口。

简单办法获得sh脚本运行结果,能想到的就是保留shell窗口,或者弹出对话框(这个好像需要tkinter,系统没有),或者写入本地文件,这个更繁琐还不如敲命令了,有没有解决办法,望大神不吝赐教。

这个我也不会,我是边学shell脚本边写一下练习sad

Reply View the author
特殊字符
deepin
2022-08-04 04:51
#6
callcz

这个我也不会,我是边学shell脚本边写一下练习sad

仍然感谢,看你的游戏就像大佬

Reply View the author
Comments
callcz
2022-08-04 06:00
不敢当啊
callcz
deepin
2022-08-04 05:23
#7
特殊字符

大神,有个问题请教下。uos下的sh脚本,怎么让它运行完能显示反馈结果呢?我是想用xdotool获得鼠标当前坐标,最基础方法就是shell中运行命令,但是还要总手动调整鼠标位置,所以编写了一个sh脚本,就只有一句话:

xdotool getmouselocation

,然后设置为可执行权限,又给它设置了系统快捷键,应该是很方便。但是运行后没有出现bash窗口,无法获得反馈信息。

检索到两个办法,脚本最后加sleep 100或者read -n 1或者read -p ,都没有效果,始终不会出现shell窗口。

简单办法获得sh脚本运行结果,能想到的就是保留shell窗口,或者弹出对话框(这个好像需要tkinter,系统没有),或者写入本地文件,这个更繁琐还不如敲命令了,有没有解决办法,望大神不吝赐教。

Screenshot_20220804_131158_edit_128767655071658.jpg
你的意思是要获得xdotool的输出是吧?而终端窗口一闪而过?

xdotool我没有用过,不知道你写得对不对,但是如果是一般的sh脚本,要用 #!/bin/bash作为第一行,还有在结尾一行加上 read -n1 -p "按任意键退出"

双击sh脚本之后在对话框选择“在终端执行”,如图。

你可以在尝试在下面的脚本的开始和结束之间添加你要写的命令

#/bin/bash
#开始
echo hello
#结束
read -n1 -p "按任意键退出"
Reply View the author
特殊字符
deepin
2022-08-04 06:14
#8
callcz

Screenshot_20220804_131158_edit_128767655071658.jpg
你的意思是要获得xdotool的输出是吧?而终端窗口一闪而过?

xdotool我没有用过,不知道你写得对不对,但是如果是一般的sh脚本,要用 #!/bin/bash作为第一行,还有在结尾一行加上 read -n1 -p "按任意键退出"

双击sh脚本之后在对话框选择“在终端执行”,如图。

你可以在尝试在下面的脚本的开始和结束之间添加你要写的命令

#/bin/bash
#开始
echo hello
#结束
read -n1 -p "按任意键退出"

非常感谢,这样成功获得shell窗口了。那用系统快捷键打开这个脚本程序怎么获得窗口呢?就像双击后不选“在终端中运行”,直接选“运行”,能不能同样弹出窗口呢?

Reply View the author
callcz
deepin
2022-08-04 10:21
#9
特殊字符

非常感谢,这样成功获得shell窗口了。那用系统快捷键打开这个脚本程序怎么获得窗口呢?就像双击后不选“在终端中运行”,直接选“运行”,能不能同样弹出窗口呢?

这样子大概需要建立一个.desktop文件来描述你的脚本运行时应该打开终端窗口:

新建一个文本文件内容如下,然后将缀名改为.desktop,如果双击启动成功的话再把这个文件设为快捷键启动:

[Desktop Action Gallery]
Exec=/脚本路径/xxxx.sh
Name=显示名称
Terminal=ture
Reply View the author
xuqi
deepin testing team
2022-08-10 14:17
#10

kissing_heart

Reply View the author
Use Markdown Editor
Loading