CodeGym /Blog Java /Random-ES /Resumen del maratón de Java: escribiendo el juego "Tres e...
Hanna Moruga
Nivel 20
Seattle

Resumen del maratón de Java: escribiendo el juego "Tres en Raya"

Publicado en el grupo Random-ES

Información general sobre el proyecto en el programa de formación en Java

Introducción a la plataforma CodeGym y a la sección de "Juegos"

Resolverás todos los desafíos (escribirás código) en la plataforma CodeGym. El proyecto de creación de un juego está dividido para tu comodidad en 24 partes, o subtareas:
  • Cada subtarea es la implementación de una acción/lógica específica.
  • La corrección de cada tarea se puede verificar automáticamente, y obtendrás el resultado en segundos utilizando el validador de CodeGym, tu asistente virtual en el complemento en línea para escribir código.
  • Si hay algo incorrecto en tu código, el validador te indicará exactamente qué condiciones del problema no se han implementado en tu solución.

Resumen de la sección "Juegos" y del proyecto que crearás

Para comenzar a trabajar en el proyecto, abre la sección "Juegos" y haz clic en la tarjeta con el juego "Tres en Raya": Resumen del maratón de Java: escribiendo el juego "Tres en Raya" - 1Después de esto, verás la descripción del juego y una simulación en video de cómo debería verse cuando esté completado. Para empezar a trabajar en el proyecto, haz clic en el botón "Escribir tu solución". A continuación, aparecerá una ventana con el complemento web de CodeGym (webIDE), una versión en línea del entorno de desarrollo: Resumen del maratón de Java: escribiendo el juego "Tres en Raya" - 2Este es nuestro simulador en línea que te permite escribir tu propio código, corregirlo, enviarlo para su revisión y obtener el resultado de si tu solución está correcta. En el campo a la derecha, encontrarás la descripción y las condiciones para realizar la tarea. Lee cuidadosamente las condiciones de la tarea antes de empezar y luego comienza a trabajar con el código en el campo de la izquierda.

Las funciones principales del complemento web CodeGym son

Resumen del maratón de Java: escribiendo el juego "Tres en Raya" - 3
  1. Verificación: Utiliza el validador para verificar si tu solución es correcta. Al presionar este botón, obtendrás el resultado en pocos segundos.
  2. Ayuda: Ofrece diversas funciones de ayuda con el código:
    • Ayuda de la comunidad: Ve a la sección de "Ayuda" para discutir esta tarea, hacer tus preguntas o aprovechar la información de discusiones existentes. Sin embargo, te recomendamos discutir tus soluciones en el chat comunitario de Telegram de CodeGym, ya que el juego "Tres en Raya" está diseñado específicamente para el programa de formación, y solo sus participantes lo están desarrollando.
    • Solución correcta: Te permite ver una versionde la solución correcta para la tarea (pueden haber varias soluciones correctas). Recomendamos usar esto solo en casos excepcionales. Si sigues atentamente las sesiones con el mentor, podrás hacerlo sin mirar la solucion.
    • Revertir mi código: Te permite volver a tu propia solución sin pistas.
    • Restablecer la solución: Elimina el código escrito por ti y comienza de nuevo desde cero.
  3. Ejecución: Despliega el código sin verificar la solución (probar como funciona el codigo).
  4. Análisis del código: Permite obtener recomendaciones para mejorar tu código.
Después de escribir una solución que pase la verificación, podrás pasar a la siguiente tarea en la creación del juego.

Cómo entregar las tareas

Todas las tareas completadas serán evaluadas por un asistente virtual, un validador incorporado en la herramienta en línea para codificar en el sitio de CodeGym (anteriormente JavaRush). Proporcionará una respuesta en cuestión de segundos. Sin embargo, también necesitamos estar al tanto de tus éxitos en el programa de entrenamiento. Para que los mentores del programa de entrenamiento registren tu tarea y tengas la oportunidad de competir por regalos de CodeGym, envía a través del bot de Telegram antes del plazo (17:00 del día siguiente a la sesión) una captura de pantalla en la que se vea claramente: 1️⃣ Ventana del complemento web de CodeGym 2️⃣ Número de la tarea. 3️⃣ Resultado exitoso de la verificación. Todo como en esta captura de pantalla: Resumen del maratón de Java: escribiendo el juego "Tres en Raya" - 4

