Contenido del curso

Fundamentos de Programación

Desarrollando un juego con HTML y JavaScript

Estilos con CSS

Optimización de código

Mapa con canvas

Backend: videojuego multijugador

Secuencia de ataques aleatorios del enemigo

Resumen

Construir un juego por turnos en JavaScript implica algo más que registrar la jugada del usuario: necesitas que el enemigo también arme su propia secuencia de ataques para poder comparar resultados. Aquí aprendes a generar esa secuencia aleatoria, guardarla en un arreglo y sincronizarla con la jugada del jugador para luego validar victorias.

Por qué cambiar de vidas a victorias en el juego

La lógica original del juego usaba tres vidas por lado, pero ahora la mecánica gira en torno a cinco ataques por jugador y conteo de victorias. Con cinco botones disponibles, cada partida produce cinco enfrentamientos y gana quien acumule más triunfos en esa secuencia.

Esto abre tres escenarios posibles:

  • Ganas tres y la máquina dos: victoria tuya.
  • Empatan dos a dos con un empate intermedio: empate.
  • La máquina se lleva cuatro y tú una: gana la máquina.

¿Por qué pasar de vidas a victorias? Porque al tener cinco botones disponibles, contar victorias por secuencia es más natural que restar vidas y permite validar empates, algo que la lógica anterior no contemplaba.

Cómo generar ataques aleatorios del enemigo según la mascota

El primer paso es dejar de usar un hardcode que limitaba los ataques del uno al tres. Como ahora cada moquepón tiene cinco ataques definidos en su constructor, conviene leerlos directamente del objeto seleccionado [03:30].

Dentro de la función seleccionarMascotaEnemigo se extrae el arreglo de ataques del personaje elegido por la máquina y se guarda en una variable como ataquesPokeponEnemigo. Para evitar errores de referencia, esa variable debe declararse arriba con let antes de asignarla.

Luego, en ataqueAleatorioEnemigo, el rango del número aleatorio se calcula con la longitud del arreglo:

javascript let ataqueAleatorio = aleatorio(0, ataquesPokeponEnemigo.length - 1);

Así, si mañana cada mascota tiene 15 ataques en lugar de 5, el rango se ajusta solo.

Cómo evitar que el índice cero quede sin ataque asignado

Un detalle clave: si el random arranca en cero pero las validaciones empiezan en uno, el cero queda huérfano y no asigna nada. La solución es ampliar el if con tablas de la verdad para cubrir los cinco índices [05:40]:

  • Si ataqueAleatorio es 0 o 1: agrega fuego.
  • Si ataqueAleatorio es 2 o 3: agrega agua.
  • En cualquier otro caso: agrega tierra.

Cómo guardar la secuencia del enemigo en un arreglo con push

La variable que almacena los ataques del enemigo no puede ser una variable cualquiera: tiene que ser un arreglo, porque vas a meterle cinco elementos uno tras otro. Si la declaras como variable simple, al llamar .push el navegador devuelve el error Cannot read property push of undefined [07:15].

La corrección es inicializarla así:

javascript let ataqueEnemigo = [];

Con eso, cada validación del if puede agregar un elemento sin romper la ejecución:

javascript ataqueEnemigo.push('fuego');

¿Qué hace el método push en JavaScript? Agrega un nuevo elemento al final de un arreglo existente. Solo funciona sobre arreglos, no sobre variables que guardan un único valor.

Cómo sincronizar el ataque del jugador con el del enemigo

Al mandar a llamar la función del enemigo, aparece un comportamiento raro: el enemigo selecciona un ataque antes de que el jugador toque algún botón. Esto pasa porque la llamada estaba fuera del forEach que asigna el evento de clic, así que se ejecutaba apenas cargaba la función [09:50].

La solución es mover la llamada a ataqueAleatorioEnemigo dentro del bloque que se dispara con cada clic. El flujo correcto queda así:

  1. La función registra el evento de clic en cada botón mediante forEach.
  2. El jugador hace clic y se guarda su ataque en el arreglo del jugador.
  3. Inmediatamente después, se ejecuta la función del enemigo y se agrega su ataque al arreglo enemigo.
  4. El ciclo se repite hasta completar las cinco selecciones.

Para verificar que todo funciona, un console.log(ataqueEnemigo) dentro de la función del enemigo permite ver en la consola la secuencia que se va construyendo en paralelo a la del jugador.

Cómo distinguir en consola la secuencia propia y la del enemigo

Cuando ambos console.log imprimen al mismo tiempo, basta con revisar la línea que reporta la consola. Por ejemplo, la línea 173 corresponde a secuenciaAtaque (jugador) y la 202 a ataqueAleatorioEnemigo. Así confirmas que cada arreglo guarda lo que debe.

¿Por qué el enemigo atacaba antes de que yo hiciera clic? Porque la función del enemigo se llamaba fuera del listener de clic. Al moverla dentro del forEach que escucha el evento, el enemigo solo ataca después de cada selección del jugador.

Qué falta para validar quién gana cada combate

Con los dos arreglos listos, uno con tu apuesta y otro con la jugada de la máquina, ya tienes la materia prima para comparar. Sin embargo, el juego sigue semiroto: los contadores muestran valores como -7 o 3 porque la lógica original bloquea botones cuando las vidas llegan a cero, y ese sistema ya no aplica.

Lo que viene es ajustar esa validación para que acepte cinco rondas y cuente victorias en lugar de restar vidas. ¿Cómo crees que conviene comparar los dos arreglos elemento por elemento? Cuéntame en los comentarios cómo lo resolverías antes de pasar a la siguiente clase.