#!/usr/local/bin/bash IFS='' declare -i height=$(($(tput lines)-5)) width=$(($(tput cols)-2)) # fila y columna de la cabeza declare -i cabeza_d cabeza_c cola_d cola_c declare -i alive declare -i length declare cuerpo declare -i direction delta_dir declare -i puntaje=0 color_borde="\e[30;43m" color_culebra="\e[32;42m" color_comida="\e[34;44m" color_texto="\e[31;43m" sin_color="\e[0m" # flags de señales FLAG_ARRIBA=USR1 FLAG_DERECHA=USR2 FLAG_ABAJO=URG FLAG_IZQUIERDA=IO FLAG_SALIR=WINCH FLAG_MUERTE=HUP # matrices direccionales: 0=arriba, 1=derecha, 2=abajo, 3=izquierda move_r=([0]=-1 [1]=0 [2]=1 [3]=0) move_c=([0]=0 [1]=1 [2]=0 [3]=-1) iniciar_juego() { clear echo -ne "\e[?25l" stty -echo for ((i=0; i<height; i++)); do for ((j=0; j<width; j++)); do eval "arr$i[$j]=' '" done done } mover_y_dibujar() { echo -ne "\e[${1};${2}H$3" } # imprime todo en el buffer dibujar_tablero() { mover_y_dibujar 1 1 "$color_borde+$sin_color" for ((i=2; i<=width+1; i++)); do mover_y_dibujar 1 $i "$color_borde-$sin_color" done mover_y_dibujar 1 $((width + 2)) "$color_borde+$sin_color" echo for ((i=0; i<height; i++)); do mover_y_dibujar $((i+2)) 1 "$color_borde|$sin_color" eval echo -en "\"\${arr$i[*]}\"" echo -e "$color_borde|$sin_color" done mover_y_dibujar $((height+2)) 1 "$color_borde+$sin_color" for ((i=2; i<=width+1; i++)); do mover_y_dibujar $((height+2)) $i "$color_borde-$sin_color" done mover_y_dibujar $((height+2)) $((width + 2)) "$color_borde+$sin_color" echo } # configura estado inicial de la culebra iniciar_culebra() { alive=0 length=10 direction=0 delta_dir=-1 cabeza_d=$((height/2-2)) cabeza_c=$((width/2)) cuerpo='' for ((i=0; i<length-1; i++)); do cuerpo="1$cuerpo" done local p=$((${move_r[1]} * (length-1))) local q=$((${move_c[1]} * (length-1))) cola_d=$((cabeza_d+p)) cola_c=$((cabeza_c+q)) eval "arr$cabeza_d[$cabeza_c]=\"${color_culebra}o$sin_color\"" prev_r=$cabeza_d prev_c=$cabeza_c b=$cuerpo while [ -n "$b" ]; do # change in each direction local p=${move_r[$(echo $b | grep -o '^[0-3]')]} local q=${move_c[$(echo $b | grep -o '^[0-3]')]} nuevo_d=$((prev_r+p)) nuevo_c=$((prev_c+q)) eval "arr$nuevo_d[$nuevo_c]=\"${color_culebra}o$sin_color\"" prev_r=$nuevo_d prev_c=$nuevo_c b=${b#[0-3]} done } esta_muerta() { if [ "$1" -lt 0 ] || [ "$1" -ge "$height" ] || \ [ "$2" -lt 0 ] || [ "$2" -ge "$width" ]; then return 0 fi eval "local pos=\${arr$1[$2]}" if [ "$pos" == "${color_culebra}o$sin_color" ]; then return 0 fi return 1 } dar_comida() { local comida_d=$((RANDOM % height)) local comida_c=$((RANDOM % width)) eval "local pos=\${arr$comida_d[$comida_c]}" while [ "$pos" != ' ' ]; do comida_d=$((RANDOM % height)) comida_c=$((RANDOM % width)) eval "pos=\${arr$comida_d[$comida_c]}" done eval "arr$comida_d[$comida_c]=\"$color_comida@$sin_color\"" } mueve_culebra() { local nuevacabeza_d=$((cabeza_d + move_r[direction])) local nuevacabeza_c=$((cabeza_c + move_c[direction])) eval "local pos=\${arr$nuevacabeza_d[$nuevacabeza_c]}" if $(esta_muerta $nuevacabeza_d $nuevacabeza_c); then alive=1 return fi if [ "$pos" == "$color_comida@$sin_color" ]; then length+=1 eval "arr$nuevacabeza_d[$nuevacabeza_c]=\"${color_culebra}o$sin_color\"" cuerpo="$(((direction+2)%4))$cuerpo" cabeza_d=$nuevacabeza_d cabeza_c=$nuevacabeza_c puntaje+=1 dar_comida; return fi cabeza_d=$nuevacabeza_d cabeza_c=$nuevacabeza_c local d=$(echo $cuerpo | grep -o '[0-3]$') cuerpo="$(((direction+2)%4))${cuerpo%[0-3]}" eval "arr$cola_d[$cola_c]=' '" eval "arr$cabeza_d[$cabeza_c]=\"${color_culebra}o$sin_color\"" # nueva tail local p=${move_r[(d+2)%4]} local q=${move_c[(d+2)%4]} cola_d=$((cola_d+p)) cola_c=$((cola_c+q)) } cambiar_dir() { if [ $(((direction+2)%4)) -ne $1 ]; then direction=$1 fi delta_dir=-1 } getchar() { trap "" SIGINT SIGQUIT trap "return;" $FLAG_MUERTE while true; do read -s -n 1 key case "$key" in [qQ]) kill -$FLAG_SALIR $pid_juego return ;; [wW]) kill -$FLAG_ARRIBA $pid_juego ;; [dD]) kill -$FLAG_DERECHA $pid_juego ;; [sS]) kill -$FLAG_ABAJO $pid_juego ;; [aA]) kill -$FLAG_IZQUIERDA $pid_juego ;; esac done } bucle_juego() { trap "delta_dir=0;" $FLAG_ARRIBA trap "delta_dir=1;" $FLAG_DERECHA trap "delta_dir=2;" $FLAG_ABAJO trap "delta_dir=3;" $FLAG_IZQUIERDA trap "exit 1;" $FLAG_SALIR while [ "$alive" -eq 0 ]; do echo -e "\n${color_texto} Tu puntaje: $puntaje $sin_color" if [ "$delta_dir" -ne -1 ]; then cambiar_dir $delta_dir fi mueve_culebra dibujar_tablero sleep 0.03 done echo -e "${color_texto}Oh, No! usted ha muerto!$sin_color" # señala al bucle de entrada que la culebra ha muerto kill -$FLAG_MUERTE $$ } borrar_juego() { stty echo echo -e "\e[?25h" } iniciar_juego iniciar_culebra dar_comida dibujar_tablero bucle_juego & pid_juego=$! getchar borrar_juego exit 0