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

Optimizando el frontend del juego

60/84
Recursos

Las optimizaciones del código no solo tienen que hacerse en el código Javascript para mejorar la lógica de un programa. También puede aplicarse en el front-end para mejorar la experiencia de usuario.

Mejoras de experiencia de usuario

Tal vez sea la primera vez que escuches sobre UX, User eXperience o experiencia de usuario. La misma es una práctica de diseño que busca entender el comportamiento de los usuarios de un software y buscar optimizar el mismo para que sea ameno el uso de la aplicación.

Por ejemplo, en el videojuego que te encuentras desarrollando pueden ocurrir errores visuales que no son gratos para el jugador.

Ejemplo punto de mejora de experiencia de usuario

Como los mokepones tienen muchos ataques, la pantalla queda chica y se rompe el HTML.

Puedes solucionarlo fácilmente modificando los estilos CSS del botón de ataque y obtener el siguiente resultado.

.boton-de-ataque {
  background-color: #11468F;
  padding: 10px;
  box-sizing: border-box;
  border-radius: 20px;
  border-color: transparent;
  width: 80px;
  color: white;
  font-family: 'Poppins', sans-serif;
}
Mejora de experiencia de usuario en los botones

Otro problema que tiene el videojuego en este punto es que permite seleccionar todas las veces que el jugador quiera, el mismo ataque. Esto puede causar que el jugador haga trampa o simplemente es un comportamiento que no queremos.

Bloquea el botón que el usuario seleccionó fácilmente con la propiedad del elemento botón llamada disabled.

function secuenciaAtaque() {
    botones.forEach((boton) => {
        boton.addEventListener('click', (e) => {
            if (e.target.textContent === '🔥') {
                // ...
                boton.disabled = true;
            } else if (e.target.textContent === '💧') {
                // ...
                boton.disabled = true;
            } else {
                // ...
                boton.disabled = true;
            }
            ataqueAleatorioEnemigo();
        })
    })
}

De esta forma, el usuario estará obligado a seleccionar los cinco ataques de su mokepon y a no repetirlos.

Si recorres tu videojuego, tal vez encuentres muchos otros puntos de mejora que puedes utilizar para practicar y aprender más. Si un amigo o familiar puede utilizar la aplicación, este puede recomendarte cómo mejorar la lógica del juego. Siempre es recomendable que otra persona prueba el software que uno mismo está programando para ver cosas que nosotros no podemos ver.

Felicitaciones por llegar hasta este punto del Curso Gratis de Programación Básica de Platzi. Ya tienes toda una aplicación funcionando para jugar con tu videojuego y optimizada con buenas prácticas de programación. A partir del siguiente módulo, comenzarás a desarrollar un mapa para que los mokepones pueda pasearse por una ciudad antes de iniciar un nuevo combate.

No dudes en continuar. ¡Nos vemos ahí!


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

Aportes 197

Preguntas 46

Ordenar por:

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

Asi vamos con los nuevos personajes

FRONTEND Y BACKEND EN PLATZI

Frontend

Backend

Creo que en la segunda sección se ha podido hacer algo mejor con la lógica de perder vidas, y mejorar la experiencia de usuario.

Felicidades jugador


Has finalizado la sección Optimización de código, descansa aquí.

Tuve que repetir varias veces estas últimas clases, pero al final hemos conseguido el reto 💪🏼

pude hacerlo tomando los nombres de los ataques en el array, y usé el método splice para borrar ataques ya usados por el enemigo, en la consola se puede ver como por cada ataque lanzado se reduce el array de los ataques del enemigo en 1.

He podido meter a las 6 mascotas:

Para poder tener las 6 mascotas centradas y divididas, quite flex y le puse un grip en 2 fracciones.

.tarjetas, .tarjetas-ataques {
    display: grid;
    grid-template-columns: 1fr 1fr;
    justify-items: center; 
    column-gap: 15px;
    row-gap: 15px;
  }

­
Agregué dos ataques más, viento con Tucapalma:

y veneno con Pydos:

­
Hay un ganador o perdedor, sin errores y es responsivo:

Les comparto mi avance en Github:
https://github.com/Torofms37/Juego-Web.git

Sé que falta mejorar diseño, pero eso luego lo hago al terminar todas las clases.

Me tomo varias horas pero lo logre 😄 cumplí el reto planteado por el profe Diego nnnice

Cuando el jugador selecciona el monstermon y el enemigoSelecionaMonster() se vera en pantalla la img .
y si el monstermon tiene ventaja de tipo se vera en el msm en pantalla otorgándole con ataque adicional de su tipo-especial

el combate sin que el enemigo repita ataques

Pienso que Diego se salió del método con el que venían los anteriores instructores y no se si es el fin del curso pero lo hizo mas para expertos y aunque es normal tener tropiezos al programar nunca entendí por que y para que cambio la lógica con la que venia el código.

La manera en la que conseguí que las elecciones fueran aleatorias y no repetidas en el mismo indice fue el siguiente.

function ataqueAleatorioEnemigo() {
  let ataqueAleatorio = aleatorio(0, ataquesMokeponEnemigo.length - 1);
  let ataque = ataquesMokeponEnemigo[ataqueAleatorio].nombre;
  ataquesMokeponEnemigo.splice(ataqueAleatorio, 1);

  if (ataque == "🔥") {
    ataqueEnemigo.push("FUEGO");
  } else if (ataque == "💧") {
    ataqueEnemigo.push("AGUA");
  } else {
    ataqueEnemigo.push("TIERRA");
  }

  console.log(ataqueEnemigo);
  inicarPelea();
}

Asigno el valor del elemento del array, luego lo elimino y despúes lo valido. De esta manera no se repite. Espero que les sirva 😃

las ultimas 4 clases de esta sección me volaron la cabeza que las repetir n números de veces xD.

Me demore bastante en los detalles de los honguitos pero valió la pena 😃🍄💗

Web:


Móvil:

aparte de desactivar los botones, Otra forma de evitar que el usuario pueda elegir el mismo ataque dos veces es hacer desaparecer el boton con el (display = none) que aprendimos a usar en clases anteriores.

en la imagen ya no se ven los botonen porque fueron desacareciendo cada vez que daba click.

hola !!
les comparto mi solución a los retos del profe Diego

La verdad el juego me gustaba mas como estaba al principio y no con las modificaciones hechas hasta este punto, sobre todo porque cuando se seleccionaba un ataque aparecia inmediatamente el ataque del jugador y del enemigo, ahora toca esperar hasta que se selecionen los 5 ataques para ver como le fue tanto al jugador como al enemigo, ademas por ningun lado se le explica al jugador las reglas del juego, es decir, que el juego se gana por el número de victorias, eso le quita emocion y dinamismo…Que lastima, se tiro el jueguito😦

Lo que entiendo de esta sección de optimización de código, es que tomamos un proyecto de programación estructurada y lo migramos a un proyecto OOP, la transición se volvió engorrosa. Yo habría preferido que escribiéramos el juego desde cero con la perspectiva OOP

Asi me quedo despues de cambiar un poco la logica y de agregar las otras mascotas:

Cuando elijo mi mokepon, la mascota del enemigo se elige aleatoriamente y dependiendo de su tipo tambien tendra un ataque mas de ese elemento. y luego empieza el combate (mas estrategico que de suerte):

Para que el usuario no pueda darle click al mismo ataque dos veces los botones van desapareciendo cada que se eligen, y batalla a batalla se va llevando el conteo y te avisa si ganaste o perdiste esa batalla.(los ataques del oponente se eligen aleatoriamente sin repetirse).


Una vez se terminan los ataques te informa el resultado final y si ganaste o perdiste o si fue empate.
Ahora Sigamos Aprendiendo!🦾🧠💪

Saludos. Esta vez no le invertí mucho tiempo al UI, aparte de detalles pequeños. Lo que si hice fue cambiar la lógica de algunas funciones para evitar validaciones innecesarias. Además entre la primera lógica (haciendo un combate a la vez) y la de secuencias, a mí personalmente me gusta más la primera. Sin embargo le puse la opción para que el usuario pueda escoger en qué modo desea jugar.
Mokepon en GitHub

Live view

Asi va mi juego de momento

Reto terminado, aunque considero que mostrar los combates uno a uno es mucho mejor y no dar un ataque extra al que tiene una evidente ventaja, pero como reto ya está. Soy aprendiz de javascript y mi código aún es bastante redundante, pero aún así aquí les dejo mi Codepen
por si les sirve a alguien.

Primera interfaz - Elección de mascota

Segunda interfaz - Elegir ataques

Tercera interfaz - Resultado del combate

Les comparto como se ve mi página al estilo Darksouls hasta el momento…

Así quedí mi Juego!

