Fundamentos de Programación

1

Bienvenida a Platzi: ¿qué necesitas para tomar el curso?

2

¿Cómo aprender programación?

3

Crea tu primer sitio web

4

Sitios web con HTML

5

Estructura de árbol en HTML

6

Instalando tu primer editor de código

7

Cómo declarar variables y usar prompt

8

Algoritmo de piedra, papel o tijera

9

Algoritmo avanzado de piedra, papel o tijera

10

Aleatoriedad

11

Refactor del código usando funciones

12

Ciclos

13

Gana 3 veces

14

Archivos de HTML y JavaScript

15

¿Qué es el DOM?

Quiz: Fundamentos de Programación

Desarrollando un juego con HTML y JavaScript

16

Maquetación con HTML

17

Sección de elegir mascota

18

¿Dónde ubicar la etiqueta script? Conectando HTML con JavaScript

19

Escuchando eventos con JavaScript

20

addEventListener

21

Manipulación del DOM

22

Enemigos aleatorios

23

Ataques en JavaScript

24

Ataques aleatorios del enemigo

25

Imprimiendo ataques del enemigo

26

¿Ganaste, perdiste o empataste?

27

Tablas de verdad

28

Creando el contador de vidas

29

¿Quién ganó el juego?

30

Reiniciando el juego

31

Ocultando elementos HTML con JS para mejorar la UX del juego

Quiz: Desarrollando un juego con HTML y JavaScript

Estilos con CSS

32

Anatomía de CSS

33

Tipos de display

34

Flexbox

35

Modelo de caja

36

Imágenes para los Mokepones

37

Estilos del botón

38

Adaptando HTML al diseño del juego

39

Layout: título y ataques

40

Adaptando JavaScript al diseño del juego

41

CSS Grid

42

Responsive Design

43

Detalles finales

Quiz: Estilos con CSS

Optimización de código

44

Revisión de código

45

Don't repeat yourself (DRY)

46

Clases y objetos

47

Clases y objetos de Mokepon

48

Arrays o arreglos

49

Objetos vs. arreglos

50

Ciclos: manipulando el DOM con iteradores

51

Declaración lenta de variables

52

Una sola fuente de la verdad

53

Mascotas aleatorias con arreglos

54

Ataques dinámicos por cada mascota: extraer

55

Renderizado dinámico en HTML

56

Eventos de click dinámicos

57

Secuencia de ataques del enemigo

58

Iniciando el combate

59

Resolviendo el reto de condicionales

60

Optimizando el frontend del juego

Quiz: Optimización de código

Mapa con canvas

61

Introducción a canvas: dibujando con JavaScript

62

Moviendo a Capipepo hacia la derecha

63

Movimiento hacia todas las direcciones

64

Movimientos con el teclado

65

Imágenes y personajes de fondo

66

Métodos en las clases

67

Obstáculos y colisiones

68

Combate entre mokepones colisionados

69

Mapa responsive

70

Botones bonitos y viewport

Quiz: Mapa con canvas

Backend: videojuego multijugador

71

¿Qué es backend?

72

Instalación de Node.js y NPM

73

Terminal de comandos y Node.js

74

Servidor web con Express.js

75

HTTP, localhost, servidores y puertos

76

Express.js y fetch: API REST con JavaScript

77

JSON y POST: mokepon online

78

Transmisión de coordenadas

79

Mokepones dinámicos en el mapa

80

Optimizando el mapa del juego

81

Batalla entre jugadores

82

Consumiendo la API de ataques del enemigo

Quiz: Backend: videojuego multijugador

Próximos pasos

83

Probando el juego en varios dispositivos

84

¿Y ahora qué curso tomar?

No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Secuencia de ataques del enemigo

57/84
Recursos

Ya tienes la lógica del mokepon que selecciona el usuario para el combate. Ahora, debes preparar al mokepon enemigo para que esté listo para combatir y determinar al ganador de la pelea.

Preparando los ataques del enemigo

Declara dos variables, ataquesMokeponEnemigo para almacenar un arreglo con los ataques del enemigo seleccionado y otra variable ataqueEnemigo donde se guardarán los ataques aleatorios para el combate.

let ataquesMokeponEnemigo;
let ataqueEnemigo = [];

Luego de que el jugador seleccione su mokepon a través de la función seleccionarMascotaJugador(), lanza la función seleccionarMascotaEnemigo() para ejecutar la misma lógica aleatoria para seleccionar un mokepon aleatorio y determinar sus ataques también de forma aleatoria.

function seleccionarMascotaJugador() {
    // ...
    seleccionarMascotaEnemigo()
}
function seleccionarMascotaEnemigo() {
    let mascotaAleatoria = aleatorio(0, mokepones.length - 1);
    spanMascotaEnemigo.innerHTML = mokepones[mascotaAleatoria].nombre;
    ataquesMokeponEnemigo = mokepones[mascotaAleatoria].ataques;
    secuenciaAtaque();
}

Una vez esté lista la lógica de los ataques del mokepon seleccionado por el usuario, lanzaremos la función ataqueAleatorioEnemigo() para preparar los ataques del enemigo.

function secuenciaAtaque() {
    botones.forEach((boton) => {
        boton.addEventListener('click', (e) => {
            // ...
            ataqueAleatorioEnemigo();
       })
   })
}

Con esta función, se selecciona un ataque aleatorio del mokepon enemigo para combatir contra los ataques del mokepon del jugador, cada vez que el mismo se selecciona un ataque.

function ataqueAleatorioEnemigo() {
    let ataqueAleatorio = aleatorio(0, ataquesMokeponEnemigo.length - 1);
    if (ataqueAleatorio == 0 || ataqueAleatorio == 1) {
        ataqueEnemigo.push('FUEGO');
    } else if (ataqueAleatorio == 3 || ataqueAleatorio == 4) {
        ataqueEnemigo.push('AGUA');
    } else {
        ataqueEnemigo.push('TIERRA');
    }
    console.log(ataqueEnemigo);
    combate();
}

La lógica para el combate está casi lista, tanto la lógica del mokepon y del usuario como el mokepon aleatorio. Solo resta un paso para finalizar la lógica de todo el combate de tu videojuego.


Contribución creada por: Kevin Fiorentino (Platzi Contributor)

Aportes 92

Preguntas 41

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

o inicia sesión.

Hola!! yo cambié un poquito el código porque entiendo que si dejamos solo en random la elección del enemigo de la secuencia de ataques no se está considerando el personaje elegido por el mismo, es decir, si el enemigo elige por ejemplo Hipodoge, el random de la secuancia de ataques del enemigo solo debería formarse por 3 aguas, 1fuego y 1 tierra (cualquier combinación de estos 5 elementos). No se si estoy interpretando mal la solución que se propone, pero en todo caso dejo mi aporte de como lo implementé en mi código.

La variable** ataquePC** contiene los ataques del personaje elegido por el enemigo, luego lo que hice fue ordenar estos ataques en forma random con el método sort()

