Mostrando entradas con la etiqueta if. Mostrar todas las entradas
Mostrando entradas con la etiqueta if. Mostrar todas las entradas

sábado, 4 de julio de 2015

Juego: Tres en raya



Esta vez repasaremos matrices, funciones, condicionales e iteraciones, todo esto aplicado en el clásico juego del tres en raya, las reglas del juego son muy conocidas, sólo haré unos cuantos razonamientos previos antes de empezar a programar:

Sobre los turnos

Sabemos que son 2 jugadores que juegan por turnos hasta que alguno gana o el tablero se llena sin ganador (situación de empate).
Vemos que debe existir una iteración que finalice cuando el juego termina:

var fin_juego = false;
var turno = 0; //los jugadores son 0 y 1

while(!fin_juego)
{
//se hace la jugada
//si se gana en este turno fin_juego = true;
//si el tablero se llena sin ganador fin_juego = true;
turno = (turno + 1) % 2; //esto es para cambiar el turno de 0 a 1 y de 1 a 0
}



Sabemos que es un tablero de 9 casillas (3 filas y 3 columnas). En principio todas las casillas están vacías y en cada turno se va llenando alguna de las casillas con la jugada hecha en el turno.
Si todas las casillas están llenas y no hay ganador, entonces es un empate.
Para controlar que el juego termine en empate creamos un condicional en cada iteración que controle si se llenó el tablero o no.

var fin_juego = false;
var turno = 0; //los jugadores son 0 y 1
var casillas_vacias = 9;

while(!fin_juego)
{
//se hace la jugada
casillas_vacias = casillas_vacias - 1; //al hacer la jugada disminuye en 1 las casillas vacías

//si se gana en este turno fin_juego = true;

//si el tablero se llena sin ganador fin_juego = true;
if(!fin_juego && casillas_vacias == 0) fin_juego = true;
turno = (turno + 1) % 2; //esto es para cambiar el turno de 0 a 1 y de 1 a 0
}

Sobre la jugada

El jugador debe seleccionar la casilla que quiere marcar, para esto utilizaremos las filas y las columnas de la matriz que representa al tablero.

var boolean fin_juego = false;
var int turno = 0; //los jugadores son 0 y 1
var int casillas_vacias = 9;
var char tablero [3][3];//matriz de 3 x 3 que representa al tablero
var int fila_jugada;
var int columna_jugada;
var char ficha='0'; //será 'X' cuando el turno sea 1

while(!fin_juego)
{
//se hace la jugada
fila_jugada = leer(); //lee de consola la fila (de 0 a 2) que selecciona el jugador en ese turno
columna_jugada = leer(); //lee de consola la columna (de 0 a 2) que selecciona el jugador en ese turno
if(turno == 0) ficha = '0'; //escoge ficha
else ficha = 'X';
tablero[fila_jugada][columna_jugada] = ficha;
casillas_vacias = casillas_vacias - 1; //al hacer la jugada disminuye en 1 las casillas vacías

//si se gana en este turno fin_juego = true;

//si el tablero se llena sin ganador fin_juego = true;
if(!fin_juego && casillas_vacias == 0) fin_juego = true;
turno = (turno + 1) % 2; //esto es para cambiar el turno de 0 a 1 y de 1 a 0
}

Sobre el control de la jugada ganadora

Cuando se coloca la ficha se hace control en vertical, horizontal y diagonales a ver si es una jugada ganadora.
Para el control horizontal, todas las fichas de la fila_jugada deben ser iguales, por tanto haremos una validación iterando las columnas.
Para el control vertical, todas las fichas de la columna_jugada deben ser iguales, por tanto haremos una validación iterando las filas.
Para el control diagonal, no es necesario realizarlo siempre, sólo cuando la jugada esté en alguna diagonal. Y sólo si está en el medio del tablero la comprobación debe ser de la doble diagonal.
Comprobar diagonal 1
fila_jugada: 0 y columna_jugada:0,
fila_jugada: 2 y columna_jugada:2

Comprobar diagonal 2
fila_jugada: 2 y columna_jugada:0,
fila_jugada: 0 y columna_jugada:2

Comprobar ambas diagonales.
fila_jugada: 1 y columna_jugada:1



Como esta lógica es un poco larga, la encapsularemos en una función y la utilizaremos en cada jugada para comprobar si la jugada es ganadora:

Entrada: ¿Qué necesito?
Tablero, fila_jugada, columna_jugada
Salida: ¿Qué quiero?
Booleano que indique si es una jugada ganadora o no
Función: ¿Cómo lo hago?
Comprobando la Horizontal, Vertical y cuando toque las diagonales.