https://estebanchica07.github.io/Mokepon-V1/

Gracias profesor Diego por las enseñanzas. Optimizar el código es la clave para pensar nuevas soluciones, por eso se me hacia raro que no buscamos la solución de los ataques del enemigo en su momento, pero genial que aquí lo dejó como tarea para nosotros.

Reto aceptado…
Solución para que los ataques del enemigo no estén hardcodeados:

function seleccionarAtaqueEnemigo() {
    let ataqueAleatorio = aleatorio(0,ataquesMokeponEnemigo.length -1)
    if (ataquesMokeponEnemigo[ataqueAleatorio].nombre === "🔥") {
        ataquesEnemigos.push('FUEGO')
    } else if (ataquesMokeponEnemigo[ataqueAleatorio].nombre === "💧") {
        ataquesEnemigos.push('AGUA')
    }else {
        ataquesEnemigos.push('PLANTA')
    }
    console.log(ataquesEnemigos)
    iniciarPelea()
}

No sé como llegué hasta aquí, y tampoco como le voy a seguir…

MOKEPON listo


Así es como se ve:

Aquí mi repositorio: Mokepon
También puedes probarlo: ¡Pruébalo ahora!
Te agradezco mucho por leer 💚💚💚

Esta es mi opción de seleccionar el ataque del enemigo de forma aleatoria e independiente de la cantidad de ataques que tenga el personaje

function ataqueAleatorioEnemigo() {
    let ataqueAleatorio = aleatorio(0, ataquesMokeponEnemigo.length - 1)
    ataqueEnemigo.push(ataquesMokeponEnemigo[ ataqueAleatorio ].titulo)
    iniciarPelea()
}

y al guardar los ataques les agrego el titulo que se muestra

ratigueya.ataques.push(
    { nombre: "🔥", id: "boton-fuego", titulo: "FUEGO" },
    { nombre: "🔥", id: "boton-fuego", titulo: "FUEGO" },
    { nombre: "🔥", id: "boton-fuego", titulo: "FUEGO" },
    { nombre: "💧", id: "boton-agua", titulo: "AGUA" },
    { nombre: "🌱", id: "boton-tierra", titulo: "TIERRA" }
)

Me quemé el cerebro mas de una vez pero ¡no desistí y no lo haré!.

Mucho ánimo a quienes todavía siguen aquí, con cada clase vista y con cada reto superado nuestro poder crece exponencialmente

Dentro de la función “function combate()” tenemos mensajes como crearMensaje(‘EMPATE’)/crearMensaje(‘GANASTE’)crearMensaje(‘PERDISTE’), las cuales ya no se están utilizando, por lo que me parece que se podrían remover, ya que solo se muestra el mensaje final de función revisarVictorias/revisarVidas

Me di cuenta que hay un pequeño Bug, no sé si ya alguien lo habrá comentado, cuando no seleccionamos ninguna mascota y le damos “Click” al botón de “Seleccionar” nos manda a la seccion “selecionar ataque” mi solución a este problema fue este.

En la funcion de “SeleccionarMascotaJugador” lo dejamos así.

	//el error era que aqui se estaba mandando a llamar el display "none" y "flex" al  momento de darle click al 
 boton, la solucion fue ponerlos en cada condicional, para que no se ejecute automáticamente al darle click, si no 
cuando este checkeado una mascota.

function seleccionarMascotaJugador() {

  if (inputHipodoge.checked) {
    spanMascotaJugador.innerHTML = inputHipodoge.id;
    mascotaJugador = inputHipodoge.id;
    sectionSeleccionarMascota.style.display = "none";
    sectionSeleccionarAtaque.style.display = "flex";
  } else if (inputCapipepo.checked) {
    spanMascotaJugador.innerHTML = inputCapipepo.id;
    mascotaJugador = inputCapipepo.id;
    sectionSeleccionarMascota.style.display = "none";
    sectionSeleccionarAtaque.style.display = "flex";
  } else if (inputRatigueya.checked) {
    spanMascotaJugador.innerHTML = inputRatigueya.id;
    mascotaJugador = inputRatigueya.id;
    sectionSeleccionarMascota.style.display = "none";
    sectionSeleccionarAtaque.style.display = "flex";
  } else {
    alert("Selecciona una mascota");
  }
  extraerAtaques(mascotaJugador);
  seleccionarMascotaEnemigo();
}

Así fue como me quedó el proyecto de Mokepon, la verdad tuve que ver clases pasadas y ver algunos de sus aportaciones. Se los agradezco bastante.

<code> 

    if (inputHipodoge.checked) {
        spanMascotaJugador.innerHTML = inputHipodoge.id
        mascotaJugador = inputHipodoge.id
    } else if(inputCapipepo.checked){
        spanMascotaJugador.innerHTML = inputCapipepo.id
        mascotaJugador = inputCapipepo.id
    } else if(inputRatigueya.checked){
        spanMascotaJugador.innerHTML = inputRatigueya.id
        mascotaJugador = inputRatigueya.id
    } else if(inputLangostelvis.checked){
        spanMascotaJugador.innerHTML = inputLangostelvis.id
        mascotaJugador = inputLangostelvis.id
    } else if(inputPydos.checked){
        spanMascotaJugador.innerHTML = inputPydos.id
        mascotaJugador = inputPydos.id
    } else if(inputTucapalma.checked){
        spanMascotaJugador.innerHTML = inputTucapalma.id
        mascotaJugador = inputTucapalma.id   
    } else {
        alert("Selecciona una mascota")
    }

https://andrescorreac.github.io/hunterXGame/

Subo mi aporte, queda mucho que me gustaria implementarle pero quiero seguir en el curso jejej

😻😻

Bueno así va quedando mi videojuego, gracias a los profesores y ustedes chicos que mas de una vez me han ayudado a salir de dudas, os comparto la version movil.

Me demore un rato, pero al fin termine, igual tengo un problema el cual comentare al final.

array.splice(punto inicial, cantidad a eliminar)

primero con respecto a los ataque del enemigo use la funcion .splice(), la cual permite eliminar un valor en especifico del array y asi logre hacer que el mokepon enemigo logre seleccionar la cantidad de ataques que le toca

function ataqueAleatorioEnemigo() {
    let ataqueAleatorio = aleatorio(0,ataquesMokeponEnemigo.length -1)
    
    if (ataquesMokeponEnemigo[ataqueAleatorio].nombre === '🔥') {
        ataqueEnemigo.push('FUEGO')
    } else if (ataquesMokeponEnemigo[ataqueAleatorio].nombre === '💧') {
        ataqueEnemigo.push('AGUA')
    } else {
        ataqueEnemigo.push('TIERRA')
    }
    ataquesMokeponEnemigo.splice(ataqueAleatorio,1)
    console.log(ataqueEnemigo)
    iniciarPelea()
}

Luego para lo que es la seleccion del tipo de mokepon, para validar el tipo, tuve que hacer algunas modificaciones dentro de las funciones, pero al final salio.
Ejemplos:
Mokepones iguales

Mokepon jugador con ventaja

Mokepon enemigo con ventaja

Ahora viene el problema, este es que no puedo deshabilitar el boton adicional despues de tirar los 5 ataques, he estado intentando, pero no se me ocurre nada, alguien tiene alguna idea de como hacerlo o algun profe? 😦

CODIGO COMPLETO

//Iniciar juego
const sectionSeleccionarAtaque = document.getElementById('seleccionar-ataque')
let sectionReiniciar = document.getElementById('reiniciar')
    sectionReiniciar.style.display = 'none'
const botonMascotaJugador = document.getElementById('boton-mascota')
const botonReiniciar = document.getElementById('boton-reiniciar')

//seleccionarMascotaJugador
const sectionSeleccionarMascota = document.getElementById('seleccionar-mascota')
const spanMascotaJugador = document.getElementById('mascota-jugador')

//selecionarMascotaEnemigo
const spanMascotaEnemigo = document.getElementById('mascota-enemigo')

//Combate
const spanVidasJugador = document.getElementById('vidas-jugador')
const spanVidasEnemigo = document.getElementById('vidas-enemigo')

//CrearMensaje
const sectionMensajes = document.getElementById('resultado')
const ataquesDelJugador = document.getElementById('ataques-del-jugador')
const ataquesDelEnemigo = document.getElementById('ataques-del-enemigo')

const contenedorTarjetas = document.getElementById('contenedorTarjetas')
const contenedorAtaques = document.getElementById('contenedorAtaques')