ataquePC.sort(()=>Math.random()-0.5**)**;

De esta forma, el enemigo solo podrá atacar con una secuencia que corresponda al personaje elegido por la pc.

Se que no tiene que ver con el curso pero por aca lo dejo por si le es util a alguien mas, a estas alturas como esta un triz complicado para nosotros los primiparos en el tema, mi atencion se empezo a despersar, encontre esta herramienta para estar enfocada en el curso, en teoria contabiliza 25 min de trabajo y 5 min de descanso, suena una alarma para alertar, me es muy utiil

https://pomofocus.io/

El profe: “Super bien, cómo vas viendo el juego”

Yo:

Los errores te hacen mas fuerte, yo despues de terminar las clases del profe diego:

posdata: buen trabajo¡¡

Aqui mi solucion para que se tome en cuenta la mascota del enemigo y para que sus ataques no puedan repetirse:

let  newArray = []

function selectEnemyPet () {
  let randomPet = randomNumber(0, mokepones.length - 1);
  enemysPet.innerHTML = mokepones[randomPet].name;
  enemysAttack = mokepones[randomPet].attack;
  for (let ind in enemysAttack) {
    newArray.push(ind);
  }
 console.log(enemysAttack);
};

function setEnemyAttack () {
  console.log(newArray);
  let randomInd = randomNumber(0, newArray.length - 1);
  let randomAttack;
  if (newArray.length <= 1) {
    randomAttack = newArray[0];
  } else {
    randomAttack = newArray[randomInd];
  }

  console.log(randomAttack);

  if (enemysAttack[randomAttack].name === "🔥") {
    enemyAttackCounter.push("FUEGO");
  } else if (enemysAttack[randomAttack].name === "🌊") {
    enemyAttackCounter.push("AGUA");
  } else if (enemysAttack[randomAttack].name === "🌱") {
    enemyAttackCounter.push("TIERRA");
  }

  newArray.splice(randomAttack, 1);
  console.log(enemyAttackCounter);
};

NOTA: me tomo un laaarrrgo rato(horas) dar con la solucion, y estoy seguro que hay muchas soluciones posibles, asi que no te rindas y nunca pares de aprender!

alamaye en este punto ya siento más dificil seguirle el paso al profe. Me detengo mucho a analizar y comprender pero ME ENCANTA :3

jajajajajaja ahora el juego quedó como la máquinas electorales que utilizan en Venezuela. Hagas lo que hagas, siempre vas a perder.

Espero poder tener la capacidad de aprender y aplicar las lógicas que ha venido haciendo el prof en estas últimas clases en otros proyectos sin ayuda

Veo a muchas personas con experiencia en los comentarios, dando soluciones que a veces nosotros los nuevos ni comprendemos jajajaja… Estoy haciendo el curso tal cual y como lo hace el profesor con el fin de entender lo máximo posible y luego de culminarlo pasar a una de sus rutas desde 0 :´).

Creo que algo que pude confundir un poco, es que se están creando las funciones de manera implícita pero el hecho de que se defina allí, no significa que ocurra ahora mismo.