Corta introducción a la programación en Java

1. Conceptos clave de Java que serán útiles conocer

POO — Programación Orientada a Objetos. Java es un lenguaje de programación orientado a objetos. Esto significa que todo lo que se crea en el programa debe ser creado en forma de objeto. Programa — es un conjunto (lista) de comandos. Inicialmente, se ejecuta el primer comando, luego el segundo, el tercero, etc. Cuando se han ejecutado todos los comandos, el programa se completa. Las programas en Java son ejecutadas por la JVM (Java Virtual Machine — Máquina Virtual de Java). La JVM es un programa especializado que puede ejecutar programas escritos en Java.

Principios básicos de escritura de comandos

Principio primero: en Java, se acostumbra escribir cada comando en una nueva línea. Al final de cada comando se coloca un punto y coma:

System.out.println("Hola, futuro programador");
Principio segundo: un programa no puede simplemente consistir en comandos. Los comandos de Java deben estar dentro de métodos, y los métodos deben estar dentro de clases. La jerarquía general se puede describir así: los programas en Java están compuestos por clases, las clases contienen métodos, y los métodos contienen comandos.

Principios importantes de formato de código

  • No olvides poner un punto y coma ; al final de cada comando que crees.
  • Cada corchete o comilla de apertura, como (, {, ", debe tener un corchete o comilla de cierre correspondiente: ), }, ".
  • Si tu código se resalta en rojo, significa que hay un error; observa más detenidamente.
  • Utiliza las sugerencias automáticas y el autocompletado; te ayudarán a escribir código correctamente.
  • Recuerda que los nombres de tus variables, métodos y clases deben ser legibles, es decir, que sus nombres deben indicar claramente qué hacen y para qué están destinados.

Resumen de la sesión #1: creación del esquema del juego

Contenido de la sesión

  • Creamos una cuadrícula de juego 3x3 (método initialize())
  • Creamos el modelo de juego y su representación visual +
  • Inicializamos las variables en las que el juego almacenará sus estados (métodos startGame())
  • Implementamos la visualización de la celda (método updateCellView())
  • Implementamos la visualización de todas las celdas en la matriz del modelo en el campo de juego (updateView())
  • Configuramos la captura de clics del ratón (método onMouseLeftClick())
En el desarrollo del juego Tres en Raya, trabajaremos con la clase pública (public) TicTacToe, que hereda de la clase Game. Esta es una clase escrita por los desarrolladores de CodeGym y contiene un conjunto de métodos que te ayudarán a escribir tu propio juego.

1. Creando la cuadrícula de juego

Entonces, necesitamos hacer un campo de juego de 3x3. Esto se puede lograr llamando al método setScreenSize(ancho, alto);. Este código se escribe en el método desde el cual comienza nuestro juego: public void initialize();. Donde:
  • public: significa un método público que puede ser utilizado fuera de nuestra clase.
  • void: es un valor que indica que el método no devuelve nada.
Para empezar, necesitas crear este método y dentro de él llamar al método setScreenSize().

2.1. Creación del Modelo de Juego y su Representación

Los juegos de este tipo constan de dos partes: el modelo y la representación. La representación es lo que ve el jugador (nuestro campo de juego). El modelo es toda la información que guarda el estado del juego. Así que, además del campo de juego, necesitamos crear el modelo: un array donde se almacenarán los datos. En nuestro caso, un array cuadrado.
  • private: significa un método privado que solo se utilizará dentro de nuestra clase.
  • []: los corchetes cuadrados indican un array cuadrado.
En nuestro array bidimensional, se utilizarán los siguientes números para representar lo que sucede en el campo de juego:
  • 0: vacío (celda vacía)
  • 1: X (movimiento del primer jugador que coloca una cruz)
  • 2: O (movimiento del segundo jugador que coloca un círculo)

2.2. Fijando al Jugador Actual

Después de la creación del modelo, es necesario crear una variable private int currentPlayer, en la cual recordaremos qué jugador está actualmente en turno (1 — primer jugador, 2 — segundo jugador).

3. Inicializando las variables donde el juego guarda sus estados

Creamos un método para inicializar el modelo: public void startGame().
  • Para llenar el array con ceros, utilizamos dos bucles for anidados.
  • Asignamos el valor 1 a la variable currentPlayer (1 — movimiento del primer jugador).
El campo de juego se llama representación, o view. Así que, public void updateView() es el método para actualizar nuestra representación (campo de juego). El método startGame() debe ser llamado en algún lugar. Agregue la llamada al método startGame() al final del método initialize().

4. Implementando la visualización de la celda

Ahora, después de la actualización, necesitamos mostrar en la celda correcta (con coordenadas x, y) el valor correcto (después del movimiento del jugador). Para esto, crearemos el método: public void updateCellView(). setCellValue — es un método para mostrar el valor en la celda, ya escrito en el motor de juego de CodeGym. La lógica del método updateCellView(int x, int y, int value):
  • Si el valor (value) es igual a 0, en la celda se debe mostrar una cadena vacía: " " (un espacio en blanco).
  • Si el valor (value) es igual a 1, en la celda se debe mostrar "X" (una letra mayúscula 'X').
  • Si el valor (value) es igual a 2, en la celda se debe mostrar "O" (una letra mayúscula 'O').

5. Implementando la visualización de todas las celdas del array model en el campo de juego

Crea el método public void updateView() para mostrar todas las celdas del array model en el campo de juego. Añade la llamada a este método al final del método initialize(). Dentro del método updateView(), debes recorrer todas las celdas del array model y mostrar el valor de cada una en la pantalla:
  • Para esto, necesitas escribir dos bucles anidados que recorran todas las celdas del array model.
  • Utiliza la llamada al método updateCellView(x, y, value) para mostrar el valor de cada celda en la pantalla.

6. Necesitamos el método onMouseLeftClick(). Este método se llamará cuando el usuario haga clic en el campo de juego con el botón izquierdo del ratón, y se le pasarán las coordenadas x, y del campo de juego donde hizo clic el usuario. Dentro del método onMouseLeftClick(), debes hacer tres cosas:
  • Escribir el valor currentPlayer en la celda model[x][y].
  • Mostrar el modelo en la pantalla llamando al método updateView().
  • Cambiar al jugador actual. Cambiar 1 a 2 y 2 a 1.
El método updateView permite que los cambios realizados en el modelo se reflejen en la pantalla, en el campo de juego.

Tarea

  1. Recrea todo lo que hizo el mentor en la lección en video: escribe seis métodos que ayudarán a crear la estructura del juego en las sub tareas 1-6.
  2. Completa independientemente la sub tarea No. 7. Colorea la X en rojo y la O en azul. Utiliza para ello el método setCellValueEx().

Resumen para la Lección #2: Agregando Turnos Secuencialmente

Para continuar trabajando en el proyecto, abre la sección "Juegos" y haz clic en la tarjeta del juego de Tres en Raya. Si tienes una cuenta activa, tu progreso en el desarrollo del juego se guarda. Simplemente abre la tarjeta del juego y continúa trabajando en las tareas.

Contenido de la Lección

  • Implementar la verificación de si una celda está ocupada (verificar en el método onMouseLeftClick()).
  • Establecer el estado de finalización del juego (isGameStopped(), startGame()).
  • Especificar la condición de que no se permite hacer clic cuando el juego ha terminado (verificar en el método onMouseLeftClick()).
  • Implementar la verificación de la condición de victoria (método checkWin()).
  • Agregar un mensaje de victoria al juego.

1. Verificamos si hay un símbolo en la celda

Comencemos prohibiendo colocar cruces/círculos en una celda que ya contiene algo. Para lograr esto, es necesario agregar una verificación en nuestro método onMouseLeftClick() utilizando una declaración condicional if.

2. Fijamos el fin del juego y prohibimos al jugador realizar un movimiento después de esto

También necesitamos evitar que el jugador realice un movimiento si el juego ya ha terminado. Para ello, necesitamos un estado de finalización del juego, que será representado por una variable private boolean llamada isGameStopped. Su valor inicial será false. Debemos agregar la verificación de si el juego ha terminado al método onMouseLeftClick(). Si el juego está detenido, interrumpimos la ejecución del método onMouseLeftClick() utilizando la declaración return.

3. Verificamos la victoria

Para determinar si el juego ha terminado y hay un ganador, agregamos un método de verificación llamado checkWin():

public boolean checkWin(int x, int y, int player)
Este método toma las coordenadas de la celda en la que se ha colocado un símbolo (X o O) y el número del jugador que hizo el movimiento. El método es de tipo booleano porque debe verificar si hay un ganador o no. Devolverá true en caso afirmativo y false en caso contrario. Debes escribir este método después del método que realiza el movimiento del jugador actual, pero antes de pasar el turno al siguiente jugador.

4. Agregamos el mensaje de victoria en el juego

Primero, al final del método onMouseLeftClick(), antes de cambiar al siguiente jugador, debemos agregar la siguiente verificación: si hay un jugador que ha ganado, a) detener el juego, b) mostrar al ganador:
  • Si checkWin() devuelve true, entonces debemos establecer la variable isGameStopped en true.
  • Mostrar al ganador utilizando la llamada al método showMessageDialog().
  • Finalizar la ejecución del método.