let mokepones = []
let ataqueJugador = []
let ataqueEnemigo = []
let opcionDeMokepones
let inputHipodoge
let inputCapipepo
let inputRatigueya
let inputPydos 
let inputTucapalma 
let inputLangostelvis 
let mascotaJugador
let ataquesMokepon
let ataquesMokeponEnemigo
let botonFuego 
let botonAgua 
let botonTierra
let tipoEnemigo
let tipoJugador
let botones = []
let indexAtaqueJugador 
let indexAtaqueEnemigo
let mascotaAleatoria
let VictoriasJugador = 0
let victoriasEnemigo = 0

//Clase para hacer clasificacion mokepones al juego
class Mokepon{
    constructor(nombre, foto, vida, tipo){
        this.nombre = nombre
        this.foto = foto
        this.vida = vida
        this.tipo = tipo
        this.ataques = [] //Variable para guardar ataques
    }
}

let hipodoge = new Mokepon('Hipodoge', './assets/mokepons_mokepon_hipodoge_attack.png', 5, '💧')

let capipepo = new Mokepon('Capipepo', './assets/mokepons_mokepon_capipepo_attack.png', 5, '🌱')

let ratigueya = new Mokepon('Ratigueya', './assets/mokepons_mokepon_Ratigueya_attack.png', 5, '🔥')

let langostelvis = new Mokepon('Langostelvis', './assets/mokepons_mokepon_langostelvis_attack.png', 5, '🔥')

let pydos = new Mokepon('Pydos', './assets/mokepons_mokepon_Pydos_attack.png', 5, '💧')

let tucapalma = new Mokepon('Tucapalma', './assets/mokepons_mokepon_tucapalma_attack.png', 5, '🌱')


hipodoge.ataques.push(
    {nombre: '💧', id: 'boton-agua'},
    {nombre: '💧', id: 'boton-agua'},
    {nombre: '💧', id: 'boton-agua'},
    {nombre: '🔥', id: 'boton-fuego'},
    {nombre: '🌱', id: 'boton-tierra'}
)

capipepo.ataques.push(
    {nombre: '🌱', id: 'boton-tierra'},
    {nombre: '🌱', id: 'boton-tierra'},
    {nombre: '🌱', id: 'boton-tierra'},
    {nombre: '💧', id: 'boton-agua'},
    {nombre: '🔥', id: 'boton-fuego'}
)

ratigueya.ataques.push(
    {nombre: '🔥', id: 'boton-fuego'},
    {nombre: '🔥', id: 'boton-fuego'},
    {nombre: '🔥', id: 'boton-fuego'},
    {nombre: '💧', id: 'boton-agua'},
    {nombre: '🌱', id: 'boton-tierra'}
)

tucapalma.ataques.push(
    {nombre: '🌱', id: 'boton-tierra'},
    {nombre: '🌱', id: 'boton-tierra'},
    {nombre: '🌱', id: 'boton-tierra'},
    {nombre: '💧', id: 'boton-agua'},
    {nombre: '🔥', id: 'boton-fuego'}
)   

pydos.ataques.push(
    {nombre: '💧', id: 'boton-agua'},
    {nombre: '💧', id: 'boton-agua'},
    {nombre: '💧', id: 'boton-agua'},
    {nombre: '🔥', id: 'boton-fuego'},
    {nombre: '🌱', id: 'boton-tierra'}
)

langostelvis.ataques.push(
    {nombre: '🔥', id: 'boton-fuego'},
    {nombre: '🔥', id: 'boton-fuego'},
    {nombre: '🔥', id: 'boton-fuego'},
    {nombre: '💧', id: 'boton-agua'},
    {nombre: '🌱', id: 'boton-tierra'}
)

mokepones.push(hipodoge, capipepo, ratigueya, tucapalma, pydos, langostelvis)

function iniciarJuego() {
    sectionSeleccionarAtaque.style.display = 'none'

    //Creacion de tarjeta Mokepon en el html
    mokepones.forEach((mokepon) => {
        opcionDeMokepones = `
        <input type="radio" name="mascota" id=${mokepon.nombre} />
                <label class="tarjeta-de-mokepon" for=${mokepon.nombre}>
                    <p>${mokepon.nombre}</p>
                    <img src=${mokepon.foto} alt=${mokepon.nombre}>
                </label>
        `
        contenedorTarjetas.innerHTML += opcionDeMokepones

         inputHipodoge = document.getElementById('Hipodoge')
         inputCapipepo = document.getElementById('Capipepo')
         inputRatigueya = document.getElementById('Ratigueya')
         inputPydos = document.getElementById('Pydos')
         inputTucapalma = document.getElementById('Tucapalma')
         inputLangostelvis = document.getElementById('Langostelvis')
    })

    
    botonMascotaJugador.addEventListener('click', seleccionarMascotaJugador)


    botonReiniciar.addEventListener('click', reiniciarJuego)
}

function seleccionarMascotaJugador() {

    sectionSeleccionarMascota.style.display = 'none'
    
    sectionSeleccionarAtaque.style.display = 'flex'
    
    
    if (inputHipodoge.checked) {
        spanMascotaJugador.innerHTML = inputHipodoge.id
        mascotaJugador = inputHipodoge.id
    } else if (inputCapipepo.checked) {
        spanMascotaJugador.innerHTML = inputCapipepo.id
        mascotaJugador = inputCapipepo.id
    } else if (inputRatigueya.checked) {
        spanMascotaJugador.innerHTML = inputRatigueya.id
        mascotaJugador = inputRatigueya.id
    }else if (inputLangostelvis.checked) {
        spanMascotaJugador.innerHTML = inputLangostelvis.id
        mascotaJugador = inputLangostelvis.id
    }else if (inputTucapalma.checked) {
        spanMascotaJugador.innerHTML = inputTucapalma.id
        mascotaJugador = inputTucapalma.id
    }else if (inputPydos.checked) {
        spanMascotaJugador.innerHTML = inputPydos.id
        mascotaJugador = inputPydos.id
    } else {
        alert('Selecciona una mascota')
    }
    mascotaAleatoria = aleatorio(0, mokepones.length-1)
    tipoEnemigo = mokepones[mascotaAleatoria].tipo
    
    extraerAtaques(mascotaJugador)
    seleccionarMascotaEnemigo()
    
}

function extraerTipo(){
    if(tipoJugador == '🔥' && tipoEnemigo == '🌱'){
        ataques.push(tipoJugador)
    } else if(tipoJugador == '💧' && tipoEnemigo == '🔥'){
        ataques.push(tipoJugador)
    } else if(tipoJugador == '🌱' && tipoEnemigo == '💧'){
        ataques.push(tipoJugador)
    }else if(tipoJugador==tipoEnemigo){
    }else{
        ataques.push(tipoEnemigo)
    }


}

function extraerAtaques(mascotaJugador){    
    let ataques
    for (let i = 0; i < mokepones.length; i++) {
        if (mascotaJugador === mokepones[i].nombre){
            
           
            tipoJugador = mokepones[i].tipo
            

            if(tipoJugador == '🔥' && tipoEnemigo == '🌱'){
                mokepones[i].ataques.push(mokepones[i].ataques[0])
            } else if(tipoJugador == '💧' && tipoEnemigo == '🔥'){
                mokepones[i].ataques.push(mokepones[i].ataques[0])
            } else if(tipoJugador == '🌱' && tipoEnemigo == '💧'){
                mokepones[i].ataques.push(mokepones[i].ataques[0])
            }else if(tipoJugador == tipoEnemigo){
                
            }else {
                mokepones[mascotaAleatoria].ataques.push(mokepones[mascotaAleatoria].ataques[0])

            }
             ataques = mokepones[i].ataques
        }
        
        
    }
    console.log(tipoJugador)
    console.log(ataques)
    mostrarAtaques(ataques)
}


function mostrarAtaques(ataques){
    ataques.forEach((ataque) => {
        ataquesMokepon = `
        <button id=${ataque.id} class="boton-de-ataque BAtaques">${ataque.nombre}</button>
        `
        contenedorAtaques.innerHTML +=  ataquesMokepon
    })
    botonFuego = document.getElementById('boton-fuego')
    botonAgua = document.getElementById('boton-agua')
    botonTierra = document.getElementById('boton-tierra')
    botones = document.querySelectorAll('.BAtaques')

}

function secuenciAtaque(){
    botones.forEach((boton) => {
        boton.addEventListener('click', (e) => {
            if(e.target.textContent === '🔥'){
                ataqueJugador.push('FUEGO')
                console.log(ataqueJugador)
                boton.style.background = '#2B7A0B'
                boton.disabled = true
            } else if(e.target.textContent === '💧'){
                ataqueJugador.push('AGUA')
                console.log(ataqueJugador)
                boton.style.background = '#2B7A0B'
                boton.disabled = true
            } else {
                ataqueJugador.push('TIERRA')
                console.log(ataqueJugador)
                boton.style.background = '#2B7A0B'
                boton.disabled = true
            }
            ataqueAleatorioEnemigo()
        })
    })

}