boton.addEventListener(‘click’, (e) => { }

Esto significa que estoy creando una funcion sin nombre, por lo que solo se ven los parentesis, y estoy pasandole como parámetro “e”, el cual es un objeto estandar del sistema y que estaba disponible en ese momento DENTRO de addEventListener… Entonces:

funcionSinNombre(e) se ejecutará correctamente, pero, no se puede llamar desde otro punto porque no tiene un nombre explícito… También puede resultar más dificil de depurar.

Me parece excelente como va el curso, pero hay conceptos que requieren práctica para que los más nuevos lo entiendan, y explicarlos un poquito podría potenciar su uso en la creatividad de todos. Yo soy nuevo en JavaScript, espero no equivocarme mucho y que les sea util.

Qué se hace en esta clase

Se asignan los ataques del enemigo, de manera aleatoria, guardándolo en un arreglo


Considerando los ataques que tiene el mokepón del enemigo

En la función ataqueAleatorioEnemigo() creo el siguiente código

// Variable que guarde un número (índice)
let i = aleatorio(0, ataquesMokeponEnemigo.length - 1)

/* Se valida ataque asignado según índice y se guarda el nombre en el array ataqueEnemigo */
if (ataquesMokeponEnemigo[i].nombre === '🔥') {
	ataqueEnemigo.push('FUEGO')
} else if (ataquesMokeponEnemigo[i].nombre === '🌊') {
  ataqueEnemigo.push('AGUA')
} else {
  ataqueEnemigo.push('TIERRA')
}

/// Se elimina ataque asignado a enemigo del arreglo ataquesMokeponEnemigo
ataquesMokeponEnemigo.splice(i, 1)

Un ligero cambio:


Sugiero que en vez de añadir un cambio de calor al botón después de ser seleccionado mejor sele agregue la propiedad disable, esto para evitar que vuelva a usar.

Muestro ejemplo:

Cada vez que veo que comete un error y no le puedo decir, automaticamente entro en MOD ANSIEDAD

Jajaja

Mis secuencias solo son TIERRA, TIERRA, TIERRA, TIERRA sin importar que seleccione, Tengo el código tal cual, A este punto es bien difcil y no entiendo casi nada, solo quiero acabar el curso por ansiedad geez T_T

y se supone que esto es programación básica, pero es muy interesante, por que hace que uno piense en las soluciones, aparte de que si uno pone atención hay otras cosas que se le puede agregar al codigo para que valla quedando mas pulido

Igual que algunos compañeros, me di cuenta que en la solución planteada por el profe no se tienen en cuenta los ataques del mokepon enemigo y si estos se repiten o no. Estuve intentando seguir la lógica de que una vez que elijamos un ataque, el enemigo elija un ataque también y así fue como me quedó.

Lo primero que hice fue crear un array global (enemyAttacks) para almacenar los números aleatorios que se convertirán en los ataques enemigos. Luego creé otro array global (enemySequence) en el que se almacena la secuencia de ataques enemigos ya transformados en emojis(los cuales he estado utilizando como ataques)
Luego, igual que el profe, declaré una variable y le agregué el número aleatorio entre 0 y 4 en este caso

function chooseEnemyAttack() {
    let randomAttack = randomNumber(0, (enemyMokeponAttack.length - 1))

Posteriormente utilicé el método includes para verificar si el número aleatorio randomAttack que se acaba de generar se encuentra en el array enemyAttacks.

    if (enemyAttacks.includes(randomAttack) === false)

Si la condición no se cumple (false)(el ataque no se repite)
entonces se agrega el numero aleatorio randomAttack al array enemyAttacks y se genera un nuevo condicional en el cual comparamos al array que contiene los ataques del mokepon enemigo enemyMokeponAttacks en la posicion randomAttack(que tiene como valor un numero de ataque que no se ha repetido, por ejemplo el 2) en su .name (que tiene por nombre el emoji correspondiente) con los distintos ataques 🔥, 💧 o 🍃 y si coincide, el ataque será agregado al array que contiene la secuencia de ataques enemigos enemySequence. Luego llama a la funcion que compara los ataques para dar una victoria (la cual se encuentra rota ahora mismo)

if (enemyAttacks.includes(randomAttack) === false) {
        enemyAttacks.push(randomAttack)
        if (enemyMokeponAttacks[randomAttack].name == "🔥") {
            enemySequence.push("🔥")
        }
        else if (enemyMokeponAttacks[randomAttack].name == "💧") {
            enemySequence.push("💧")
        }
        else {
            enemySequence.push("🍃")
        }

        battleResult()
    }

Y por último, si la condición en la que comparamos si el número aleatorio que se generó al inicio de la función randomAttack nos da como resultado true quiere decir que el número aleatorio se repite dentro del array de ataques enemyAttacks y se repetiría el ataque, asi que no se realiza el .push sino que se llama nuevamente a la funcion para que empiece de nuevo y logre encontrar un número que no se repita

    else {
        chooseEnemyAttack()
    }
}

Intenté explicar lo mejor que pude, espero que les sirva de ayuda!

Super F!
Se rompio mi codigo JS
Selecciono los ataques pero ninguno se registra y solo se queda alli el juego
Profe Diego ayudeeee

Sinceramente a este punto requiere bastante detenimiento entender que esta pasando, pero me emociona ver que el código funciona y todas las cosas que son posibles realizar.

Así hice para que me seleccione los ataques del enemigo, le pase la variable ‘mascotaAleatorio’, la cual ya tenía el valor del mokepon seleccionado por el enemigo, y luego creo la función para que le agregue los ataques al arreglo ataqueEnemigo.

function ataqueAleatorioEnemigo(mascotaAleatorio) {
    let ataques=mokepones[mascotaAleatorio].ataques
    ataqueAleatorio = ataques[aleatorio(ataques.length-1)].nombre.toUpperCase()
    ataqueEnemigo.push(ataqueAleatorio)
    console.log(ataqueEnemigo)
}

ni a mi novia le presto tanta atención como a estas clases de la clase 50 hasta aquí 🤣🤣🤣🤣

Siento que en este punto ya la lógica perdió, se hizo un poco denso y complicado, Creo que me perdí. Pd. A medio video me perdí porque se brinco el 3.

Buenas a todos! Duré 2 días, pero finalmente logre hacer que el ataque del enemigo sea fiel a las normas del juego! lo pensé de muchas maneras, pero un poco de lógica y la función .includes() me terminaron bastando!

Declaré un array en global (arrayVerificacion) para cargar los números aleatorios ahí, para luego preguntar con el if y la funcion includes si el numero aleatorio se encuentra repetido en el arrayVerificacion, si no se encontraba, entonces que cargue el numero en el array del ataque del enemigo.

El segundo if es para que a medida de que el array del jugador guarde sus ataques, el array del enemigo vaya acorde a elegir y guardar sus ataques a la par, hasta llegar a 5.length los 2. Espero haberlos ayudado!!

function ataqAlEnemigo(){
    let ataqueAleatorioEn = aleatorio(0, ataqMokeponEnemigo.length -1) 

        if(!arrayVerificacion.includes(ataqueAleatorioEn)){
            
            ataqEnemigo.push(ataqMokeponEnemigo[ataqueAleatorioEn].nombre)
        }
    
    arrayVerificacion.push(ataqueAleatorioEn)
        
    // console.log(ataqEnemigo) 
    // console.log(ataqueAleatorioEn) 

        if (ataqEnemigo.length === ataqJugador.length) {
            iniciarPelea()
        } else {
            ataqAlEnemigo()
        }

}

Me demoré un chingo de tiempo para darme cuenta de que habia tipeado mal, y era con mayùscula. Les dejo esta herramienta donde pueden comparar el código suyo con el del profe.
https://pinetools.com/es/diff-comparar-archivos

Siento que hay un error en la interpretación del juego, ya que dependiendo del personaje, este puede tener más ataques de fuego o más de agua o más de tierra. Con la solución propuesta por Diego, el arrays que se crea con los ataques del enemigo no se tiene en cuenta que personaje es. Les comparto mi solución:

  1. En la función en la que se selecciona el personaje enemigo, al igual que Diego, yo creé un variable en la que se almacene el array de los ataques que arrojó esta función.
    Dentro de esta misma función hago llamado a otra función llamada “ramdomEnemyAttack” y como parámetro le envio el array de los ataques propios del personaje del enemigo:
function selectWarriorEnemy(){
    let ramdonEnemy = random(0, warriors.length - 1)
    spanWarriorEnemyName.innerHTML = warriors[ramdonEnemy].name
    enemyAttacks = warriors[ramdonEnemy].attacks
    ramdomEnemyAttack(enemyAttacks)
}
  1. La función “ramdomEnemyAttack” recibe el array de los ataques del enemigo y lo que hace es retornar el mismo array pero con los elemento ordenados de forma aleatoria
function ramdomEnemyAttack(enemyAttacks) {
    for (var i = enemyAttacks.length - 1; i > 0; i--) {
        var j = Math.floor(Math.random() * (i + 1));
        var temp = enemyAttacks[i];
        enemyAttacks[i] = enemyAttacks[j];
        enemyAttacks[j] = temp;
    }
    console.log(enemyAttacks)
}

Me cuentan sus opiniones de esta sugerencia de mejora. Un abrazo !!!

Buenas! desde la clase anterior me esta costando entender. Desde la clase 47 hasta la 55 me hice un resumen y fui escribiendo los codigos con notas y distintos colores para poder identificar cada variable y/o funcion. importante para mi visualmente escribi todo en cada hoja solo en una carilla. Ustedes tienen otro metodo?

Por que no se encuentran los recursos.?

Hasta el momento, con cada clase voy observando como existen muchas maneras de hacer las cosas. Cada vez se pone más interesante.!

note que el programa que hizo el profe era muy genérico así que la solución que hice para hacerlo de pendiendo de la mascota del enemigo fu esta

function ataqueAleatoriEnemigo()
{
    let ataqueAleatorio = aleatorio(0,ataqueEnemigo.length - 1)
    
 	
    ataqueEnemigo.push(mokepones[enemigo].ataques[ataque 
    Aleatorio].nombre)
    console.log(ataqueEnemigo)
    combate()
}    

donde enemigo es el numero aleatorio que genera en la función que selecciona la mascota del enemigo y la volví variable global para usarla en esta función

3 horas me demore en completar el reto, y añadí los ataque en los resultados para poder corroborar que si son las comparaciones correctas

Optimize un poco el código en la función de ataqueAleatorioEnemigo, en vez de usar una secuencia if guarde el mokepon del enemigo en una varibale y cambie todo ese codigo por el siguiente

  • ataqueEnemigo.push(mascotaEnemigo.ataques[ataqueAleatorio].ataque)*

Pero entonces lo del ataque aleatorio cuando dijo que si llegan mas ataques los guarda, pero aquí estamos con 5
entonces no veo la optimización del if porque manualmente digito los números 0 a 5. Pero bueno esperar las otras clases para ver en que termina 😅

function ataqueAleatorioEnemigo() {
    let ataqueAleatorio = aleatorio(0, ataquesMokeponEnemigo.length - 1);
    if (ataqueAleatorio == 0 || ataqueAleatorio == 1) {
        ataqueEnemigo.push('FUEGO');
    } else if (ataqueAleatorio == 3 || ataqueAleatorio == 4) {
        ataqueEnemigo.push('AGUA');
    } else {
        ataqueEnemigo.push('TIERRA');
    }
    console.log(ataqueEnemigo);
    combate();
}

Pensé que yo era el único perdido acá, pero bueno veo que varios somos primiparos adelantando conocimientos para luego de a poco comprender.

de Profe a Profe , decir "ya habiamos hecho esto" "ya habías visto eso" , inconscientemente hace sentir tontos a los estudiantes , inconscientemente repito.

Casi se me rompe el código de tantos cambio, casi no la cuento xd🤯

Hola a todos. Si al momento de ejecutar el código les sale en la consola que su elección fue solo [TIERRA, TIERRA, TIERRA], les recomiendo poner un console.log(e) debajo del boton.addEventListener(“click”, (e) => { para así ver en la consola cómo está almacenado el emoji del botón que seleccionaron y lo copien tal y como está en el navegador con todo y espacios en su código para que la condición pueda ser True y pueda variar dependiendo del botón elegido.

las probabilidades de ataque enemigo son las siguientes:
fuego: 40%
agua: 40%
tierra: 20%

Hola, como muchos han comentado esta solución no considera cual es la mascota del enemigo. Comparto mi solución que creo más sencilla y es usando una función que se llama splice(), la cual va recortando los ataques del mokepon, por lo tanto, no repetiremos el ataque seleccionado. Saludos y espero que les ayude a los que no han entendido.

<code> 
function ataqueAleatorioEnemigo(){
    let ataqueAleatorio = aleatorio(0,ataquesMokeponEnemigo.length-1)
    		ataqueEnemigo.push(ataquesMokeponEnemigo[ataqueAleatorio].nombre)
    ataquesMokeponEnemigo.splice(ataqueAleatorio,1)    
    console.log(ataqueEnemigo)
    combate()
}
function secuenciaAtaqueEnemigo() {
    let ataqueAleatorio = aleatorio(0, ataquesPersonajeEnemigo.length - 1)

    if (ataquesPersonajeEnemigo[ataqueAleatorio].nombre === "🪨") {
        ataqueEnemigo.push("Rock")
    } else if(ataquesPersonajeEnemigo[ataqueAleatorio].nombre === "✂️") {
        ataqueEnemigo.push("Scissors")
    } else {
        ataqueEnemigo.push("Paper")
    }
    console.log(ataqueEnemigo)
    ataquesPersonajeEnemigo.splice(ataqueAleatorio, 1)
}

Dejo por aqui mi avance en el curso de programacion basica, tome un camino muy diferente al que hicieron.
Mis mokepones tienen 120 puntos de vida y cada ataque tiene un daño base, segun el tipo de mokepon y el tipo de ataque, del enemigo y del jugador, hace un calculo de aumento o decrecimiento del daño, tambien agregue una funcion de curacion limitada a 3 usos. Me gustaria que le echaran un ojo y me dieran su opinion.

Este es el github

y por aca les dejo el juego en githubpages

Yo lo que hice para que tomara en cuenta la mascota del enemigo es:
1 crear un objeto mascotaEnemigo
donde se guarda la mascota aleatoria del enemigo.

2 con la función

numeroAleatorio(0, mascotaEnemigo.ataques.length)

generar un número aleatorio para elegir un ataque aleatorio de los que tiene la mascota y guardalo en una variable auxiliar “ataque”.

3 guardar el ataque del enemigo en la variable “ataqueEnemigo” de la siguiente forma

ataqueEnemigo = mascotaEnemigo.ataques[ataque]

4 borrar del array “mascotaEnemigo.ataques” el ataque ya usado

mascotaEnemigo.ataques.splice(ataque, 1)

Les dejo la documentación que encontré sobre arrays en JS donde encontré este método, hay otros métodos para borrar elementos de un array pero este es el que mas se ajusto a lo que necesitaba Docuemtacion Arrays

Y aquí sobre el método splice()

Y listo, de esa forma el enemigo selecciona ataques según su personaje y a medida que ataca no puede volver a usar esos mismos ataques.

Al igual que muchos aquí, también me parece que no usar los ataques que ya están establecidos en el arreglo de la clase (class) de los mokepones en mi caso son armas, pues no es lo lógico, así que mi solución fue crear un nuevo arreglo y a este arreglo enviar la copia de lo ya creado luego desordenar el arreglo para que los ataques no sean siempre los mismos, la línea de código que use fue la siguiente tuArreglo.sort(function(){return Math.random() - 0.5 });, el resto fue comparar las posiciones de los arreglos, modificar los mensajes y listo.

He realizado algunas variantes al código, para que use las opciones de ataque del mokepon que escoge la computador.
También le agregé una nueva llave al arreglo de los ataques del mokepon, para que contenga la descripción del ataque

let     opponentMokepon
function sequenceAttacks(){
    let buttonsAttacks=document.querySelectorAll('.button-attack')
    buttonsAttacks.forEach((buttonAttack) => {
        buttonAttack.addEventListener('click', (e) => {
            attacksplayer.push(buttonAttack.value)
            buttonAttack.style.background='#001D6E'
            console.log(attacksplayer)
            opponentRandomAttack()
        })
    })
}
function chooseOpponentMokepon(){
    let mokeponRandomnumber = randomnumber(0,mokepons.length-1)
    opponentMokepon=mokepons[mokeponRandomnumber]
    spanMokeponOpponent.innerHTML = opponentMokepon.name
    imgMokeponOpponent.alt=opponentMokepon.name
    imgMokeponOpponent.src=opponentMokepon.image
    sequenceAttacks()        
}
function opponentRandomAttack(){
    let attackindex=randomnumber(1,opponentMokepon.attacks.length-1)
    attacksopponent.push(opponentMokepon.attacks[attackindex].desc)
    battle()
}

La solución que encontré (después de horas xd) al problema mencionado en los comentarios fue en la función donde se selecciona los ataques aleatorios, ordenar aleatoriamente los ataques del personaje del enemigo y luego ir agregándolos al array de ataques seleccionados y al mismo tiempo eliminándolos del array de los ataques del personaje, para que no se repitan, por eso se selecciona el primer ataque del array e inmediatamente se elimina para que a la próxima vez que se seleccione un ataque se tenga que elegir otro y nunca se elija el mismo de antes :

function seleccionarAtaqueEnemigo(){

ataquesMokeponEnemigo.sort(()=>Math.random()-0.5)

 ataqueSeleccionadoEnemigo.push(ataquesMokeponEnemigo[0].nombre)

    ataquesMokeponEnemigo.shift()


    console.log(ataqueSeleccionadoEnemigo)


    combate()
![](https://static.platzi.com/media/user_upload/sp2-d79af1ff-640f-4bcb-9e6d-936b2df74378.jpg)El código que resalté se me dificultó entenderlo, ya que en mi mente daba 3 porque es la longitud del arreglo o vector mokepones, por ende el ataqueMokeponesEnemigo era para mí justo eso, un valor entre el índice 0 y 2, pero con la propiedad .ataques cambia la longitud del arreglo por la propia sintaxis del lenguaje, entonces se accede directamente a la longitud de los ataques que son 5, o sea, 0-4 que es la longitud del vector ataques, no sé si me hice entender, pero espero les ayude para avanzar en la clase, es tediosa, si yo no hubiera visto en la universidad antes lógica o fundamentos, estaría con derrame cerebral ya que hay cositas que se pasan por alto y JavaScript no lo había manejado hasta ahora

Se me hace un poco complicado seguir a este profesor. Quiero terminar los videos pero esta ha sido la seccion que menos he aprendido. Quizas conecto mejor con otro metodo de explicacion porque en esta seccion ando en el limbo

TENGO buen nivel en javascript pero estas clases se vuelven cada vez muy difícil de entender por la falta de explicación.!!!

Una hora buscando por qué mi código se rompía, para que al final haya sido por escribir "lenght" en vez de "length"
Hola, les comparto mi solución que creo que es algo más fácil. Les explico: El enemigo tiene cinco ataques únicos, y cuando selecciona uno ya no debería poder seleccionarlo nuevamente. Entonces, para hacer eso, lo que yo hice fue crear un número aleatorio (rng) entre cero (el índice del primer ataque) y el número total de ataques menos uno (índice del último ataque). Y después, para asegurarme de que no se pudiera volver a seleccionar ese ataque, lo eliminé del arreglo que contiene los ataques del mokepón del enemigo (mascotaEnemigo.ataques) `rng = aleatorio(0, [mascotaEnemigo.ataques.length -1])    ataqueEnemigo = mascotaEnemigo.ataques[rng].nombre    ataquesEnemigo.push(ataqueEnemigo)    mascotaEnemigo.ataques.splice(rng, 1)` Por último creé dos variables, una llamada ataqueEnemigo que es la que utilizo para validar quién gana en la ronda actual, y otra llamada AtaquesEnemigo (que es un arreglo) en la que guardo el historial de ataques del enemigo.

Gracias al aporte de Paula Inés Cudicio me inspiré a realizar esta solución al problema. Para que el enemigo elija los ataques de acuerdo a su mascota

Blablabla, tengo problemas para seguir comentando 😦 la verdad es que no se si sea un bug pero estoy intentando hacer aportes pero me sale un mensaje de error abajo de la caja de texto de platzi y no me deja postear…

3 horas me demore en completar el reto, y añadí los ataque en los resultados para poder corroborar que si son las comparaciones correctas

ayen por favor mi codigo no funciona y ya ise todo lo que se tenia que hacer

para hacer la barra vertical | , presionen la tecla que está ANTES de la tecla 1 , en su portatil.

Veo que se aun se repite mucho código, además cualquier mascota enemiga tendrá las mismas probabilidades de ataque sin tener en cuenta que unas puede ser mas probable que usen fuego, agua o tierra dependiendo de su tipo.

mi solución a esto es:

function ataqueEnemigoAleatorio(){
    let ataqueEnemigo = mascotaEnemigo.ataques
    return ataquesEnemigo[aleatorio(1,ataquesEnemigo.length)-1].id
}
  1. defino una variable ataqueEnemigo que tiene todos los ataques de la mascota que haya salido del aleatorio y con esta función retorno la propiedad id de un ataque aleatorio que va desde 1 hasta la cantidad de ataques que tenga la mascota enemiga (.length)
            ataquesEnemigo.push(ataqueEnemigoAleatorio())

y luego simplemente le agrego este resultado con el método push a la variable global ataquesEnemigo

clase 57. functionataqueAleatrioEnemigo (), se tiene (0 ó 1) fuego; (3 ó 4 ) agua; else (2)para tierra; considero no acertado por probabilidad de ocurrencia de ataques aleatorios son diferentes.

Gracias por la espectacularmente complicada clase.

Yo no le entiendo nada 😦

Alguien que pueda ayudarme por favor este ha sido el video que menos he podido entender nisiquiera bajando el mismo codigo del profesor le encuentro la logica

Les comparto mi código:

//Ataque Aleatorio del Enemigo

ataque_enemigo = personaje_enemigo.attacks[numeroRandom(0, personaje_enemigo.attacks.length -1)].nombre;

De esta manera hacemos que la elección de ataque del CPU enemigo sea dinámico.

A veces el codigo no me funciona pero si agarro y copio el codigo que esta en los recursos de la clase , magicamente si funciona , muy raro

ups,… esto se puso muy bueno, y muy complejo,. es muy avanzado para un curso básico? bueno, vamos al código.

Yo con POO cree Attacks y le doy un array de debilidades

class Attacks {
    constructor(public attacks: Attack[]) {}
    create(attack: Attack) {
        this.attacks.push(attack);
    }
    getbyName(name: TypeAtacks): Attack {
        return this.attacks.find((attack) => attack.type === name) as Attack;
    }

    public get all(): Attack[] {
        return this.attacks;
    }
}

y cree una funcion llamada result en la que busco la debilidad del usaurio y busco si alguna debilidad es igual al ataque del enemigo

const result = () => {
    const weakUser = attacks.getbyName(ataqueJugador).weak;
    const winPC = weakUser.some((attack) => {
        return attack === ataqueEnemigo;
    });
    ++turno;
    if (!winPC && ataqueJugador !== ataqueEnemigo) {
        changeLife('pcPetLife');
        return 'ganaste';
    } else if (ataqueJugador === ataqueEnemigo) {
        return 'empate';
    } else {
        changeLife('yourPetLife');
        return 'perdiste';
    }
};

Símbolo de O: ||

me rompió el desactivar los botones de ataques pero lo resolvi de esta forma

<code> 
function desactivarAtaques() {
    botonReiniciar.style.display = "block"
    
    botones.forEach((boton) => {
        boton.disabled = true
    })
}

anteriormente lo tenia asi :

<code> 
function desactivarAtaques() {
    botonReiniciar.style.display = "block"
    botonFuego.disabled = true
    botonAgua.disabled = true
    botonPlanta.disabled = true
}

A estas alturas el nivel del curso se ha puesto en mi opinión cuesta arriba 😦, estaba entendiendo paso a paso bien y como que en las últimas 5 o 6 clases mi mente desconecta o no comprendo la “lógica” entiendo que todo se hace de forma dinámica porque luego pueden existir mil personajes y mil ataques y no vas a ir uno por uno indicando cada vez pero como después del día trabajando y luego cenar y ponerme a estudiar a este nivel me cuesta mucho.

Espero poder ir comprendiendo más no quiero rendirme

!!HOLA estudiantes de platzi !!! aqui les dejo un consejo de forEach es un poco largo pero util lean detenidamente y hasta el final incluso las lineas de codigo ya que son la clave para
entener forEach.

recuerdan en clases pasadas y en esta clase hemos usado forEach pueda que algunos sigan con dudas, así que lo explicare de la mejor manera :

pueden interpretar

ataques.forEach((ataque) =>{     <button id="${ataque.id}"  class="ataques BAtaque">${ataque.nombre} </button>
        `     })  

como una funcion :

ataques.forEach(function (ataque){
<button id="${ataque.id}"  class="ataques BAtaque">${ataque.nombre} </button>
        `
})

y lo que dice es : que forEach pasara por cada una de las variable que estan dentro del array ataques y por cada iteracion se ejecutara la “funcion ataque”, los elementos que estan dentro del array ataques son encerrados en la funcion ataque y a la vez que tambien se ejecuta el codigo que pusimos adentro de la funcion que seria el siguiente :

ataquesMokepon = `
        <button id="${ataque.id}"  class="ataques BAtaque">${ataque.nombre} </button>
        `

entonces dentro de la variable ataquesMokepon estariamos guardando la estructura del boton que necesitamos y pueda que aqui es donde se confundieron y la analogia de la funcion nos ayudara a entender esto dijimos que ataque seria una funcion que guardaria cada linea de codigo independiente dentro de el si recordamos ataques tiene :

{nombre: '🔥', id: 'boton-fuego'}

entonces eso se guardaria dentro de la funcion ataque y ya podemos acceder desde la funcion y buscar el id que tiene guardado y tambien a su nombre como hicimos en :

<button id="${ataque.id}"  class="ataques BAtaque">${ataque.nombre} </button>
        `

ya que tenemos guardado el nombre y el id en la funcion podemos usarlas accediendo desde el, ya que estan guardadas dentro de la funcion que se ejecutara por cada iteracion.

Es increible como una simple letra mal puesta te complica la vida , esto es como jugar a ser detective

Solo como pregunta general, no es mejor dividir las variables en otro archivo, y las funciones en otro para que sea mas facil de acceder a ellos?

Aquí veo varios comentarios de l@s compañer@s que son principiantes y que en este punto ya están un poco perdidos, sin embargo me salen con terminologías expertas y ejemplos super avanzados y soluciones extraordinarias. A mi a las justas se me a quedado el nombre del juego 😭

  • ¿Cómo ves el juego?
  • Paso a pasito, el nivel está muy bueno

Yo los ataques de la maquina los nombres del ataque no lo que me lo tome directamte del arreglo de los ataques de la mascota del pc
let ataquecontrincante=[]
function ata_contrincante(){let eleccionataquecontrincante=aleatorio(0,ataquescontrincante.length-1)
console.log(eleccionataquecontrincante)
ataquecontrincante.push(ataquescontrincante[eleccionataquecontrincante].nombre)
console.log(ataquecontrincante)

Hola el curso me ha parecido super bueno, pero a mi opinion personal no me parece que se cambie mucho la logica del juego, porque teniamos desde el inicio una logica y entonces han cambiado muchas cosas y se que quizas sea asi en la realidad de un proyecto real como tal pero eso hace que se pierdan muchas cosas como tiempo, y quizas hasta algunos estilos y demas cosas, pero para eso estamos nosotros para modificar y llevar nuestro propio proyecto a donde nosotros mismo queramos.

Me parece muy valioso que durante el curso aparezca errores y se solucionen, siento que es un poco el día a día en programación y es fundamental entender estos errores.

Recuerden que en la partde de recursos aparece el GitHub donde encuntran las líneas de código. A veces si algo no te funciona es bueno revisar y comprar línea por línea 😃

La forma en que yo hice que mi código creara 5 ataques diferentes según los ataques que tiene el mokepon enemigo fue crear una matriz de números, la cual guardara números aleatorios y comparara los existentes con el que se va a ingresar para saber si alguno es repetido, en caso de que se repita el numero creara otro y así hasta tener los 5 aleatorios

let numeros = []
    var j = 0;
    while(j < 5)
    {
        numero = aleatorio(0, ataquesMokeponEnemigo.length - 1)
        var existe = false 
        for(var i = 0; i < numeros.length; i++)
        {            
            if(numeros[i] == numero)
            {
                existe = true;
                break;
            }
        }       
        if(existe == false)
        {
            numeros.push(numero)
            j++
        }        
    }

luego de esto recorro la matriz de numeros para hacer el push del respectivo ataque de la mascota que encaja con el numero aleatorio en su posicion

for(var i = 0; i<numeros.length; i++){
    
        tipoAtaqueEnemigo.push(mokepones[mascotaAleatoria].ataques[numeros[i]].nombre2)
    
    }

no se si me hice entender, pero si tienen alguna pregunta con gusto les respondo

Es interesante como se usa el metodo de los ataques de los mokepones similar al del enemigo. Aunque un falta complementar lo que dejo el profe. Se nota que esta parte es un poco tediosa, pero entretenida. A seguir aprendiendo.

Si tenemos una función que no esta mandada a llamar en ninguna otra función la función que no esta llamada no hará nada (como si no hubiera nada)

Me había atorado con un error de dedo pero ya voy tomando camino de nuevo.

excelente.

Buenas! yo lo hice de esta manera pensando en qué pasaría si agregaramos más ataques (osea más botones) y evitando el hardcode:

Explicación paso a paso:

function selectPetEnemy() {
  randomPetEnemy = random(0, mokepons.length - 1);
  showSelectedPetEnemy.innerHTML = mokepons[randomPetEnemy].name;
}

En esta función primero creo una variable llamada randomPetEnemy que guarda el número aleatorio entre 0 y la cantidad de mokepones que hay. Recordemos que en los arreglos comenzamos a contar desde 0, por eso se pone el -1. Por ejemplo, si tenemos cinco mokepones entonces sería de 0 a 4. Luego le digo que pinte contenido HTML a través de innerHTML, en este caso va a pintar el nombre del mokepon aleatorio.

function randomEnemyAttack() {
  let enemyPetAttacks = mokepons[randomPetEnemy].attacks;
  let randomAttack = random(0, enemyPetAttacks.length - 1);
  let attackName = enemyPetAttacks[randomAttack].name;

  enemyAttack.push(attackName);
  // Delete the selected attack to prevent it from being selected again
  enemyPetAttacks.splice(randomAttack, 1);

  console.log(`enemy attacks: ${enemyAttack}`);

  // Show match result (player attack, enemy attack and winner)
  // createMessage(combat());

  // Check lives to get the winner
  // checkLives(); 
}

En esta segunda función hacemos algo parecido a la anterior, pero esta vez para los ataques. enemyPetAttacks guarda los ataques de una mascota aleatoria, randomAttack guarda un número aleatorio entre 0 y la cantidad de ataques - 1. Y por último attackName guarda el nombre del ataque aleatorio. Luego empujamos ese nombre del ataque en el arreglo global de los ataques del enemigo. Después le aplicamos el método splice al arreglo que guarda los ataques de la mascota aleatoria, splice lo que hace es eliminar un elemento específico del arreglo, el primer valor que pide es el índice donde se encuentra el elemento que queremos eliminar, en este caso ponemos randomAttack para que automáticamente apenas se escoga un ataque al azar, lo elimine y el enemigo no pueda volver a escogerlo. Y el segundo valor solamente es el número de elementos a eliminar que siempre será 1.

Por último imprimimos el ataque en la consola.

Muchas gracias por leer🫡. Espero haya quedado todo claro, se agradece feedback.
Saludos y feliz código👍🏼

la secuencia de ataques en el if no son consecutivos

Hola, dejo mi código para que me den feedback de que les parece… funciona perfectamente, al menos hasta el momento.

Explico el paso a paso


primero crear las variables



let ataqueEnemigo =[]
let seleccionEnemigo =[]

Después extraigo los ataques y mediante la función aleatorio ubicando el número en la posición por si aumentan o disminuyen los ataques en el futuro.

function seleccionarMascotaEnemigo(){
    let mascotaEnemigo = aleatorio(0, (mokepones.length-1))

        spanMascotaEnemigo.innerHTML = mokepones[mascotaEnemigo].nombre
        ataqueEnemigo = mokepones[mascotaEnemigo].ataques

}

function ataqueAleatorioEnemigo(){
    let eleccionEnemigo = aleatorio(0,(ataqueEnemigo.length-1))
    seleccionEnemigo.push(ataqueEnemigo[eleccionEnemigo].nombre)

    resultadoCombate()
    crearMensaje()
}

Cambiamos la condición para que cada vez que haya un comparativo sea en la ultima posición del array

function resultadoCombate(){
    if (ataqueJugador[ataqueJugador.length-1] == '🔥 FUEGO' && seleccionEnemigo[seleccionEnemigo.length-1] == '🪴 TIERRA' || ataqueJugador[ataqueJugador.length-1] == '💧 AGUA' && seleccionEnemigo[seleccionEnemigo.length-1] =='🔥 FUEGO' || ataqueJugador[ataqueJugador.length-1] == '🪴 TIERRA' && seleccionEnemigo[seleccionEnemigo.length-1] =='💧 AGUA'){
        resultado= 'GANASTE!! 😁';
    }else if (ataqueJugador[ataqueJugador.length-1] == seleccionEnemigo[seleccionEnemigo.length-1]){
        resultado= 'empate';
    }else {
        resultado= 'perdiste 😢';
    }
}

Cambio en lo que se va a imprimir en pantalla en base a las jugadas

function crearMensaje(){
    let nuevoAtaqueJugador = document.createElement("p")
    let nuevoAtaqueEnemigo = document.createElement("p")
    
    sectionResultado.innerHTML = resultado
    nuevoAtaqueJugador.innerHTML = ataqueJugador[ataqueJugador.length-1]
    nuevoAtaqueEnemigo.innerHTML = seleccionEnemigo[seleccionEnemigo.length-1]

    sectionAtaqueJugador.appendChild(nuevoAtaqueJugador)
    sectionAtaqueEnemigo.appendChild(nuevoAtaqueEnemigo)
    
    contadorVidas()
}

Muchisimas gracias

BUENAS!!
Cambie el codigo un poco, arme un IF por cada pokemon para poder asignarles a c/u sus botones con sus poderes correspondientes. Seguro se puede optimizar ya que quedo con mucha linea de codigo. Despues de varios minutos me funciono y cada pokemon tiene sus botones con sus respectivos ataques…

function ataqueEnemigo(){
   let enemigoAtaque = aleatorio(0, ataquePokemonEnemigo.length -1)
    if(pokemones[mascotaAleatorio].nombre === 'Charizard'){ 
       if(enemigoAtaque === 0 || enemigoAtaque === 1 || enemigoAtaque === 2){
            poderEnemigo.push('FUEGO🔥')
        }else if(enemigoAtaque === 3){
            poderEnemigo.push('AGUA💧')
        }else if(enemigoAtaque === 4){
            poderEnemigo.push('TIERRA🌱')
        }else if(enemigoAtaque === 5){
            poderEnemigo.push('RAYO⚡')
        }else if(enemigoAtaque === 6){
            poderEnemigo.push('AIRE🌌')
        }}
    if(pokemones[mascotaAleatorio].nombre === 'Bulbasaur'){ 
        if(enemigoAtaque === 0 || enemigoAtaque === 1 || enemigoAtaque === 2){
                poderEnemigo.push('TIERRA🌱')
            }else if(enemigoAtaque === 3){
                poderEnemigo.push('AGUA💧')
            }else if(enemigoAtaque === 4){
            poderEnemigo.push('FUEGO🔥')
            }else if(enemigoAtaque === 5){
                poderEnemigo.push('RAYO⚡')
            }else if(enemigoAtaque === 6){
                poderEnemigo.push('AIRE🌌')
            }}
    if(pokemones[mascotaAleatorio].nombre === 'Pikachu'){ 
    if(enemigoAtaque === 0 || enemigoAtaque === 1 || enemigoAtaque === 2){
        poderEnemigo.push('RAYO⚡')
        }else if(enemigoAtaque === 3){
            poderEnemigo.push('AGUA💧')
        }else if(enemigoAtaque === 4){
        poderEnemigo.push('FUEGO🔥')
        }else if(enemigoAtaque === 5){
        poderEnemigo.push('TIERRA🌱')
        }else if(enemigoAtaque === 6){
            poderEnemigo.push('AIRE🌌')
        }}
    if(pokemones[mascotaAleatorio].nombre === 'Blastoise'){ 
    if(enemigoAtaque === 0 || enemigoAtaque === 1 || enemigoAtaque === 2){
        poderEnemigo.push('AGUA💧')
        }else if(enemigoAtaque === 3){
        poderEnemigo.push('RAYO⚡') 
        }else if(enemigoAtaque === 4){
        poderEnemigo.push('FUEGO🔥')
        }else if(enemigoAtaque === 5){
        poderEnemigo.push('TIERRA🌱')
        }else if(enemigoAtaque === 6){
            poderEnemigo.push('AIRE🌌')
        }}
   console.log(pokemones[mascotaAleatorio].nombre)
   console.log(enemigoAtaque)
   console.log(poderEnemigo)
   resultadoCombate()
   crearMensaje()
   resultadoFinal()

Tenía un error y era que coloque la llamada de la función mostrarAtaques(ataques) en la línea antes de que terminase el for y por eso se repitieron, cuidado con eso.

Me costó mucho poder seguir con la lógica del juego. Me pasó como a todos que no estamos de acuerdo con que la solución propuesta en la clase era una buena opción, porque perdía lo lógica del juego, ya que el enemigo también debe jugar con los 5 ataques disponibles de su jugador.
Para poder hacer que el Enemigo solo cuente con los mismos ataques del array, fui quitando ese ataque del array por medio de la función array.splice que consulté en la web.

Algo que no pude solucionar es que al agregarle un ataque por medio del Push no me funciona en el condicional pelea, lo solucioné creando otra variable y dandole el mismo resultado.

Dejo mi solución:

function ataqueAleatorioEnemigo(){
ataqueAleatorio1 = aleatorio(0,ataquesMokeponEnemigo.length -1)

if (ataquesMokeponEnemigo[ataqueAleatorio1].nombre === "Fuego"){
    ataqueEnemigo.push("FUEGO")
    jugadaEnemigo = "FUEGO"
    spanImagenAtaqueEnemigo = `<img id="${ataquesMokeponEnemigo[ataqueAleatorio1].id}" src="./imagenes/1200px-Pokémon_Fire_Type_Icon.svg.png" class="Fuego">`
}

else if (ataquesMokeponEnemigo[ataqueAleatorio1].nombre === "Agua"){
    ataqueEnemigo.push("AGUA")
    jugadaEnemigo = "AGUA"
    spanImagenAtaqueEnemigo = `<img id="${ataquesMokeponEnemigo[ataqueAleatorio1].id}" src="./imagenes/1024px-Pokémon_Water_Type_Icon.svg.png" class="Agua">`
}

 else if (ataquesMokeponEnemigo[ataqueAleatorio1].nombre === "Tierra") {
    ataqueEnemigo.push("TIERRA")
    jugadaEnemigo = "TIERRA"
    spanImagenAtaqueEnemigo = `<img id="${ataquesMokeponEnemigo[ataqueAleatorio1].id}" src="./imagenes/1200px-Pokémon_Ground_Type_Icon.svg.png" class="Tierra"></img>`
}

console.log(ataqueEnemigo)
ataquesMokeponEnemigo.splice([ataqueAleatorio1],1)

divResultado.style.display = "flex"
divVersus.style.display = "none"

pelea() 

}

Esta fue una manera en la que hice que los ataques del enemigo vayan de acuerdo al personaje y no se repitan

function ataqueAleatorioEnemigo(){
    let k=aleatorio(0,ataquesMokeponEnemigo.length-1)

    arregloAleatorios.push(k)
    do{
        let numeroAleatorio=aleatorio(0,ataquesMokeponEnemigo.length-1)

        if(arregloAleatorios.includes(numeroAleatorio)){

        }else{
            arregloAleatorios.push(numeroAleatorio)
        }
    }while(arregloAleatorios.length<5)

    arregloAleatorios.forEach((arregloBoton)=>{
        ataquecontrario.push( ataquesMokeponEnemigo[arregloBoton].nombre)
    })

    console.log(ataquecontrario)
    console.log(arregloAleatorios)
}

Yo lo que hice para que se tomará en cuenta la mascota que el enemigo escogió aleatoriamente y extraer los ataques fue declarar la variable ‘exist’ como falso, esto nos ayudará en el ciclo para cambiarla a verdadera cuando no se repitan los ataques del array de los ataques del enemigo.

Luego hice un ciclo que mientras la variable ‘exist’ sea falsa nos tire un numero aleatorio que es la variable ‘randomNumberAttack’, también declare un array para contabilizar los números de los ataques que es ‘ammountEnemyAttacks’ de ahí una condicional a la inversa que mientas en el array de ‘ammountEnemyAttacks’ no exista el número aleatorio que prosiga con el código.
Si eso se cumple la variable ‘exist’ cambia a verdadero y con push incluimos en el array de ‘ammountEnemyAttacks’ el nuevo número aleatorio.
de ahí declaramos randomAttack como la nueva variable del número y hacemos las condicionales de los ataques del enemigo para ir metiendo en el array ‘enemyAttack’ los ataques que vayan saliendo de acuerdo al número aleatorio que ha salido.

siguiendo con el ciclo, vas a estar tirando números aleatorios hasta que se cumpla la condional y asi evitamos que hayan ataques de mas respecto a la mascota que el enemigo escogió

Esta parte del curso si que esta dificil!! 😅

mirando los comentarios de todos, y volviendo a ver la clase un par de veces XD

aca mi solucion!

function seleccionarMascotaEnemigo() {
    let eleccionEnemigo = aleatorio(0, mokepones.length - 1);
    preAtaqueEnemigo = mokepones[eleccionEnemigo].ataques;
    $spanMascotaEnemigo.innerHTML = mokepones[eleccionEnemigo].nombre;

    ataqueEnemigoDefinitivo(preAtaqueEnemigo);
    secuenciaAtaque();
}

function ataqueEnemigoDefinitivo(preAtaqueEnemigo) {  
    preAtaqueEnemigo.forEach((boton2) => {
        if (boton2.nombre === "🔥") {
          ataqueEnemigo.push("FUEGO");
        } else if (boton2.nombre === "💧") {
          ataqueEnemigo.push("AGUA");
        } else {
            ataqueEnemigo.push("TIERRA");
        }
     console.log(ataqueEnemigo);
    })
}

Este fue mi codigo para que tenga en cuenta los poderes de acuerdo al personaje y adicional cuando haga push lo haga con el nombre de y no con el emoji

function ataquealeatorioenemigo () {
        let ataquealeatorio = Math.floor(Math.random() * (ataquemokeponenemigo.length) )
        
   // la variable simbolo almacena el nombre  del ataque  que esta en emoji , segun el array del personaje que tenga el enemigo
        if (ataquealeatorio == 0) {
	   simboloataque = ataquemokeponenemigo[0].nombre
        } else if (ataquealeatorio == 1) {
                simboloataque = ataquemokeponenemigo[1].nombre
        }else if (ataquealeatorio == 2) {
                simboloataque = ataquemokeponenemigo[2].nombre
        } else if (ataquealeatorio == 3) {
                simboloataque = ataquemokeponenemigo[3].nombre
        } else if (ataquealeatorio == 4) {
                simboloataque = ataquemokeponenemigo[4].nombre
        } else if (ataquealeatorio == 5) {
                simboloataque = ataquemokeponenemigo[5].nombre
        }
        else {alert("hay un error")
        }
// aca ya se añade al array en letras el poder que se este usando
        if (simboloataque === "🔥") {
                ataqueenemigo.push ("FUEGO")
        } else if (simboloataque === "💧") {
                ataqueenemigo.push ("AGUA")
        }else if (simboloataque === "🗻") {
                ataqueenemigo.push ("TIERRA")
        }else if (simboloataque === "🌀") {
                ataqueenemigo.push ("AIRE")
        }else {alert("hay un error")
        }