El objetivo de este ejercicio es crear un programa que juegue a tres en raya contra un oponente humano. Tras cada movimiento el programa debe mostrar el tablero y permitir mover al humano. El programa debe detectar en qué momento se ha obtenido tres en raya. Con objeto de aclarar la dinámica del juego se muestra un ejemplo de la salida del programa por pantalla. En este ejemplo el programa realiza el primer movimiento y usa el simbolo “X”. Las nueve posibles posiciones del tablero se designaran con los números del 0 al 8: 0 | 1 | 2 ---+---+--3 | 4 | 5 ---+---+--6 | 7 | 8 EJEMPLO DE PARTIDA Pongo en la casilla: 4 El tablero queda como: | | ---+---+--| X | ---+---+--| | Donde quieres poner?: 0 Pongo en la casilla: 8 O | | ---+---+--| X | ---+---+--| | X Dónde quieres poner?: 2 Pongo en la casilla: 1 O | X | O ---+---+--| X | ---+---+--| | X 1 Dónde quieres poner: 3 Pongo en la casilla: 7 O | X | O ---+---+--O | X | ---+---+--| X | X Juego terminado. Gané! Para escribir un programa que juegue a tres en raya, debes tener en cuenta los siguientes puntos: 1. decidir qué tipo de estrategia va a seguir el programa. 2. decidir qué tipo de estructuras de datos vas a usar para representar el tablero, la posición de las fichas y la detección de las jugadas ganadoras 3. descomponer el problema en módulos pequeños y sencillos implementados si es posible como funciones sencillas y bien definidas. La estrategia Para ayudaros a comenzar sugeriré una estrategia para el ordenador (que juega con Xs): 1. Si tengo dos en raya colocar la tercera X (si es posible). 2. Si (1) no es posible y hay dos Os en raya colocar una X para bloquear la línea 3. Si (1) y (2) no son posibles y el centro (posición 4) esta libre poner una X en él. 4. Si (1), (2) y (3) no son posibles y cualquiera de las esquinas está libre (0,2,6,8) poner una X en las esquinas 5. Si (1), (2), (3) y (4) no son posibles poner una ficha al azar. La primera decisión a tener en cuenta es cómo representar el tablero. Una posibilidad es usar un array bidimensional tablero[3][3], donde el primer índice se refiere a la fila y el segundo a la columna. Otra posibilidad es usar un array unidimensional de dimensión nueve, donde los índices del 0 al 8 representan las distintas 2 posiciones. El valor de cada elemento debe indicar si la casilla contiene una X, una O, o esta vacía. Así pues decide si usar un array bidimensional o unidimensional y qué tipo de array (char, int, float) vas a usar. Si utilizas la estrategia descrita arriba, tendrás que detectar dos en línea (ya sea X ó O). Ya sea horizontal, vertical o diagonalmente. Por ejemplo, las combinaciones siguientes son algunas de las posibles combinaciones de X que dan dos en raya: | | X | | X | | ---+---+--- ---+---+--- ---+---+--| | X | | | | X ---+---+--- ---+---+--- ---+---+--| | | | X | | X También tendrás que detectar tres en raya (esto es, si has ganado o perdido). Hay ocho posibles combinaciones ganadoras: 3 filas, 3 columnas y 2 diagonales. Una posiblidad para detectar esta situación es comprobar si cualquiera de las siguientes ternas de casillas están ocupadas por Xs ó por Os. Usando la codificación descrita arriba, las posiciones ganadoras son: (1) (2) (3) (4) (5) (6) (7) (8) 0 3 6 0 1 2 0 2 1 4 7 3 4 5 4 4 2 5 8 6 7 8 8 6 Almacena estas ocho configuraciones en un array y usando un bucle comprueba si en alguna de estas 8 posibles combinaciones hay algún tres en raya o dos en raya. Recuerda que tambien tienes que comprobar si se ha empatado Descomposición del problema Siempre que sea posible divide el problema en pasos más sencillos y no intentes escribir el programa directamente desde el principio. A continuación os descompongo el problema en pasos más sencillos. 3 1. Escribe un programa que permita al usuario introducir un movimiento, rellene la casilla correspondiente en el tablero y muestre el tablero por pantalla. Esto es, por ahora ignorar el juego, sencillamente escribir un bucle que muestre el tablero y permita al usuario introducir su próximo movimiento. 2. Añade unas pocas líneas más de código que comprueben si el usuario ha ganado (hay tres Os en raya). Si esto ocurre el programa debe terminar. 3. Añade unas cuantas líneas más para conseguir que el ordenador juegue aleatoriamente (ponga una X en una casilla al azar cuando le toque el turno). Debe comprobar si alguien ha ganado o se da un empate 4. Modifica un poco más el programa de forma que la estrategia descrita arriba se siga. Extras: Una vez implementado el programa juega un poco con él. Si el ordenador mueve primero, es difícil ganarle pero no imposible. De hecho es posible hacer un programa un poco más listo hasta el punto de que no sea posible derrotarle. A continuación se propone una estrategia para implementar dicho programa; la clave consiste en escribir una función de coste que sea capaz de evaluar cuan buena es una posición. Esta función debería tomar el tablero (la posición de un conjunto de Xs and Os) como argumento y devolver un valor indicando sus posibilidades de éxito. A continuación se describe en pseudicódigo un posible algoritmo: mejor_puntuacion = -10000; bucle sobre cada casilla del tablero Si la casilla esta vacia entonces: Coloca una X en la casilla puntuacion = evalua_tablero(tablero); Si (puntuacion > mejor_puntuacion) entonces mejor_puntuacion = puntuacion almacena la casilla con mejor_puntuacion fin_del_Si borra la X del tablero fin_del_Si fin del bucle devuelve la casilla que proporciona la mejor_puntuacion 4 Este pseudocódigo detecta todas las casilla libres. Colocará una X en cada casilla libre y calcula la función de coste (cuan buena es la posición para el ordenador). Al final devuelve la casilla que maximiza la función de coste. Una posible función de coste es contar el valor de una en raya, dos en raya y tres en raya, tanto para Xs como para Os y devolver un valor basado en el número de ocurrencias. Podéis comenzar con la siguiente función y probar alternativas: puntuacion = -1000 * O2raya - O1raya +1000 * X3raya + 10 * X2raya + X1raya donde O2raya es el número de dos en raya que tiene el humano, X3raya es el número de tres en raya que tiene el ordenador, etc. (Recuerda que esta función se llama despues de que el ordenador imagine un movimiento y que por lo tanto no puede haber tres Os en raya). 5