Luego, creamos el método que mostrará el mensaje en caso de victoria de uno de los jugadores: showMessageDialog(). En los paréntesis, podemos establecer el texto del mensaje y su color. Utiliza los siguientes parámetros:
  • cellColor — color de la ventana de diálogo
  • text — texto del mensaje
  • textColor — color del texto
  • textSize — tamaño del texto en porcentaje de la altura de la ventana

Tarea

  1. Reproduce todo lo que hizo el mentor en el video en los subtareas 8-11.
  2. Realiza de forma independiente el subtarea 12. Adicionalmente, escribe una comprobación que muestre si las casillas están llenas diagonalmente (en ambas direcciones) con tres cruces o ceros para completar la verificación de si algún jugador ha ganado. Esto debe hacerse en el método checkWin(). El método debería devolver true si hay una línea vertical, horizontal o diagonal llenada con el valor n. De lo contrario, el método debería devolver false.

Resumen de la lección #3: Reinicio del juego

Contenido de la lección

  • Extraemos el código a un método llamado setSignAndCheck().
  • Implementamos la verificación para un empate.
  • Añadimos la verificación de si hay una casilla vacía en el campo de juego (método hasEmptyCell()).
  • Implementamos el reinicio del juego con el método onKeyPress().
  • Agregamos la opción de reiniciar un juego no finalizado.