function seleccionarMascotaEnemigo() {
    console.log(tipoEnemigo)
    spanMascotaEnemigo.innerHTML = mokepones[mascotaAleatoria].nombre
    ataquesMokeponEnemigo = mokepones[mascotaAleatoria].ataques
    console.log(ataquesMokeponEnemigo)
    secuenciAtaque()
}



function ataqueAleatorioEnemigo() {
    let ataqueAleatorio = aleatorio(0,ataquesMokeponEnemigo.length -1)
    
    if (ataquesMokeponEnemigo[ataqueAleatorio].nombre === '🔥') {
        ataqueEnemigo.push('FUEGO')
    } else if (ataquesMokeponEnemigo[ataqueAleatorio].nombre === '💧') {
        ataqueEnemigo.push('AGUA')
    } else {
        ataqueEnemigo.push('TIERRA')
    }
    ataquesMokeponEnemigo.splice(ataqueAleatorio,1)
    console.log(ataqueEnemigo)
    iniciarPelea()
}

function iniciarPelea(){
    if(ataqueJugador.length === 5){
        combate()
    }
}

function indexAmbosOponentes(jugador, enemigo){
    indexAtaqueJugador = ataqueJugador[jugador]
    indexAtaqueEnemigo = ataqueEnemigo[enemigo]
}

function combate() {

    for (let index = 0; index < ataqueJugador.length; index++) {
        if(ataqueJugador[index] === ataqueEnemigo[index]){
            indexAmbosOponentes(index,index)
            crearMensaje('EMPATE')
        } else if(ataqueJugador[index] == 'FUEGO' && ataqueEnemigo[index] == 'TIERRA') {
            indexAmbosOponentes(index,index)
            crearMensaje("GANASTE")
            VictoriasJugador++
            spanVidasJugador.innerHTML = VictoriasJugador
        } else if(ataqueJugador[index] == 'AGUA' && ataqueEnemigo[index] == 'FUEGO') {
            indexAmbosOponentes(index,index)
            crearMensaje("GANASTE")
            VictoriasJugador++
            spanVidasJugador.innerHTML = VictoriasJugador
        } else if(ataqueJugador[index] == 'TIERRA' && ataqueEnemigo[index] == 'AGUA') {
            indexAmbosOponentes(index,index)
            crearMensaje("GANASTE")
            VictoriasJugador++
            spanVidasJugador.innerHTML = VictoriasJugador
        } else {
            indexAmbosOponentes(index,index)
            crearMensaje("PERDISTE")
            victoriasEnemigo++
            spanVidasEnemigo.innerHTML = victoriasEnemigo
        }
        
    }
    

    revisarVidas()
}

function revisarVidas() {
    if (victoriasEnemigo == VictoriasJugador) {
        crearMensajeFinal("EMPATE")
    } else if (VictoriasJugador > victoriasEnemigo) {
        crearMensajeFinal("FELICITACIONES! Ganaste :)")
    } else {
        crearMensajeFinal('Lo siento, perdiste :(')
    }
}

function crearMensaje(resultado) {
    
    let nuevoAtaqueDelJugador = document.createElement('p')
    let nuevoAtaqueDelEnemigo = document.createElement('p')
    botones.disabled = true
    sectionMensajes.innerHTML = resultado
    nuevoAtaqueDelJugador.innerHTML = indexAtaqueJugador
    nuevoAtaqueDelEnemigo.innerHTML = indexAtaqueEnemigo

    ataquesDelJugador.appendChild(nuevoAtaqueDelJugador)
    ataquesDelEnemigo.appendChild(nuevoAtaqueDelEnemigo)
}

function crearMensajeFinal(resultadoFinal) {
    
    sectionMensajes.innerHTML = resultadoFinal

    sectionReiniciar.style.display = 'block'
}

function reiniciarJuego() {
    location.reload()
}

function aleatorio(min, max) {
    return Math.floor(Math.random() * (max - min + 1) + min)
}

window.addEventListener('load', iniciarJuego)

POR FIN LOGRADO… SUBIRIA IMAGENES PERO NO ME DEJA ASI QUE DEJO EL DEPLOY…
never stop learning!!

https://bartydev.github.io/mokeponNewGame.github.io/

te quiero mucho Pedro Pascal me ha encantado esta clase ❤️

Definitivamente mi profesor favorito, Diego supo hacer muy fácil lo que es más complicado, a la velocidad perfecta, realmente queda como mi ejemplo a seguir en términos de optimización y programación dinámica, una lástima no poderlo ver más adelante

En este módulo aprendí el porqué dicen que el programar es tener una tolerancia a la frustración, con todas las veces que se me rompió el código y lo tuve que ver y rever para poder continuar clase por clase, pero al final se llegó 😄

Que satisfacción llegar al fin de este modulo. dolio, mucho pero al final se siente una recompensa. Gracias al profesor

Esto es lo que decidíi hacer como reto, los que son Miku y Arceus los agregué como extras, dandole a ellos un ataque que obtienen cuando se enfrentan antes ciertos mokepons como ventaja, magia para Arceus, y Psiquico para Miku

Veo comentarios quejándose de como el profe cambio la lógica del juego pero poco se habla de que es otra forma de hacer un juego.

Así vamos con nuevos personajes con doble tipo de ataque!
https://github.com/sariswis/Mokepon.git

Yo creo que agregar la propiedad de tipo no es necesario, ya que al elegir un tipo que es fuerte contra otro contás con una ventaja:

3 de tus ataques son fuertes contra 3 de los ataques del rival!

Hola a todos, pensando en la opción de “Not repeat yourself” cuando vamos a crear más mokepones, tenemos una parte del código donde verificamos cada una de las opciones de mokepon y revisamos si es el que está checkeado o no, para asi asignarlo a la variable mascotaJugador y hacer el innerHTML.

Buscando en la web encontré que podemos usar este código

inputMascotaSeleccionada = document.querySelector('input[type="radio"]:checked').id

Esto con el fin de buscar en todos los input de type “radio” para saber cual es el que está seleccionado.
Luego hice un for para compararlo con los mokepones que tenemos y asi asignar el mokepon asignado

Este sería el for:

for (let im = 0; im < mokepones.length; im++) {
        if (inputMascotaSeleccionada == mokepones[im].nombre) {
            spanMascotaJugador.innerHTML = inputMascotaSeleccionada
            mascotaJugador = mokepones[im]
        }
    }

Yo detecté desde el principio que los empates no se dan puntos a favor ni en contra, o pueden ser para nadie o para los dos.

Agregué esto y me funcionó, pero igual esta mejor quitarlo:

