Snake: Difference between revisions

3,518 bytes added ,  1 year ago
→‎{{header|UNIX Shell}}: Add implementation.
m (syntax highlighting fixup automation)
(→‎{{header|UNIX Shell}}: Add implementation.)
Line 4,066:
 
SnakeGame(w || 80, h || 24).play</syntaxhighlight>
 
=={{header|UNIX Shell}}==
{{works with|Bourne Again SHell}}
{{works with|Z Shell}}
 
Play ASCII snake in your ANSI terminal.
 
It theoretically should also work with the Korn Shell, but for some reason the timeout on the key read is not consistent and the snake stops moving except one step after each keypress.
 
<syntaxhighlight lang="bash">function main {
typeset -i game_over=0
typeset -i height=$(tput lines) width=$(tput cols)
 
# start out in the middle moving to the right
typeset -i dx dy hx=$(( width/2 )) hy=$(( height/2 ))
typeset -a sx=($hx) sy=($hy)
typeset -a timeout
clear
tput cup "$sy" "$sx" && printf '@'
tput cup $(( height/2+2 )) 0
center $width "Press h, j, k, l to move left, down, up, right"
 
# place first food
typeset -i fx=hx fy=hy
while (( fx == hx && fy == hy )); do
fx=$(( RANDOM % (width-2)+1 )) fy=$(( RANDOM % (height-2)+1 ))
done
tput cup "$fy" "$fx" && printf '*'
 
# handle variations between shells
keypress=(-N 1) origin=0
if [[ -n $ZSH_VERSION ]]; then
keypress=(-k)
origin=1
fi
 
stty -echo
tput civis
typeset key
read "${keypress[@]}" -s key
typeset -i start_time=$(date +%s)
tput cup "$(( height/2+2 ))" 0 && tput el
while (( ! game_over )); do
timeout=(-t $(printf '0.%04d' $(( 2000 / (${#sx[@]}+1) )) ) )
if [[ -z $key ]]; then
read "${timeout[@]}" "${keypress[@]}" -s key
fi
 
case "$key" in
h) if (( dx != 1 )); then dx=-1; dy=0; fi;;
j) if (( dy != -1 )); then dy=1; dx=0; fi;;
k) if (( dy != 1 )); then dy=-1; dx=0; fi;;
l) if (( dx != -1 )); then dx=1; dy=0; fi;;
q) game_over=1; tput cup 0 0 && print "Final food was at ($fx,$fy)";;
esac
key=
(( hx += dx, hy += dy ))
# if we try to go off screen, game over
if (( hx < 0 || hx >= width || hy < 0 || hy >= height )); then
game_over=1
else
# if we run into ourself, game over
for (( i=0; i<${#sx[@]}; ++i )); do
if (( hx==sx[i+origin] && hy==sy[i+origin] )); then
game_over=1
break
fi
done
fi
if (( game_over )); then
break
fi
# add new spot
sx+=($hx) sy+=($hy)
 
if (( hx == fx && hy == fy )); then
# if we just ate some food, place some new food out
ok=0
while (( ! ok )); do
# make sure we don't put it under ourselves
ok=1
fx=$(( RANDOM % (width-2)+1 )) fy=$(( RANDOM % (height-2)+1 ))
for (( i=0; i<${#sx[@]}; ++i )); do
if (( fx == sx[i+origin] && fy == sy[i+origin] )); then
ok=0
break
fi
done
done
tput cup "$fy" "$fx" && printf '*'
# and don't remove our tail because we've just grown by 1
else
# if we didn't just eat food, remove our tail from its previous spot
tput cup ${sy[origin]} ${sx[origin]} && printf ' '
sx=( ${sx[@]:1} )
sy=( ${sy[@]:1} )
fi
# draw our new head
tput cup "$hy" "$hx" && printf '@'
done
typeset -i end_time=$(date +%s)
tput cup $(( height / 2 -1 )) 0 && center $width 'GAME OVER'
tput cup $(( height / 2 )) 0 &&
center $width 'Time: %d seconds' $(( end_time - start_time ))
tput cup $(( height / 2 + 1 )) 0 &&
center $width 'Final length: %d' ${#sx[@]}
echo
stty echo
tput cnorm
}
 
function center {
typeset -i width=$1 i
shift
typeset message=$(printf "$@")
tput cuf $(( (width-${#message}) / 2 ))
printf '%s' "$message"
}
 
main "$@"</syntaxhighlight>
 
=={{header|Wren}}==
1,481

edits