#! /bin/bash
# -----------------------------------------------
# Dibujado de tablero
# -----------------------------------------------
dibujaFila1()
{
echo "| $1 | $2 | $3 |";
}
dibujaFila2()
{
echo "|---+---+---|"
}
dibujaTablero()
{
# Toda esta basura del IFS la he tenido que meter para poder leer el array
# desde dentro de la función, si no, no funciona.
OLD_IFS=$IFS
IFS=''
tab2=$1
local array_string="$1[*]"
local tab=(${!array_string})
IFS=$OLD_IFS
echo " ----------- "
dibujaFila1 ${tab[0]} ${tab[1]} ${tab[2]}
dibujaFila2
dibujaFila1 ${tab[3]} ${tab[4]} ${tab[5]}
dibujaFila2
dibujaFila1 ${tab[6]} ${tab[7]} ${tab[8]}
echo " ----------- "
echo
}
# -----------------------------------------------
# Elección de posición
# -----------------------------------------------
# Ok
eligePosMaquina()
{
# Hacemos aleatorios:
fila=$(($RANDOM % 3))
columna=$(($RANDOM % 3))
return $((3*$fila+$columna))
}
# Ok
eligePosJugador()
{
fila=0
until test $fila -ge 1 && test $fila -le 3; do
echo "Introduzca una fila [1-3]:"
read fila
done
columna=0
until test $columna -ge 1 && test $columna -le 3; do
echo "Introduzca una columna [1-3]:"
read columna
done
fila=$(($fila-1))
columna=$(($columna-1))
return $((3*$fila+$columna))
}
#eval echo \${$array_name[$i]}
# -----------------------------------------------
# Comprobaciones de 3 en raya
# -----------------------------------------------
compruebaColumnas()
{
OLD_IFS=$IFS
IFS=''
tab2=$1
local array_string="$1[*]"
local tab=(${!array_string})
IFS=$OLD_IFS
local fila=0
local columna=0
local patron="."
local posicion=0
local encontrado=0 # 1 si 3 en raya, 0 si no.
while test $encontrado -eq 0 && test $columna -lt 3; do
posicion=$((3*$fila+$columna))
if test ${tab[$posicion]} = "."; then
columna=$(($columna+1))
fila=0
posicion=$((3*$fila+$columna))
#echo "Pasando a la siguiente columna."
else
#echo "El patrón a seguir es ${tab[$posicion]}"
patron=${tab[$posicion]}
fila=$(($fila+1))
posicion=$((3*$fila+$columna))
if test ! ${tab[$posicion]} = $patron; then
columna=$(($columna+1))
fila=0
posicion=$((3*$fila+$columna))
#echo "Pasando a la siguiente columna."
else
fila=$(($fila+1))
posicion=$((3*$fila+$columna))
if test ! ${tab[$posicion]} = $patron; then
columna=$(($columna+1))
fila=0
posicion=$((3*$fila+$columna))
#echo "Pasando a la siguiente columna."
else
#echo "Patrón encontrado"
encontrado=1
fi
fi
fi
done
return $encontrado
}
compruebaFilas()
{
OLD_IFS=$IFS
IFS=''
tab2=$1
local array_string="$1[*]"
local tab=(${!array_string})
IFS=$OLD_IFS
local fila=0
local columna=0
local patron="."
local posicion=0
local encontrado=0 # 1 si 3 en raya, 0 si no.
while test $encontrado -eq 0 && test $fila -lt 3; do
posicion=$((3*$fila+$columna))
if test ${tab[$posicion]} = "."; then
fila=$(($fila+1))
columna=0
posicion=$((3*$fila+$columna))
#echo "Pasando a la siguiente fila."
else
#echo "El patrón a seguir es ${tab[$posicion]}"
patron=${tab[$posicion]}
columna=$(($columna+1))
posicion=$((3*$fila+$columna))
if test ! ${tab[$posicion]} = $patron; then
fila=$(($fila+1))
columna=0
posicion=$((3*$fila+$columna))
#echo "Pasando a la siguiente fila."
else
columna=$(($columna+1))
posicion=$((3*$fila+$columna))
if test ! ${tab[$posicion]} = $patron; then
fila=$(($fila+1))
columna=0
posicion=$((3*$fila+$columna))
#echo "Pasando a la siguiente fila."
else
#echo "Patrón encontrado"
encontrado=1
fi
fi
fi
done
return $encontrado
}
compruebaDiagonales()
{
OLD_IFS=$IFS
IFS=''
tab2=$1
local array_string="$1[*]"
local tab=(${!array_string})
IFS=$OLD_IFS
if test ! ${tab[0]} = "." && test ${tab[0]} = ${tab[4]} && test ${tab[4]} = ${tab[8]}; then
return 1
fi
if test ! ${tab[2]} = "." && test ${tab[2]} = ${tab[4]} && test ${tab[4]} = ${tab[6]}; then
return 1
fi
return 0
}
tresEnRaya()
{
OLD_IFS=$IFS
IFS=''
tab2=$1
local array_string="$1[*]"
local tab=(${!array_string})
IFS=$OLD_IFS
# Algoritmo:
# - Miramos si hay 3 en raya en las filas
compruebaFilas tab
encontrado=$?
if test $encontrado -eq 1; then
return 1
fi
# - Miramos si hay 3 en raya en las columnas
compruebaColumnas tab
encontrado=$?
if test $encontrado -eq 1; then
return 1
fi
# - Miramos si hay 3 en raya en las diagonales
compruebaDiagonales tab
encontrado=$?
return $encontrado
}
# -----------------------------------------------
# Tareas de principio de partida
# -----------------------------------------------
eligeFicha()
{
# Otro de los pocos métodos donde necesitamos usar variables globales
# La razón es por no ensuciar el código de fuera, ya que tenemos dos variables de retorno: fichaJugador y fichaMaquina, y bash no permite devolver cadenas, solo enteros, lo que implicaría tener que meter cases de conversión fuera etc....
seleccion=0
echo "Qué fichas desea manejar (cruz o círculo)?"
local ok2=0
while test $ok2 -eq 0; do
read seleccion
# todos los trs de las ies para filtrar ies con tilde o sin tilde.
case `echo $seleccion | tr -s 'í' 'I' | tr -s 'Í' 'I' | tr -s '[a-z]' '[A-Z]'` in
CRUZ)
fichaJugador="x"
fichaMaquina="o"
ok2=1;;
CIRCULO)
fichaJugador="o"
fichaMaquina="x"
ok2=1;;
*) echo "Introduzca una opción válida";;
esac
done
}
eligeTurno()
{
local ok2=0
local turno2=0
echo "Desea colocar primero (si o no)?"
while test $ok2 -eq 0; do
read seleccion
case `echo $seleccion | tr -s 'í' 'I' | tr -s 'Í' 'I' | tr -s '[a-z]' '[A-Z]'` in
SI)
turno2=1
ok2=1;;
NO)
turno2=2
ok2=1;;
*) echo "Introduzca una opción válida";;
esac
done
return $turno2
}
# -----------------------------------------------
# Tareas de fin de partida
# -----------------------------------------------
ganador()
{
local turno2=$1
if test $turno2 -eq 1; then
echo "La máquina gana!!"
else
echo "Usted gana!!"
fi
}
reseteaTablero()
{
# Este es el único método que tenemos que usar variables globales por huevos
# ya que no conseguimos encontrar la forma de que las modificaciones desde
# dentro se apliquen a un array externo.
tablero[0]="."
tablero[1]="."
tablero[2]="."
tablero[3]="."
tablero[4]="."
tablero[5]="."
tablero[6]="."
tablero[7]="."
tablero[8]="."
}
nuevaPartida()
{
OLD_IFS=$IFS
IFS=''
tab2=$1
local array_string="$1[*]"
local tab=(${!array_string})
IFS=$OLD_IFS
local ok2=0
local final=1
local seleccion2=""
echo "¿Desea jugar de nuevo? (si o no)"
while test $ok2 -eq 0; do
read seleccion2
case `echo $seleccion2 | tr -s 'í' 'I' | tr -s 'Í' 'I' | tr -s '[a-z]' '[A-Z]'` in
SI)
final=0
ok2=1
reseteaTablero;;
NO)
ok2=1
echo "Adios.";;
*) echo "Introduzca una opción válida";;
esac
done
return $final
}
# Inicialización del tablero
# Indispensable inicializarlos con puntitos para que no desordene
# el array ni reduzca los espacios en blanco.
tablero[0]="."
tablero[1]="."
tablero[2]="."
tablero[3]="."
tablero[4]="."
tablero[5]="."
tablero[6]="."
tablero[7]="."
tablero[8]="."
# ----------------------------------------------------------------
# Programa principal
# ----------------------------------------------------------------
fichaJugador=""
fichaMaquina=""
clear
echo "Bienvenido a las tres en raya."
eligeFicha
turno=0
eligeTurno
turno=$?
clear
# ---------------------------------
# Bloque principal del algoritmo
# ---------------------------------
fin=0
dibujaTablero tablero
while test $fin -eq 0; do
libre=1
# libre: 0 si está ocupada, 1 si está vacía.
while test ! $libre -eq 0; do
# Vemos de quien es el turno y ejecutamos un algoritmo
# u otro.
if test $turno = 1; then
eligePosJugador
posicion=$?
else
eligePosMaquina
posicion=$?
fi
# Si estuviese vacía, este test daría 0 y saldría del bucle
test ${tablero[posicion]} = "."
libre=$?
done
# Ponemos la ficha correspondiente en la casilla elegida.
if test $turno -eq 1; then
tablero[posicion]=$fichaJugador
else
tablero[posicion]=$fichaMaquina
fi
# Cambiamos el turno
if test $turno -eq 1; then
turno=2
else
turno=1
fi
# Estas son las 2 últimas sentencias para hacerlo parecido a
# un do...while
clear
dibujaTablero tablero
tresEnRaya tablero
fin=$?
if test $fin -eq 1; then
ganador $turno
nuevaPartida tablero
fin=$?
if test $fin -eq 0; then
clear
eligeFicha
turno=0
eligeTurno
turno=$?
clear
fi
fi
done