function combate() {
    for (let index = 0; index < ataqueJugador.length; index++) {
        if(ataqueJugador[index] === ataqueEnemigo[index]) {
            indexAmbosOponentes(index, index)
            crearMensaje('Empate');
            victoriasJugador++;
            victoriasEnemigo++;
            spanVidasEnemigo.innerHTML = victoriasJugador;
No ha sido sencillo, pero se logró completar este módulo.![](https://static.platzi.com/media/user_upload/Captura%20de%20pantalla%20%2818%29-7fd3a006-772a-41af-9d2e-bc48e7ac1d82.jpg)
Me gustaría compartirles un poco el proceso. Aclaro que no sabía absolutamente nada y a la fecha lo que he aprendido es por el curso, Platzi y por consultas extras en internet. ![](https://static.platzi.com/media/user_upload/image-570c2ecf-5ee7-4ef4-80f5-9ecddc54ee1e.jpg)![](https://static.platzi.com/media/user_upload/image-6f950716-b2ce-4d12-8f1e-4e759d08c72d.jpg) ![]()![]()![]()![]()![](https://static.platzi.com/media/user_upload/image-3f4d47a3-b3cc-409e-92db-fa407b02af64.jpg)
Reto 01 Antes ```js 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) iniciarPelea() } ``` Despues ```js function ataqueAleatorioEnemigo() { let ataqueAleatorio = aleatorio(0, ataquesMokeponEnemigo.length - 1) if (ataquesMokeponEnemigo[ataqueAleatorio].nombre == "🔥") { ataqueEnemigo.push('FUEGO') } else if (ataquesMokeponEnemigo[ataqueAleatorio].nombre == "💧") { ataqueEnemigo.push('AGUA') } else { ataqueEnemigo.push('TIERRA') } console.log(ataqueEnemigo) iniciarPelea() } ```

🌻 Ahora que nos vamos a despedir de Diego: puede que a veces pueda parecer frustrante cambiar de profesor o de lógica justo cuando ya estábamos acostumbrados, pero creo que es un acierto permitirnos estar expuestos a diferentes programadores 👾.

En los proyectos será así 🚀, cada persona será un mundo, tendrá su personalidad y su estilo, habrá cambios repentinos que no dependerán de nosotros e incluso gente que nos gustaba se irá… es importante también practicar eso, ser humilde y no pensar que solo hay una forma de hacer las cosas bien, colaborar 🫱🏼‍🫲🏾e intentar apreciar 💫los cables que intentan echarnos los demás porque, si no, vamos a pasarnos el día frustrados 🔥porque el de allá hizo no sé qué 🔥🔥 y el de acá no supo explicarse bien 🔥🔥🔥etc etc.

En ocasiones habrá que poner mucho de nuestra parte por comprender🤔, por seguir el ritmo 🏃🏽, por adaptarnos 🏄🏻… y gestionar bien esas situaciones nos hará probablemente más eficientes 🎯, pero sobre todo nos ahorrarán un sufrimiento interno que no aporta nada a nadie 🔥🔥🫠💻🔥.

(último aporte después de un texto tan largo: me encanta que llame a eso “áreas de oportunidad”, lo voy a usar en el mundo real también 😅 cuántas áreas de oportunidad por todas partes)

Yo tengo una duda, en la consola no me aparece error, pero los ataques del enemigo se repiten y por mas que busque no se donde se encuentra el error, ¿alguien podría ayudarme por favor? Este es el código: ```html const sectionSeleccionarAtaque = document.getElementById('seleccionar-ataque') const sectionReiniciar = document.getElementById('reiniciar') const botonMascotaJugador = document.getElementById('boton-mascota') const botonReiniciar = document.getElementById('boton-reiniciar') sectionReiniciar.style.display = 'none' const sectionSeleccionarMascota = document.getElementById('seleccionar-mascota') const spanMascotaJugador = document.getElementById('mascota-jugador') const spanMascotaEnemigo = document.getElementById('mascota-enemigo') const spanVidasJugador = document.getElementById('vidas-jugador') const spanVidasEnemigo = document.getElementById('vidas-enemigo') const sectionMensajes = document.getElementById('resultado') const ataquesDelJugador = document.getElementById('ataques-del-jugador') const ataquesDelEnemigo = document.getElementById('ataques-del-enemigo') const contenedorTarjetas = document.getElementById('contenedorTarjetas') const contenedorAtaques = document.getElementById('contenedorAtaques') let pokemones = [] let ataqueJugador = [] let ataqueEnemigo = [] let opcionDePokemones let inputBolbasaur let inputCharmander let inputSquirtle let mascotaJugador let ataquesPokemon let ataquesPokemonEnemigo let botonPlanta let botonFuego let botonAgua let botones = [] let indexAtaqueJugador let indexAtaqueEnemigo let victoriasJugador = 0 let victoriasEnemigo = 0 let vidasJugador = 3 let vidasEnemigo = 3 class Pokemon { constructor(nombre, foto, vida) { this.nombre = nombre this.foto = foto this.vida = vida this.ataques = [] } } let bolbasaur = new Pokemon('Bolbasaur', 'https://assets.pokemon.com/assets/cms2/img/pokedex/detail/001.png', 5) let charmander = new Pokemon('Charmander', 'https://assets.pokemon.com/assets/cms2/img/pokedex/detail/004.png', 5) let squirtle = new Pokemon('Squirtle', 'https://assets.pokemon.com/assets/cms2/img/pokedex/detail/007.png', 5) bolbasaur.ataques.push( { nombre: '🍃', id: 'boton-planta' }, { nombre: '🍃', id: 'boton-planta' }, { nombre: '🍃', id: 'boton-planta' }, { nombre: '💧', id: 'boton-agua' }, { nombre: '🔥', id: 'boton-fuego' }, ) charmander.ataques.push( { nombre: '🔥', id: 'boton-fuego' }, { nombre: '🔥', id: 'boton-fuego' }, { nombre: '🔥', id: 'boton-fuego' }, { nombre: '🍃', id: 'boton-planta' }, { nombre: '💧', id: 'boton-agua' }, ) squirtle.ataques.push( { nombre: '💧', id: 'boton-agua' }, { nombre: '💧', id: 'boton-agua' }, { nombre: '💧', id: 'boton-agua' }, { nombre: '🔥', id: 'boton-fuego' }, { nombre: '🍃', id: 'boton-planta' }, ) pokemones.push(bolbasaur,charmander,squirtle) function iniciarJuego() { sectionSeleccionarAtaque.style.display = 'none' pokemones.forEach((pokemon) => { opcionDePokemones = ` <input type="radio" name="mascota" id=${pokemon.nombre} /> <label class="tarjeta-de-pokemon" for=${pokemon.nombre}>

${pokemon.nombre}

</label> ` contenedorTarjetas.innerHTML += opcionDePokemones inputBolbasaur = document.getElementById('Bolbasaur') inputCharmander = document.getElementById('Charmander') inputSquirtle = document.getElementById('Squirtle') }) botonMascotaJugador.addEventListener('click', seleccionarMascotaJugador) botonReiniciar.addEventListener('click', reiniciarJuego) } function seleccionarMascotaJugador() { sectionSeleccionarMascota.style.display = 'none' sectionSeleccionarAtaque.style.display = 'flex' if (inputBolbasaur.checked) { spanMascotaJugador.innerHTML = inputBolbasaur.id mascotaJugador = inputBolbasaur.id } else if (inputCharmander.checked) { spanMascotaJugador.innerHTML = inputCharmander.id mascotaJugador = inputCharmander.id } else if (inputSquirtle.checked) { spanMascotaJugador.innerHTML = inputSquirtle.id mascotaJugador = inputSquirtle.id } else { alert('Selecciona un pokemon') } extraerAtaques(mascotaJugador) seleccionarMascotaEnemigo() } function extraerAtaques(mascotaJugador) { let ataques for (let i = 0; i < pokemones.length; i++) { if (mascotaJugador === pokemones[i].nombre) { ataques = pokemones[i].ataques } } mostrarAtaques(ataques) } function mostrarAtaques(ataques) { ataques.forEach((ataque) => { ataquesPokemon = ` <button id=${ataque.id} class="boton-de-ataque BAtaque">${ataque.nombre}</button> ` contenedorAtaques.innerHTML += ataquesPokemon }) botonPlanta = document.getElementById('boton-planta') botonFuego = document.getElementById('boton-fuego') botonAgua = document.getElementById('boton-agua') botones = document.querySelectorAll('.BAtaque') } function secuenciaAtaque() { botones.forEach((boton) => { boton.addEventListener('click', (e) => { if (e.target.textContent === '🍃') { ataqueJugador.push('PLANTA') console.log(ataqueJugador) boton.style.background = '#91C8E4' boton.disabled = true } else if (e.target.textContent === '💧') { ataqueJugador.push('AGUA') console.log(ataqueJugador) boton.style.background = '#91C8E4' boton.disabled = true } else { ataqueJugador.push('FUEGO') console.log(ataqueJugador) boton.style.background = '#91C8E4' boton.disabled = true } ataqueAleatorioEnemigo() }) }) } function seleccionarMascotaEnemigo() { let mascotaAleatoria = aleatorio(0, pokemones.length -1) spanMascotaEnemigo.innerHTML = pokemones[mascotaAleatoria].nombre ataquesPokemonEnemigo = pokemones[mascotaAleatoria].ataques secuenciaAtaque() } function ataqueAleatorioEnemigo() { let ataqueAleatorio = aleatorio(0,ataquesPokemonEnemigo.length -1) if (ataqueAleatorio == 0 || ataqueAleatorio == 1) { ataqueEnemigo.push('PLANTA') } else if (ataqueAleatorio == 3 || ataqueAleatorio == 4) { ataqueEnemigo.push('AGUA') } else { ataqueEnemigo.push('FUEGO') } console.log(ataqueEnemigo) iniciarPelea() } function iniciarPelea() { if (ataqueJugador.length === 5) { combate() } } function indexAmbosOponentes(jugador, enemigo) { indexAtaqueJugador = ataqueJugador[jugador] indexAtaqueEnemigo = ataqueEnemigo[enemigo] } function combate() { for (let index = 0; index < ataqueJugador.length; index++) { if(ataqueJugador[index] === ataqueEnemigo[index]) { indexAmbosOponentes(index, index) crearMensaje("EMPATE") } else if(ataqueJugador[index] === 'PLANTA' && ataqueEnemigo[index] === 'AGUA') { indexAmbosOponentes(index, index) crearMensaje("GANASTE") victoriasJugador++ spanVidasJugador.innerHTML = victoriasJugador } else if(ataqueJugador[index] === 'AGUA' && ataqueEnemigo[index] === 'FUEGO') { indexAmbosOponentes(index, index) crearMensaje("GANASTE") victoriasJugador++ spanVidasJugador.innerHTML = victoriasJugador } else if(ataqueJugador[index] === 'FUEGO' && ataqueEnemigo[index] === 'PLANTA') { indexAmbosOponentes(index, index) crearMensaje("GANASTE") victoriasJugador++ spanVidasJugador.innerHTML = victoriasJugador } else { indexAmbosOponentes(index, index) crearMensaje("PERDISTE") victoriasEnemigo++ spanVidasEnemigo.innerHTML = victoriasEnemigo } } revisarVidas() } function revisarVidas() { if (victoriasJugador === victoriasEnemigo) { crearMensajeFinal("AMBOS POKEMON TIENEN LA MISMA CANTIDAD DE PUNTOS, ¡ES UN EMPATE🙂!") } else if (victoriasJugador > victoriasEnemigo) { crearMensajeFinal("TIENES MAS PUNTOS QUE EL POKEMON ENEMIGO, ¡HAS GANADO😃!, BUEN TRABAJO") } else { crearMensajeFinal("EL POKEMON ENEMIGO TIENE MAS PUNTOS, ¡HAS PERDIDO😑!, SUERTE PARA LA PROXIMA") } } function crearMensaje(resultado) { let nuevoAtaqueDelJugador = document.createElement('p') let nuevoAtaqueDelEnemigo = document.createElement('p') sectionMensajes.innerHTML = resultado nuevoAtaqueDelJugador.innerHTML = indexAtaqueJugador nuevoAtaqueDelEnemigo.innerHTML = indexAtaqueEnemigo ataquesDelJugador.appendChild(nuevoAtaqueDelJugador) ataquesDelEnemigo.appendChild(nuevoAtaqueDelEnemigo) } function crearMensajeFinal(resultadoFinal) { sectionMensajes.innerHTML = resultadoFinal sectionReiniciar.style.display = 'block' } function reiniciarJuego() { location.reload() } function aleatorio(min, max) { return Math.floor(Math.random() * (max - min + 1) + min) } window.addEventListener('load', iniciarJuego) ```
Hace rato termine esta clase y tuve que hacer una parada de tres días para implementar varias cositas en el juego. Pero se siente muy bien tener los conocimientos para implementarlos. Así vamos hasta ahora: ![](https://static.platzi.com/media/user_upload/image-e9fbead2-50fc-4888-8265-1ec16150903b.jpg) ![](https://static.platzi.com/media/user_upload/image-2d780dbc-f160-4671-aaa5-388896a9b807.jpg)
![](https://static.platzi.com/media/user_upload/image-864e60d2-7f7b-4cfe-ab8f-a2c5d93243fa.jpg) ![](https://static.platzi.com/media/user_upload/image-8918b7e5-ad00-4456-8680-de821f58be46.jpg) ![](https://static.platzi.com/media/user_upload/image-72ff6189-9712-4be7-8e03-ebde3b0b0ed6.jpg)

Bueeeeno, no entendiiiii porque mi codigo se rompio y tampoco entendi nada desde la clase 44, me rindoooo

Aca dejo mi reto (nintendo no me demandes D:)

Falto yunobo pero si lo metia no quedaba simetrico xd

Hola a todos, así vamos:

  • Acá se muestra cuando el mokepon es más fuerte y tiene 6 ataques:

  • Así se ve cuando el mokepon enemigo es más fuerte y tiene 4 ataques:

  • Y así se ve el responsive:


Asi lo llevo, Zapato el mejor personaje 😎

Hola necesito ayuda con mi código, no encuentro el error

<code> 
const sectionSeleccionarAtaque = document.getElementById("seleccionar-ataque")
const sectionReiniciar = document.getElementById("reiniciar")
const BotonMascotaJugador = document.getElementById('Boton-Mascota')
const botonReiniciar = document.getElementById("boton-reiniciar") 
sectionReiniciar.style.display = "none"
const sectionSeleccionarMascota = document.getElementById("seleccionar-mascota")
const spanMascotaJugador = document.getElementById("mascota-jugador")
const spanMascotaEnemigo = document.getElementById("mascota-enemigo")
const spanVidasJugador = document.getElementById ( "vidas-jugador")
const spanVidasEnemigo = document.getElementById ( "vidas-enemigo")
const sectionMensajes = document.getElementById("resultado")
const ataquesDelJugador = document.getElementById("ataques-del-jugador")
const ataquesDelEnemigo = document.getElementById("ataques-del-enemigo")
const contenedorTarjetas = document.getElementById("contenedorTarjetas")
const contenedorAtaques = document.getElementById("contenedorAtaques")
let dogfights = []
let ataqueJugador = []
let ataqueEnemigo = []
let opcionDeDogfights
let inputBombon 
let inputJack 
let inputYamiro  
let mascotaJugador
let ataquesDogfight
let ataquesDogfightEnemigo
let botonFuego 
let botonAgua
let botonTierra 
let botones = []
let indexAtaqueJugador
let indexAtaqueEnemigo
let victoriasJugador = 0
let victoriasEnemigo = 0
let vidasJugador = 3
let vidasEnemigo = 3 
class dogfight {
    constructor(nombre, foto, vida) {
        this.nombre = nombre
        this.foto = foto
        this.vida = vida
        this.ataques = []
    }
}
// tengo que agregar las fotos//
let bombon = new dogfight('Bombon', '', 5)

let jack = new dogfight('Jack', ' ', 5)

let yamiro = new dogfight('Yamiro', ' ', 5)

bombon.ataques.push(
    { nombre: '💧', id: 'boton-agua' },
    { nombre: '💧', id: 'boton-agua' },
    { nombre: '💧', id: 'boton-agua' },
    { nombre: '🔥', id: 'boton-fuego' },
    { nombre: '🌱', id: 'boton-tierra' },
)

jack.ataques.push(
    { nombre: '🌱', id: 'boton-tierra' },
    { nombre: '🌱', id: 'boton-tierra' },
    { nombre: '🌱', id: 'boton-tierra' },
    { nombre: '💧', id: 'boton-agua' },
    { nombre: '🔥', id: 'boton-fuego' },
    
)

yamiro.ataques.push(
    { nombre: '🔥', id: 'boton-fuego' },
    { nombre: '🔥', id: 'boton-fuego' },
    { nombre: '🔥', id: 'boton-fuego' }, 
    { nombre: '💧', id: 'boton-agua' },
    { nombre: '🌱', id: 'boton-tierra' },
)

dogfights.push(bombon,jack,yamiro)
 
function iniciarJuego() {
    
    sectionSeleccionarAtaque.style.display = 'none'

    dogfights.forEach((dogfight) => {
        opcionDeDogfights = `
        <input type="radio" name="mascota" id=${dogfight.nombre} />
        <label class="tarjeta-de-dogfight" for=${dogfight.nombre}>
            <p>${dogfight.nombre}</p>
            <img src=${dogfight.foto} alt=${dogfight.nombre}>
        </label>
        `
    contenedorTarjetas.innerHTML +=opcionDeDogfights

     inputBombon= document.getElementById("Bombon")
     inputJack= document.getElementById("Jack")
    inputYamiro= document.getElementById("Yamiro")

    })
    BotonMascotaJugador.addEventListener('click',seleccionarMascotaJugador)  

    botonReiniciar.addEventListener("click", reiniciarJuego)
   }
function seleccionarMascotaJugador() {
   
    sectionSeleccionarMascota.style.display = "none"

   
    sectionSeleccionarAtaque.style.display = "flex"

    

   if (inputBombon.checked) {   
    spanMascotaJugador.innerHTML = inputBombon.id
    mascotaJugador = inputBombon.id
   } else if (inputJack.checked) {
    spanMascotaJugador.innerHTML = inputJack.id
    mascotaJugador = inputJack.id
   }else if (inputYamiro.checked){
    spanMascotaJugador.innerHTML = inputYamiro.id  
    mascotaJugador = inputYamiro.id
    } else {
        alert('Selecciona una mascota')
    }

    extraerAtaques(mascotaJugador)
    seleccionarMascotaEnemigo()
}
function extraerAtaques(mascotaJugador) {
    let ataques
    for (let i = 0; i < dogfights.length; i++) {
        if (mascotaJugador === dogfights [i].nombre) {
            ataques = dogfights[i].ataques
        }
        
    }
    mostrarAtaques(ataques)
}
function mostrarAtaques(ataques){
    ataques.forEach((ataque) => {
        ataquesDogfight = `
        <button id=${ataque.id} class="boton-de-ataque BAataque">${ataque.nombre}</button>
        `
        contenedorAtaques.innerHTML += ataquesDogfight
    })
     botonFuego = document.getElementById("Boton-Fuego")
     botonAgua = document.getElementById("Boton-Agua")
     botonTierra = document.getElementById("Boton-Tierra")
    botones = document.querySelectorAll (".BAataque")
function secuenciaAtaque () {
    botones.forEach((boton) => {
        boton.addEventListener("click", (e) => {
           if (e.target.textContent === "🔥") {
            ataqueJugador.push("FUEGO")
            console.log(ataqueJugador)
                boton.style.background = "#112f58"
                boton.disabled = true
           } else if (e.target.textContent ==="💧" ){
            ataqueJugador.push("AGUA")
            console.log(ataqueJugador)
            boton.style.background = "#112f58"
            boton.disabled = true
           } else {
            ataqueJugador.push("TIERRA")
            console.log(ataqueJugador)
           boton.style.background = "#112f58"
           boton.disabled = true
           }
           ataqueAleatorioEnemigo()
       })        
    })
}
function seleccionarMascotaEnemigo() {
    let mascotaAleatorio = aleatorio(0, dogfights.length -1)
    spanMascotaEnemigo.innerHTML = dogfights [mascotaAleatorio].nombre
    ataquesDogfightEnemigo = dogfights [mascotaAleatorio].ataques
    secuenciaAtaque ()

} 
function ataqueAleatorioEnemigo (){
    let ataqueAleatorio = aleatorio(0,ataquesDogfightEnemigo.lenght -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)
    iniciarPelea()    
} 

function iniciarPelea () {
    if (ataqueJugador.length === 5) {
        combate() 
    }
}
function indexAmbosOponentes(jugador,enemigo) {
    indexAtaqueJugador = ataqueJugador[jugador]
    indexAtaqueEnemigo = ataqueEnemigo [enemigo]
}

function combate (){
    function combate() {
        for (let index = 0; index < ataqueJugador.length; index++) {
            if(ataqueJugador[index] === ataqueEnemigo[index]) {
                indexAmbosOponentes(index, index);
                crearMensaje("EMPATE");  
            } else if (ataqueJugador[index] === 'FUEGO' && ataqueEnemigo[index] === 'TIERRA') {
                indexAmbosOponentes(index, index);
                crearMensaje("GANASTE");
                victoriasJugador++;
                spanVidasJugador.innerHTML = victoriasJugador;
            } else if (ataqueJugador[index] ==='AGUA' && ataqueEnemigo[index] === 'FUEGO') {
                indexAmbosOponentes(index, index);
                crearMensaje("GANASTE");
                victoriasJugador++;
                spanVidasJugador.innerHTML = victoriasJugador;
            } else if (ataqueJugador[index] === 'TIERRA' && ataqueEnemigo[index] === 'AGUA') {
                indexAmbosOponente(index, index);
                crearMensaje("GANASTE");
                victoriasJugador++;
                spanVidasJugador.innerHTML = victoriasJugador;
            } else {
                indexAmbosOponentes(index, index);
                crearMensaje("PERDISTE");
                victoriasEnemigo++;
                spanVidasEnemigo.innerHTML = victoriasEnemigo;
            }
        }
        revisarVidas();
    }
   
      revisarVidas()
}
function revisarVidas() {
 if (victoriasJugador === victoriasEnemigo ) {
    crearMensajeFinal("Esto fue un empate")
 } else if (
    victoriasJugador> victoriasEnemigo
 ) {
    crearMensajeFinal("FELICITACIONES! Ganaste 🎉😁")
 } else {
    crearMensajeFinal ("Lo siento, perdiste 😢 ")
 }
}
function crearMensaje(resultado) {
    let nuevoAtaqueDelJugador = document.createElement("p")
    let nuevoAtaqueDelEnemigo = document.createElement("p")

    sectionMensajes.innerHTML=resultado
    nuevoAtaqueDelJugador.innerHTML = indexAtaqueJugador
    nuevoAtaqueDelEnemigo.innerHTML = indexAtaqueEnemigo
  
    ataquesDelJugador.appendChild(nuevoAtaqueDelJugador)
    ataquesDelEnemigo.appendChild(nuevoAtaqueDelEnemigo)
}
function crearMensajeFinal(resultadoFinal) {
    sectionMensajes.innerHTML = resultadoFinal
    sectionReiniciar.style.display = 'block'
    

}
function reiniciarJuego () { 
    location.reload()
}

function aleatorio(min, max) {
    return Math.floor(Math.random() * (max - min + 1) + min)
      
}

window.addEventListener("load", iniciarJuego)
}

reto 1 solucionado pero no me demore mucho, le pregunte a GPT y compare con comentarios a ver que tenian, hay muchos incompletos. Pero se logro este reto con dos nuevos ataques.
Pero para el reto 2 del tipo y agregar un nuevo ataque y quede funcional, ni modos. Porque si quedo pero no funcional. El reto estaba interesante ojala hubieran dado la solución.

Así va el proyecto!


Agregue las nuevas mascotas continuando con la lógica de programación de la class Mokepon, colocando la nueva característica del tipo.

Utilice splice para los ataques aleatorios del enemigo y el condicional if para otorgar un punto de victoria al tipo de mokepon más fuerte entre jugador y pc

Finalmente Ya esta completo el Reto:

Fue Tardado pero lo hize jeje

No he puesto nada a lo largo del curso pero aqui dejo mi huella de como va mi proyecto a este punto.

  1. Logré completar ambos retos, añadi el ataque extra (El que se tiene fondo dorado) cuando el elemento de tu mascota es superior al del oponente (O lo mismo en viceversa)
  1. Ademas de que resolvi el problema de no tomar en cuenta los ataques de la mascota del enemigo investigando metodos de array y ocupando “Splice”.

Aprovecho para mencionar que hasta este punto todos los profesores han hecho un excelente trabajo en explicar las cosas muy bien y todos han sido muy carismaticos y agradables❤️



2do Reto cumplido

Agrego un guerrero mas me da miedo dañar todo lo que llevo Jajaja…

Cumplí ambos retos y un poco mas

  • Extra:
    Como habia que poner nuevos mokepones a la hora de poner las comprobaciones de los inputs vi que era muy repetitivo y extenso asi que opte por lo siguiente:
inputsMokepones.push(
        [inputCapipepo, capipepo], 
        [inputHipodoge, hipodoge], 
        [inputRatigueya, ratigueya], 
        [inputPydos, pydos], 
        [inputTucapalma, tucapalma], 
        [inputLangostelvis, langostelvis]
 );

function comprobarInputChecked() 
{
    for (let index = 0; index < inputsMokepones.length; index++) 
    {
        const inputEscogido = inputsMokepones[index]
        if (inputEscogido[0].checked == true)
        {
            spanMascotaJugador.innerHTML = inputEscogido[0].id;
            mokeponJugador = inputEscogido[1];
            return true;
        }
    }
}

function seleccionarMascotaJugador() 
{
    let escogioMokepon = comprobarInputChecked();

    if (escogioMokepon == true){
        seleccionarMascotaEnemigo();
    } else {
        alert("Escoge un Mokepon");
    }
}

Lo que hice fue guardar la referencia tanto del input como de su mokepon correspondiente, a partir de ahi hice una funcion que compruebe que input esta “checked” y segun eso poner al mokepon escogido tanto en el html como para el codigo en adelante ahorrandome el tener que hacer un nuevo if cada vez que meto un nuevo mokepon al juego

  • Reto1: No sacarse ataques de la manga
    Eso lo resolvi con el siguiente codigo algo largo:
function ataqueAleatorioEnemigo() {

    let ataqueAleatorio = aleatorio(0, ataquesMokeponEnemigo .length - 1);
    let ataquePosible;
    console.log(ataqueAleatorio)
    
    if (ataquesEnemigoEscogido.length == 0)
    {
        ataquesEnemigoEscogido = ataquesMokeponEnemigo;
    }
    
    ataquePosible = ataquesMokeponEnemigo[ataqueAleatorio];

    for (let index = 0; index < ataqueEnemigo.length; index = index) {
        if (ataquesEnemigoEscogido[ataqueAleatorio] == "NaN")
        {
            ataqueAleatorio = aleatorio(0, ataquesMokeponEnemigo .length - 1);
            ataquePosible = ataquesMokeponEnemigo[ataqueAleatorio];
            console.log("ReRoll")
        } else {
            console.log("Despues de evaluar se ha escogido el ataque: "+ index + ataquePosible.nombre);
            console.log(ataquesEnemigoEscogido[ataqueAleatorio])
            index++;
        }
        
    }
    if (ataquePosible.nombre == "🔥")
    {
        ataqueEnemigo.push("FUEGO");
        ataquesEnemigoEscogido[ataqueAleatorio] = "NaN";
    } else if (ataquePosible.nombre == "💧") {
        ataqueEnemigo.push("AGUA");
        ataquesEnemigoEscogido[ataqueAleatorio] = "NaN";
    } else {
        ataqueEnemigo.push("TIERRA");
        ataquesEnemigoEscogido[ataqueAleatorio] = "NaN";
    }
    console.log(ataqueEnemigo);
    console.log(ataquesEnemigoEscogido);
    iniciarCombate()
}

Comprueba que ataque escogio la maquina si es uno nuevo lo descarta con el NaN y el for comprueba que si ya fue escogido ese ataque vuelva a escoger otro hasta que sea uno nuevo

  • Reto2: Agregar mas mokepones y la mecanica de los tipos:
    Pues agregar los mokepones nuevos fue “sencillo” y lo de los tipos lo hice con la siguientes funciones:
function ventajaPorTipo() {
    const tipoJugador = mokeponJugador.tipo;
    const tipoEnemigo = mokeponEnemigo.tipo;

    if ((tipoJugador == "🔥" && tipoEnemigo == "🌱") || (tipoJugador == "💧" && tipoEnemigo == "🔥") || (tipoJugador == "🌱" && tipoEnemigo == "💧")){
        ventajaJugadorTipo = true;

        const ataquesJugador = mokeponJugador.ataques;
        const ataquesEnemigo = mokeponEnemigo.ataques;

        mokeponJugador.ataques.push({ nombre: ataquesJugador[0].nombre, id: ataquesJugador[0].id})
        mokeponEnemigo.ataques.push({ nombre: ataquesEnemigo[0].nombre, id: ataquesEnemigo[0].id})

        console.log(mokeponJugador.ataques);
        console.log(mokeponEnemigo.ataques);
    }
    mostrarAtaques();
}

function iniciarCombate()
{
    if (ataqueJugador.length == 5 && ventajaJugadorTipo == false)
    {
        combate()
    } else if (ataqueJugador.length == 6 && ventajaJugadorTipo == true) {
        combate()
    }
}

La puse justo despues de que se escoja el mokepon del jugador y del enemigo y solo comprueba si el jugador tiene un mokepon con tipo dominante si es haci agrega tanto al jugador como al enemigo un ataque que sea de su tipo y en la otra funcion comprueba si hay ventaja de tipo para que sepa cuantos turnos debe contar

Asi va mi proyecto ; )

Mi humilde proyecto

Esta parte del curso con Diego, sufri pero tambien aprendi bastante, vi que varios se quejaron, pero la realidad es que asi es como trabaja un dev en su dia a dia, haciendo muchos cambios a un proyecto…

Creo que en este curso faltó un poquito de game design / gestión / producción / planificación para el juego al menos hasta donde estoy viendo. Igualmente un éxito y gracias por compartir sus conocimientos.

Es interesante el complemento de los elementos de funcionamiento del juego. Sabia algunas partes, pero no esta mal complementar algunas mejoras y hacer robusta la pagina

Mi versión del juego:
[](
[](

Oportunidades en el juego mejorar el juego con el recurso aprendido: completar el ataque aleatorio, adicionar mascotas yadicionar un ataque a la mascota mas fuerte
2. Adicionar mascotas

1.Funcion AtaqueAleatorioEnemigo, agrupe por mascota
function ataqueAleatorioEnemigo(){
let ataqueAleatorio=aleatorio(0,ataquesMokeponEnemigo.length-1)
if (mascotaAleatorio === 0){
if ((ataqueAleatorio >= 0) && (ataqueAleatorio ❤️)){
ataqueEnemigo.push(‘AGUA’)
}else if(ataqueAleatorio == 3) {
ataqueEnemigo.push(‘FUEGO’)
}else {
ataqueEnemigo.push(‘TIERRA’)
}
}else mascota 1{ la logica anterior cambia el tipo de ataque
}else mascota 2{ la logica anterior cambia el tipo de ataque
}else mascota 3{ la logica anterior cambia el tipo de ataque
} …
iniciarPelea()
}//fin ataque enemigo

  1. de momento si de antemano se conoce cual es la mascota que es mas fuerte, agregarle el ataque adicional y en vez de 5 tendría 6. la situación es que para el usuario ya estaría por entendido y seleccionaría la fuerte, el azar (que le salga o no la mascota fuerte) solo lo tendría el enemigo.

Definitivamente de inicio a fin fue muy emocionante todo el aprendizaje. Sin embargo confieso que el aumento de la dificultal hace que en algunos casos el nivel de frustacion aumente cuando no logras entender la logica.

Sin mas, se logro solucionar el reto y se continua con el aprendizaje.

Gran esfuerzo de los docentes de Platzi en armar este curso. Puede parecer algo complicado y confuso, pero no deja de ser programación básica.
Éxitos en las clases que vienen, continúen esforzándose por aprender a programar.

No me gustó el diseño del juego con el que se ha estado trabajando en el curso hasta este punto, me pareció aburrido que el juego fuera tan simple así que hice mi propia versión llamada Plagiomon, le agregué más mecánicas de combate y añadí varios personajes con movimientos diferentes, habilidades especiales y así me ha quedado hasta ahora. Quería agregar más cosas como items y la habilidad para jugar con varios Plagiomon al mismo tiempo, mejor conocido como batallas dobles pero la cabeza solo me dio para hacerlos 1 vs 1, estuve como 2 semanas haciéndolo me dicen qué tal les parece pueden probar el juego aquí. https://leodexe.github.io/jsmokepon/index.html

Después de unas cuantas revisiones, logre mejorar la parte de ataque aleatorio del enemigo.
Primero, declare randomPet por fura de la función para poder usar su valor en la función de ataques del enemigo.
Esto lo hice debido a que, anteriormente, el PC ya había elegido sus ataques antes de que lo hiciera el jugador.



Luego guarde el arreglo de los ataques según la mascota elegida por el PC en la variable pcAttacks para poder ejecutar la selección aleatoria de ataques.



Primero comparé el ataque random con el nombre del ataque. Si coinciden, entonces agrego ese ataque a la variable **pcAttack **que más adelante me permite mostrar los ataques que eligió el PC.
Luego, eliminé ese ataque del arreglo pcAttacks para limitar las opciones del PC y que solo pueda elegir los ataques correspondientes a su mascota.

Asi me quedo.!

Esta parte con Diego ha sido una locura, el salto que se ha dado me ha costado, pero llegue! 😄

Por ahora mi único problema es que no logro que el enemigo no repita ataques que no pueda repetir.

De momento quedo así 😄

Agregue las imágenes de los Mokepones que iban a combatir, tambien pude hacer responsiva la parte del duelo

Hice mis propios mokepones y mi hija los nombro

¿Alguien me puede ayudar por favor?

Función ataque enemigo que tiene encuenta los ataques de cada mokepon y los elige de manera aleatoria.

function ataqueAleatorioEnemigo(){
    
    let condicion = 0

    while (condicion == 0) {
        let ataqueAleatorio = aleatorio(0,ataquesMokeponEnemigo.length-1)
        if(ataqueAleatorio == 0 || ataqueAleatorio == 1 || ataqueAleatorio == 2 && ataqueEnemigo1 > 0){
            ataqueEnemigo.push(ataquesMokeponEnemigo[ataqueAleatorio].nombre)
            ataqueEnemigo1--
            condicion++
        }else if(ataqueAleatorio == 3 && ataqueEnemigo2 > 0){
            ataqueEnemigo.push(ataquesMokeponEnemigo[ataqueAleatorio].nombre)
            ataqueEnemigo2--
            condicion++
        }else if(ataqueAleatorio == 4  && ataqueEnemigo3 > 0){
            ataqueEnemigo.push(ataquesMokeponEnemigo[ataqueAleatorio].nombre)
            ataqueEnemigo3--
            condicion++
        }
    }
    console.log(ataqueEnemigo)
    iniciarPelea()

}

Pude agregar los otros tres personajes.

Mejore la lógica con la que los ataques del enemigo son elegidos (gracias al método splice)

Agregue la mecánica que permite que cuando haya desventaja de tipo le de al jugador un ataque adicional para que pueda ganarle al contrincante

En esta clase me he sentido muy bien, porque todo lo que el profesor aplico a la mejora, lo fui realizando mientras iba desarrollando el código!

Asi me quedo

Así quedo mi juego con todo lo que trabajamos.
Mokepon

Espero en el futuro dejar un enlace con algunas mejoras que no he hecho, pero por ahora así quedo.

cambie un poco mi codigo, y pude agregar mas mokepones, mi hija me esta ayudando con la creacion de los personajes, yo solo codeo para que esten en el juego xD
Tengo el inconveniente de que después de hacer clic en un segundo ataque, se realizan varios combates y aumentan a medida que doy clic. ![](https://static.platzi.com/media/user_upload/image-0c4bdb44-5693-4c75-8752-3a73c8183591.jpg)