1. Extraemos nuestro código a un método llamado setSignAndCheck()

Es el momento de realizar una pequeña refactorización en nuestro código. Refactorización (del inglés refactoring) es un cambio en la estructura interna de un programa que no afecta su comportamiento externo. Básicamente, es simplificar y mejorar el código existente para darle una apariencia más compacta y comprensible, aumentar la productividad y evitar errores en el código en el futuro. Necesitamos extraer parte del código del método onMouseLeftClick() (dedicado al movimiento del jugador y la verificación de la victoria en el juego) a un método separado: public void setSignAndCheck(int x, int y). En el video, el mentor demuestra cómo hacerlo. En el método onMouseLeftClick(), reemplace todo este código con la llamada setSignAndCheck(x, y).

2. Implementamos la verificación de empate

¿Qué hacer en caso de que el juego termine, no haya celdas disponibles para un movimiento y no se pueda determinar un ganador? Necesitamos agregar en el código una manejo para el empate como resultado del juego. Crea un nuevo método: public boolean hasEmptyCell(). Este método verificará si todavía hay celdas vacías en el campo. En este método, debemos recorrer todos los valores en la matriz model y devolver true si al menos un valor es igual a cero. De lo contrario, el método debe devolver false.

3. Añadimos la verificación de si hay celdas vacías en el campo de juego

Si no quedan celdas vacías en el campo y no hay un ganador, necesitamos mostrar un mensaje de empate. Al final del método setSignAndCheck(), utilizando hasEmptyCell(), debemos verificar si hay celdas vacías en el campo y, si no las hay, debemos finalizar el juego:
  • Mostrar un mensaje de empate.
  • Establecer el valor de isGameStopped en true.

4. Añadimos el reinicio del juego

La condición para reiniciar el juego y restablecer todos los resultados anteriores será presionar la tecla de espacio. Para lograr esto, necesitamos sobrescribir el método que ya existe en la clase Game (nuestro motor de juego). Elige el método onKeyPress, que es precisamente lo que necesitamos. En el método, debemos agregar un bucle con la siguiente lógica: si nuestro juego ha terminado y el usuario presiona la tecla de espacio (SPACE), entonces debemos volver a inicializar el modelo y actualizar la vista (representación del juego).

