083_贪吃蛇-Shell跑马灯版 2022最新代码
效果图:
代码:
#!/bin/bash # 基础知识 # 前景色(文字颜色): echo -e "\e[${num}m有颜色的文字" # 39默认前景色 30黑色 31红色 32绿色 33黄色 34蓝色 35品红 36青色 37浅灰 # 90深灰色 91红灯 92浅绿色 93淡黄色 94浅蓝 95浅洋红色 96浅青色 97白色 # 背景色: echo -e "\e[$(num)m有背景颜色的文字" # 49默认背景颜色 40黑色 41红色 42绿色 43黄色 44蓝色 45品红 46青色 47浅灰 # 100深灰色 101红灯 102浅绿色 103淡黄色 104浅蓝 105浅洋红色 106浅青色 107白色 # 属性: # \e[0m 关闭所有属性 # \e[1m 设置高亮度 # \e[4m 下划线 # \e[5m 闪烁 # \e[7m 反显 # \e[8m 消隐 # \e[30m -- \e[37m 设置前景色 # \e[40m -- \e[47m 设置背景色 # \e[nA 光标上移n行 # \e[nB 光标下移n行 # \e[nC 光标右移n行 # \e[nD 光标左移n行 # \e[y;xH 设置光标位置 # \e[2J 清屏 # \e[K 清除从光标到行尾的内容 # \e[s 保存光标位置 # \e[u 恢复光标位置 # \e[?25l 隐藏光标 # \e[?25h 显示光标 # 属性示例: # 1 粗体高亮 echo -e "\e[1mBold" # 2 变暗 echo -e "\e[2mDim" # 4 下划线 echo -e "\e[4mUnderlined" # 5 闪烁 echo -e "\e[5mBlink" # 7 反转 (反转前景色和背景色) echo -e "\e[7minverted" # 8 隐藏(对密码有用) echo -e "\e[8mHidden" # 结合: # echo -e "\e[41;32m文字\e[0m" 红色背景绿色字并清除属性 # echo -e "\e[1;3H*\e[0m" 第一行第三列输出一个* # echo -e "\e[3;3H\e[44;31m*\e[0m" 第三行第三列输出一个蓝色背景红色字 # echo -e "\e[5;31;42m文字\e[0m" 闪烁、红色背景、绿色的文字并清除属性 # echo -e "\e[3;3H\e[5;31;42m*************\e[0m" 第三行第三列输出一排闪烁的星 # 键盘控制 w s a d # 退出游戏 q # 地图大小 长宽可以自由改动 declare -i MAP_WIDTH=60 declare -i MAP_HIGHT=20 # 地图起始位置(左上角的开始绘制的位置, 可以自由改动) declare -i MAP_X=20 declare -i MAP_Y=5 # 定义 蛇头的起始位置x,y 及 蛇初始化长度4 declare -i X=30 declare -i Y=30 declare -i LENGTH=4 # 舌头蛇身的坐标点 declare -a X_ARR=() declare -a Y_ARR=() # 食物的坐标 declare -i RANDOM_X=0 declare -i RANDOM_Y=0 # 跑马灯的开始颜色 declare -i COLOR_INDEX=15 # 初始化 蛇 出生移动方向 DIR='d' score=0 # 游戏结束恢复环境 function end_of_game() { kill -9 $! echo -e "\e[0m" echo -e "\e[?25h" exit 1 } # 生成边界 function init_map() { # 两横 for i in $(seq ${MAP_X} $((${MAP_X} + ${MAP_WIDTH}))); do echo -e "\e[${MAP_Y};${i}H@\e[0m" echo -e "\e[$((${MAP_Y} + ${MAP_HIGHT}));${i}H@\e[0m" done # 两竖 for j in $(seq ${MAP_Y} $((${MAP_Y} + ${MAP_HIGHT}))); do echo -e "\e[${j};${MAP_X}H@\e[0m" echo -e "\e[${j};$((${MAP_X} + ${MAP_WIDTH}))H@\e[0m" done } # 跑马灯效果 function init_map_lamp() { while true :; do let COLOR_INDEX=15 for i in $(seq ${MAP_X} $((${MAP_X} + ${MAP_WIDTH}))); do let COLOR_INDEX++ sleep 0.003 echo -e "\e[38;5;${COLOR_INDEX}m\e[${MAP_Y};${i}H@\e[0m" done for j in $(seq ${MAP_Y} $((${MAP_Y} + ${MAP_HIGHT}))); do let COLOR_INDEX++ sleep 0.003 echo -e "\e[38;5;${COLOR_INDEX}m\e[${j};$((${MAP_X} + ${MAP_WIDTH}))H@\e[0m" done for ((k = $((${MAP_X} + ${MAP_WIDTH})); k >= ${MAP_X}; k--)); do let COLOR_INDEX-- sleep 0.003 echo -e "\e[38;5;${COLOR_INDEX}m\e[$((${MAP_Y} + ${MAP_HIGHT}));${k}H@\e[0m" done for ((m = $((${MAP_Y} + ${MAP_HIGHT})); m >= ${MAP_Y}; m--)); do let COLOR_INDEX-- sleep 0.003 echo -e "\e[38;5;${COLOR_INDEX}m\e[${m};${MAP_X}H@\e[0m" done done } # 初始化蛇 function draw_snake() { clear # 生成蛇身 for ((i = 1; i < ${LENGTH}; i++)); do echo -e "\e[${Y_ARR[$i]};${X_ARR[$i]}H*\e[0m" done # 生成蛇头 echo -e "\e[${Y_ARR[$i]};${X_ARR[$i]}H$\e[0m" # 随机生成食物 echo -e "\e[5;32m\e[${RANDOM_Y};${RANDOM_X}H#\e[0m" # 生成地图 init_map # 输出蛇头、食物的起位置 打印分数 echo -e "\e[$(($MAP_Y + $MAP_HIGHT + 2));${MAP_X}H\e[32mSnake:${X},${Y}\e[0m\e[0m" echo -e "\e[$(($MAP_Y + $MAP_HIGHT + 3));${MAP_X}H\e[32mFood :${RANDOM_X},${RANDOM_Y}\e[0m\e[0m" echo -e "\e[$(($MAP_Y + $MAP_HIGHT + 4));${MAP_X}H\e[33mScore:${score}\e[0m\e[0m" } # 生成食物 function gen_food() { let flag=1 while [ $flag -eq 1 ]; do # 0-58 + 21 let RANDOM_X=$(($RANDOM % $((${MAP_WIDTH} - 1)) + $((${MAP_X} + 1)))) # 0-18 + 6 let RANDOM_Y=$(($RANDOM % $((${MAP_HIGHT} - 1)) + $((${MAP_Y} + 1)))) # 生成与蛇身+蛇头 坐标不相等的 食物坐标 for ((i = 0; i < ${LENGTH}; i++)); do # 如果相等 退出当前循环,重新 while循环,i又从1开始 if [[ ${X_ARR[$i]} -eq ${RANDOM_X} && ${Y_ARR[$i]} -eq ${RANDOM_Y} ]]; then break fi done # 只有生成的食物坐标与蛇头+蛇身坐标完全不相等时 if [ $i -eq ${LENGTH} ]; then flag=0 fi done } function init() { clear # 清除所有属性 echo -e "\e[0m" # 隐藏光标 echo -e "\e[?25l" # 生成蛇的初始化坐标 for i in $(seq 5); do # 在地图的中点取五个点初始化蛇的位置 let pos_x=$((${MAP_WIDTH} / 2 - 2 + ${i}))+${MAP_X} let pos_y=$(((${MAP_Y} + ${MAP_HIGHT}) / 2))+${MAP_Y} X_ARR+=($pos_x) Y_ARR+=($pos_y) done X=$pos_x Y=$pos_y # 生成食物 gen_food } function move() { case $DIR in "w") Y=$Y-1 ;; # 往上移动 "s") Y=$Y+1 ;; # 往下移动 "a") X=$X-1 ;; # 往左移动 "q") end_of_game ;; *) X=$X+1 ;; # 默认右移 esac # 如果蛇头碰到食物,长度+1,并重新生成食物 if [[ $X -eq ${RANDOM_X} && $Y -eq ${RANDOM_Y} ]]; then ((LENGTH++)) let score+=10 X_ARR[${LENGTH}]=$X Y_ARR[${LENGTH}]=$Y gen_food return fi # 越界退出 if [[ $X -le $MAP_X || $Y -le $MAP_Y || $X -ge $(($MAP_X + $MAP_WIDTH)) || $Y -ge $(($MAP_Y + $MAP_HIGHT)) ]]; then end_of_game fi # 蛇头碰到蛇身 for ((i = 2; i <= ${LENGTH}; i++)); do if [[ $X -eq ${X_ARR[$i]} && $Y -eq ${Y_ARR[$i]} ]]; then end_of_game fi done # 向前蠕动一下 for ((i = 0; i <= ${LENGTH}; i++)); do X_ARR[$i]=${X_ARR[$i + 1]} Y_ARR[$i]=${Y_ARR[$i + 1]} done # 更新蛇头到数组 X_ARR[${LENGTH}]=$X Y_ARR[${LENGTH}]=$Y } function main() { init draw_snake # 以子进程的方式开启跑马灯效果 { init_map_lamp } & while :; do OLD_DIR=$DIR # 如果没有wasd输入,则保持原方向不变,否则调转方向 if ! read -n 1 -t 0.5 -s DIR; then DIR=$OLD_DIR fi sleep 0.0001 move draw_snake done } main