Boolean esGanador(tablero, fila_jugada, columna_jugada)
{
Boolean jugada_ganadora = false;
//validación horizontal 
if(Tablero[fila_jugada][0] == Tablero[fila_jugada][1] &&
Tablero[fila_jugada][0] == Tablero[fila_jugada][2])
{
return true; //jugada ganadora en la horizontal, termina la ejecución
}
//validación vertical 
if(Tablero[0][columna_jugada] == Tablero[1][columna_jugada] &&
Tablero[0][columna_jugada] == Tablero[2][columna_jugada])
{
return true; //jugada ganadora en la vertical, termina la ejecución
}
//verifica la diagonal 1 (sólo si es necesario)
if( (fila_jugada == 0 && columna_jugada == 0) || (fila_jugada == 2 && columna_jugada == 2))
{
if(Tablero[0][0] == Tablero[1][1] &&
Tablero[0][0] == Tablero[2][2])
{
return true; //jugada ganadora en la diagonal 1, termina la ejecución
}
}

//verifica la diagonal 2 (sólo si es necesario)
if( (fila_jugada == 0 && columna_jugada == 2) || (fila_jugada == 2 && columna_jugada == 0))
{
if(Tablero[0][2] == Tablero[1][1] &&
Tablero[0][2] == Tablero[2][0])
{
return true; //jugada ganadora en la diagonal 2, termina la ejecución
}
}

//verifica la doble diagonal(sólo si es necesario)
if( fila_jugada == 1 && columna_jugada == 1)
{
if((Tablero[0][2] == Tablero[1][1] &&
Tablero[0][2] == Tablero[2][0]) ||
(Tablero[0][0] == Tablero[1][1] &&
Tablero[0][0] == Tablero[2][2]))
{
return true; //jugada ganadora en alguna de las diagonales, termina la ejecución
}
}


return jugada_ganadora; //sólo llega a esta línea de código cuando no es jugada ganadora
}



Incorporamos la llamada a la función en el programa principal
var boolean fin_juego = false;
var int turno = 0; //los jugadores son 0 y 1
var int casillas_vacias = 9;
var char tablero [3][3];//matriz de 3 x 3 que representa al tablero
var int fila_jugada;
var int columna_jugada;
var char ficha='0'; //será 'X' cuando el turno sea 1

while(!fin_juego)
{
//se hace la jugada
fila_jugada = leer(); //lee de consola la fila (de 0 a 2) que selecciona el jugador en ese turno
columna_jugada = leer(); //lee de consola la columna (de 0 a 2) que selecciona el jugador en ese turno
if(turno == 0) ficha = '0'; //escoge ficha
else ficha = 'X';
tablero[fila_jugada][columna_jugada] = ficha;
casillas_vacias = casillas_vacias - 1; //al hacer la jugada disminuye en 1 las casillas vacías

//si se gana en este turno fin_juego = true;
fin_juego = esGanador(tablero, fila_jugada, columna_jugada);

//si el tablero se llena sin ganador fin_juego = true;
if(!fin_juego && casillas_vacias == 0) fin_juego = true;
turno = (turno + 1) % 2; //esto es para cambiar el turno de 0 a 1 y de 1 a 0
}


Con esto tendríamos lo básico para el tres en raya, pero ¿qué pasaría si el jugador pusiera la ficha en un lugar ocupado? ¿qué pasaría si inicialmente el tablero está ocupado?¿No vendría bien agregar una impresión del tablero para que jugador sepa en cada jugada cuáles son sus opciones de juego?

¿Cómo modificaríais el programa para agregar estas funcionalidades?

Enlaces




domingo, 20 de julio de 2014

Algo de matrices

Una de las dificultades más comunes son los vectores, sobretodo comprender la diferencia entre el indice de un vector (posición) y el valor contenido en el índice del vector (datos).

Para complicarlo aún más viene el tema de las matrices, que no son más que vectores pero en dos dimensiones, esto es que ahora el índice está formado por dos posiciones.

Sobre teoría de matrices se ha escrito mucho, lo que pretendo en este post es simplemente mostrar como acceder a una matriz y determinar si es una matriz identidad o no (¿Qués es una matriz identidad?). Para este fin utilizaremos el recorrido secuencial de una matriz fila a fila y para cada elemento de la fila veremos si tiene el valor correcto que le corresponde a la matriz identidad (1 en la diagonal y 0 en el resto de campos):

int esIdentidad = 1; //variable que indica si la matriz es identidad o no
int x, y = 0; //indice de filas y columnas
int N=10;//dimensión de la matriz

//se asumen que la matriz es de Identidad hasta que se muestre que tenga un valor incorrecto
while(esidentidad)
{
  //recorre todos los elementos de la fila hasta que encuentre algún error o termine la fila
  for(int y=0; y<N && esIdentidad; y++)
  {
    //la diagonal debe tener el valor 1, en caso contrario no puede ser una matriz Identidad
    if(x==y && Matriz[x][y] !=1) esidentidad = 0;
    //los que no están en la diagonal deben ser 0, en caso contrario no puede ser una matriz identidad
    if(x!=y && Matriz[x][y] !=0) esidentidad = 0;
  }
  x++;//cada iteración del while se corresponde con cada fila de la matriz  
}

//resultado de la evaluación
if(esIdentidad) print("La matriz es identidad");
else print("La matriz no es identidad");


Vemos que el el indice de la  matriz está compuesto por dos posiciones: x e y.
Vemos que el valor en una posición determinada de la matriz se accede a través de las posiciones: Matriz[x][y].
Vemos que cuando encuentra un valor que no se corresponde con la matriz identidad cambia la variable esIdentidad para salir inmediatamente de los bucles for y while, puesto que al primer valor incorrecto no hace falta seguir recorriendo la matriz, ya sabemos que no es de Identidad.
Vemos que para recorrer una matriz hace falta 2 bucles anidados, en este caso el while recorre las filas de la matriz y el for recorre las columnas para cada fila.



martes, 5 de marzo de 2013

Las variables booleanas

Nos referimos a variables booleanas a aquellas que utilizamos para indicar que algo es verdadero o falso.

Lo importante de estas variables es que sólo pueden tomar dos valores: verdadero o falso, no hay más posibilidades y esta propiedad la utilizaremos para tomar decisiones, por ejemplo: tengo una variable que se llama bTarifaMenor y que es verdadera si tengo una variable edad de tipo entero <= 12 y en caso contrario será falsa. Podríamos decir que si la variable bTarifa Menor es verdadera aplicaremos un descuento del 20% en el precio de un producto.

La definición de estas variables dependerá del lenguaje de programación que estemos utilizando. No podemos encontrar con los tipos: booblean, bool, Boolean, Bool. En cuanto tengamos claro cual de los tipos es el que utiliza el lenguaje con el que estamos programando definiremos la variable:

Para c# definiríamos así:
bool bTarifaMenor; //definimos la variable booleana
bTarifaMenor = False; //inicializamos la variable con valor falso

int edadCliente = 13; //definimos e inicializamos la variable edad en 13

Para aplicar la lógica de decisión que evalúa el valor de la variable edadCliente utilizamos la instrucción if que sigue la siguiente sintaxis:

if (condición que se evalúa)
{
  //Entre estas llaves va el conjunto de instrucciones que se ejecutan si se cumple
  //la condición que se evalúa
}

aplicando la instrucción de evaluación if en el ejemplo:

//la condición de evaluación es que la edad del cliente sea menor o igual que 12
//dejamos la referencia de los operadores disponibles que iremos aplicando en los ejemplos
if (edadCliente <= 12)
{
  bTarifaMenor = True; //asignamos el valor de verdadero a la variable booleana
}

Las llaves “{“ y “}” contienen un conjunto de instrucciones que sólo se ejecutarán si se cumple la condición que se evalúa dentro del paréntesis, si ese conjunto de instrucciones consta de una sola instrucción como es el caso del ejemplo, se pueden obviar las llaves:

if (edadCliente <= 12)
  bTarifaMenor = True; //asignamos el valor de verdadero a la variable booleana

Sin embargo, si Ud. está empezando a programar le recomiendo que utilice siempre las llaves,  así podrá distinguir claramente cuáles son las instrucciones que se ejecutarán en el caso que se cumpla la condición del if.


Para terminar el ejemplo, aplicaremos el descuento a los menores utilizando como condicional a la variable booleana:

if (bTarifaMenor)
{
 //aquí hace las instrucciones necesarias para aplicar el 20% de descuento en el precio
}

En el caso de este if la condición que se evalúa es simplemente una variable booleana, por que en sí esta variable es True o False, en el caso que su valor sea True se ejecutará el bloque de instrucciones que se encuentra entre las llaves (descuento en el precio).


Aquí más información sobre la instrucción if