5. Añadimos el reinicio de un juego no terminado

También agregamos la posibilidad de reiniciar un juego no terminado en cualquier momento presionando Escape. Si el usuario presiona ESC, debemos reiniciar el juego. La lógica anterior también debe funcionar: si el usuario presiona espacio y el juego ha terminado, debemos reiniciar el juego. Ejemplo de verificación de la tecla de espacio:

if (key == Key.SPACE) { ... }

Tarea

  1. Reproduce todo lo que hizo el mentor en el video en las sub-tareas 13-17.
  2. Realiza de manera independiente la sub-tarea N.º 18. Reescribe el texto de los mensajes: en lugar de "Player N wins" — "You win", en lugar de "Draw" — "Game over".
    • "You Win!" debe mostrarse en color verde, si el primer jugador gana.
    • "Game Over" debe mostrarse en color rojo, si el primer jugador pierde — el segundo gana.
    • Los cambios deben realizarse en el método setSignAndCheck().

Resumen de la lección #4: agregamos la lógica para los turnos de la computadora

Contenido de la lección:

  • Creación del método para el turno de la computadora — computerTurn().
  • Enseñanza al computador para realizar movimientos.
  • Creación del método checkFutureWin(), que prevé la victoria del jugador.
  • Mejora de la lógica del juego de la computadora.

1. Agregamos los movimientos de la computadora

Para incorporar los movimientos de la computadora, utilizamos el método public void computerTurn() y agregamos una condición para que la computadora siempre realice un movimiento en la casilla central si está libre después del movimiento del jugador, de lo contrario, realizará un movimiento en una casilla adyacente. El método computerTurn() debe ser llamado al final del método onMouseLeftClick() y después de esto, se cambia nuevamente al jugador actual: currentPlayer = 3 - currentPlayer;.

2. Enseñamos a la computadora a "moverse"

El método computerTurn() debe realizar un movimiento en una celda específica. Al decir "moverse a una celda", nos referimos a llamar al método setSignAndCheck() con las coordenadas de la celda. Es necesario implementar dos estrategias simples:
  • Verificar si la celda central está libre y, si es así, moverse a ella.
  • En caso contrario, moverse a la primera celda libre encontrada.
Importante: solo se debe realizar un movimiento, no más. Si la computadora realiza un movimiento, el método computerTurn() debe finalizarse.

3. Prever la victoria del jugador

Para complicar la "lógica" de la computadora, necesitaremos el método checkFutureWin(). Añade el método public boolean checkFutureWin(int x, int y, int n). Debe devolver true si el jugador n gana el juego después de realizar un movimiento en la celda (x, y). De lo contrario, el método debe devolver false.

4. Mejoramos la lógica del juego de la computadora

Conectamos los métodos computerTurn() y checkFutureWin() para mejorar la lógica del método computerTurn(). Después de verificar la celda central, agrega la siguiente lógica: recorremos todas las celdas del array model y verificamos: si es posible ganar el juego haciendo un movimiento en la celda (x, y), entonces realiza un movimiento en la celda (x, y).

Tarea

  1. Reproduce todo lo que hizo el mentor en el video de la sesión en los subtareas 19-22.
  2. Realiza de forma independiente la tarea número 23. Mejora el método computerTurn(): escribe el método checkEnemyWin(), que prevé la victoria del oponente e interfiere con él.
La nueva lógica del método computerTurn() debe ser la siguiente:
  • Intenta hacer un movimiento en la casilla central.
  • Haz un movimiento si puedes ganar en un solo movimiento.
  • Obstaculiza al oponente si puede ganar.
  • Haz un movimiento en la primera casilla vacía que encuentres.
¡Aquí está todo! ¡Eres un campeón!

Importante: la tarea número 24 es tu espacio para personalizar aún más el juego. Tal vez quieras cambiar, mejorar o agregar algo a tus "Tic-Tac-Toe" para que el juego sea único.

Si te gusta el juego tal como está y no planeas escribir código adicional, simplemente haz clic en "Verificación", el validador evaluará tu código y podrás publicar el juego terminado.

Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION