Fundamentos de Programación

1

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

2

Programación en Navegadores: Primeros Pasos

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

Don't repeat yourself (DRY)

45/84
Recursos

Uno de los consejos más importantes para la optimización de código, es no repetir el mismo.

Qué significa DRY: ¡no te repitas!

El acrónimo DRY significa “Don’t repeat yourself”, es uno de los principios del buen desarrollo de software que nos recomienda no repetir código fuente que ya hemos escrito.

Repetir código puede generar que, si el día de mañana debemos modificarlo en un lugar, también debamos modificarlo en los otros y si nos olvidamos de esto causará problemas en nuestra aplicación, además del esfuerzo que conlleva tener que realizar todas las modificaciones.

Si tenemos un mismo código fuente en un único punto de nuestra app, será mucho más fácil cambiarlo y también mejoraremos el rendimiento y el peso de los archivos.

Identificando puntos de mejora

A medida que tus habilidades y conocimiento en programación crezca, lograrás identificar con más claridad puntos donde estás repitiendo código y este pueda mejorarse.

Si por ejemplo tienes dos funciones que realizan la misma acción:

sumarNumeros(a, b) {
    return a + b;
}
realizarSumar(a, b) {
    return a + b;
}

Debes eliminar una de ellas, dado que estamos repitiendo código innecesariamente y podemos reutilizar la función en todos los puntos de nuestro código que necesitemos.

Si te encuentras capturando elementos HTML en las funciones del código Javascript:

function iniciarJuego() {
    let botonFuego = document.getElementById('boton-fuego');
    // ...
}
function realizarAtaque() {
    let botonFuego = document.getElementById('boton-fuego');
    // ...
}

Puedes realizar esta captura del elemento una sola vez por fuera de las funciones y utilizarla siempre que necesites:

let botonFuego = document.getElementById('boton-fuego');
function iniciarJuego() {
    // ...
}
function realizarAtaque() {
    // ...
}

La no repetición de código suele estar muy ligado al uso de funciones que poseen la lógica de tu aplicación. Pero también es un concepto que también tienes que aplicar al código CSS. ¿Cómo harías para no repetir clases CSS y poder reutilizarlas cuando las necesites?

Tipos de variables

Habrás observado que cuando declaramos una variable, utilizamos la palabra let por delante. La misma permite que el valor de esa variable cambie con el tiempo a medida que el usuario utiliza el software. Puedes modificar la variable siempre que lo necesites.

En ciertas ocasiones, modificar el valor de una variable puede generar problemas. Por ejemplo, evalúa el siguiente código:

let botonFuego = document.getElementById('boton-fuego');
function iniciarJuego() {
    // ...
}
function realizarAtaque() {
    // ...
}

¿Qué ocurriría si la función iniciarJuego() altera el valor de la variable botonFuego, y posteriormente la función realizarAtaque() intenta utilizar la misma? Posiblemente, la aplicación se rompa y ocurriría algún comportamiento inesperado.

Para evitar que una variable cambie de valor, sabiendo previamente que nunca debe cambiar, puedes usar el tipo de variable const en lugar de let.

const botonFuego = document.getElementById('boton-fuego');
// ...

Las variables “Constantes” no podrán cambiar nunca su valor. Ocurrirá un error si lo intentas.

Con este simple cambio, tu aplicación ya es un poco más segura a evitar errores inesperados por cambios en los valores de las variables que no deberían cambiar. A medida que ganes en conocimiento y experiencia en programación, sabrás cuándo utilizar let o cuándo utilizar const.

Conclusión

No es necesario obsesionarse con no repetir código fuente. A veces es necesario o no puede evitarse. Siempre es recomendable hacer un esfuerzo de escribir código de la forma más escalable y limpia posible y no repetirlo es uno de los principales factores.

Evaluar la repetición de código y el uso correcto de los tipos de variables son dos conceptos que tienes que comenzar a asimilar para convertirte en ese gran desarrollador de software que sueñas.

Son principios que aplican para casi cualquier lenguaje de programación, no solo para Javascript.


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

Aportes 128

Preguntas 47

Ordenar por:

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

Para evitar tener que esperar ir al navegador y ver los errores en consola, podemos descargar la extensión:


así poder ver los errores de esta manera:

espero les sirva!

despues de un rato buscando el atajo del teclado para seleccionar las let y cambiarlas por const… eso se hace con CTRL+ALT+FLECHA HACIA ABAJO

Resumen

Es buena práctica sacar las variables del tipo .getElementById de las funciones y colocarlas al inicio del js para ser usadas como variables globales. Así nos aseguramos de no estar repitiendo código. Es importante no definir más de una vez la misma variable y las funciones deben tener nombres distintos para evitar problemas.

Tipos de variables:
let = su valor puede variar, es decir cambia a lo largo del código
const = su valor será el mismo de inicio a fin

pro tip: cuando quieran seleccionar un palabra específica múltiples veces, pueden pararse sobre ella con el mouse y luego usar

ctrl + D 

con esto empezarán a seleccionar las palabras que estén escritas exactamente igual, una por uno de ahí para abajo

La linea 5 del código no es una variable. Cuidado ahí.

Una de las frases que más paz mental me da es esa de que podemos llegar a diferentes soluciones y si funciona, ESTÁ BIEN HECHO.

Les dejo un buen articulo para complementar el principio DRY

7 acrónimos que cualquier developer debería conocer

Les dejo esta extension, esta super porque te permite editar tus tags apertura y cierre de HTML al mismo tiempo.

Creo que es una practica muy avanzada para alguien que va empezando en la programacion, porque retirar los getElementByID de su locazlizacion original puede afectar al momento de querer leer el codigo siendo nuevo en la programacion, yo por mi parte las deje como comentario.

le agregue en el HTML la propiedad name con el valor boton a los 3 botones, entonces con el metodo getElementsByName()
me trae los 3 botones juntos en un array el cual recorro con un forEach y de esa manera les agrega uno por uno la propiedad disabled

<code> 
```let botones = document.getElementsByName("boton");
  botones.forEach((boton) => {
    boton.disabled = true;
  });

También pueden seleccionar toda la línea de código haciendo click en el número que la identifica a la izquierda.

Primera vez que para una constante no se dice “Como por ejemplo el número pi”… Muchas, muchas, muchas y más gracias por dar un ejemplo de que es un valor constate en el mundo real!!!😄

Yo instale esta extensión, me parece graciosa y útil

Variables:
­
Imagínate que te gusta el sushi de camarón 🍙 🍤y nomas compras ese.

const sushiDeCamaron

Como siempre compras ese sushi y no lo cambias, lo metes a esa variable const.
­
El asunto será cuando quieras pagar ese sushi de camarón y ver su precio. El precio no será el mismo este mes y dentro de 6 meses, el costo cambia.

Así que su precio será una variable let:

// lunes, 8 de agosto de 2022, precio de sushi de camarón:
 let sushiDeCamarón = 129

// lunes, 8 de marzo de 2023, precio de sushi de camarón:
 let sushiDeCamarón = 179

Con alt + arriba o abajo, pueden mover una linea de código sin cortar y pegar 😄

Si sienten que se van a perder durante el transcurso de la clase hagan un respaldo .txt de su script JS original, cuando estén moviendo sus variables let comenten a function pertenecen, así podrán saber en donde se ubican en caso de que código se rompa.

El código se puede mejorar

Despues de haber escrito el código y tenerlo funcional, se puede pasar a mejorarlo, hacerlo más corto y hacer que sea más agradable para el usuario. En lugar de tener una misma linea de código repetida múlples veces

<aside>
💡 Existe una opción para no tener lineas largas de código en visual studio
Solo hay que ir a view → word wrap y listo! también se puede usar alt + z

</aside>

Con esto podemos sacar variables locales que tienen el mismo nombre y se declaran múltiples veces y volverlas globales, esto evita repeticiones, además

Existen distintos tipos de variables

  • let es un tipo de variable que permite modificar el valor contenida en ella
  • const es un tipo de variable que guarda un valor que no queremos modificar en el futuro, una constante

Tengo este problema y no se como resolver 😦![]

Esta clase es oro puro

Otro atajo que me sirvió muchísimo, espero que a ustedes igual

Para MAC Command
Para Windows Control

Command + D: Para seleccionar todos los similares uno por uno.
Command + Shift + L: Para seleccionar todos los similares al mismo tiempo.

Consejo VS Code

.
Para hacer más rápida la búsqueda de código duplicado pueden usar el atajo

Control +F

Después de seleccionar el código elegido. Esto hará que busque, cuente y señale todas las coincidencias que haya en el código.

En pocas palabras, lo recomendable es crear nuestras variables como variables globales a menos que estas sean específicas para una función en particular.

Se siente la tención en el ambiente mientras el profe Diego, corta y pega el código previamente escrito…

Comparto mi código js

let ataqueJugador
let ataqueEnemigo
let vidasJugador = 3
let vidasEnemigo = 3

const $ = id => document.getElementById(id)
const $createE = element => document.createElement(element)

const $botonMascotaJugador = $('boton-mascota')
const $inputHipodoge = $('hipodoge')
const $inputCapipepo = $('capipepo')
const $inputRatigueya = $('ratigueya')

$botonMascotaJugador.addEventListener('click', seleccionarMascotaJugador)

const $spanMascotaJugador = $('mascota-jugador')

const $spanMascotaEnemigo = $('mascota-enemigo')

const $sectionMensajes = $('resultado')
const $ataquesJugador = $('ataques-jugador')
const $ataquesEnemigo = $('ataques-enemigo')
const $nuevoAtaqueJugador = $createE('p')
const $nuevoAtaqueEnemigo = $createE('p')

const $spanVidasJugador = $('vidas-jugador')
const $spanVidasEnemigo = $('vidas-enemigo')

const $botonReiniciar = $('boton-reiniciar')

let $botonFuego = $("boton-fuego")
let $botonAgua = $("boton-agua")
let $botonTierra = $("boton-tierra")

$botonFuego.addEventListener('click', ataqueFuego)
$botonAgua.addEventListener('click', ataqueAgua)
$botonTierra.addEventListener('click', ataqueTierra)

$botonReiniciar.addEventListener('click', reiniciarJuego)

const $sectionSeleccionarAtaque = $('seleccionar-ataque')

const $sectionSeleccionarMascota = $('seleccionar-mascota')

const $sectionReiniciar = $('reiniciar')

$sectionSeleccionarAtaque.style.display = 'none'
$sectionReiniciar.style.display = 'none'

function seleccionarMascotaJugador() {
    $sectionSeleccionarMascota.style.display = 'none'
    $sectionSeleccionarAtaque.style.display = 'flex'

    if($inputHipodoge.checked) {
        $spanMascotaJugador.innerHTML = 'Hipodoge'
    }
    else if ($inputCapipepo.checked) {
        $spanMascotaJugador.innerHTML = 'Capipepo'
    }
    else if ($inputRatigueya.checked) {
        $spanMascotaJugador.innerHTML = 'Ratigueya'
    }
    else {
        alert('Selecciona un Moqopon')
    }
    seleccionarMascotaEnemigo()
}

function seleccionarMascotaEnemigo() {
    let mascotaAleatoria = aleatorio(1,3)

    if (mascotaAleatoria == 1) {
        $spanMascotaEnemigo.innerHTML = 'Hipodoge'
    } else if (mascotaAleatoria == 2) {
        $spanMascotaEnemigo.innerHTML = 'Capipepo'
    } else {
        $spanMascotaEnemigo.innerHTML = 'Ratigueya'
    }
}

function ataqueFuego() {
    ataqueJugador = 'FUEGO🔥🔥🔥'
    ataqueAleatorioEnemigo()
}
function ataqueAgua() {
    ataqueJugador = 'AGUA💧💧💧'
    ataqueAleatorioEnemigo()
}
function ataqueTierra() {
    ataqueJugador = 'TIERRA🌱🌱🌱'
    ataqueAleatorioEnemigo()
}

function ataqueAleatorioEnemigo() {
    let ataqueAleatorio = aleatorio(1,3)

    if(ataqueAleatorio == 1) {
        ataqueEnemigo = 'FUEGO🔥🔥🔥'
    } else if (ataqueAleatorio == 2) {
        ataqueEnemigo = 'AGUA💧💧💧'
    } else {
        ataqueEnemigo = 'TIERRA🌱🌱🌱'
    }
    combate()
}

function combate() {
    if (ataqueJugador == ataqueEnemigo) {
        crearMensaje('EMPATE')
    } else if (ataqueJugador == 'FUEGO🔥🔥🔥' && ataqueEnemigo == 'TIERRA🌱🌱🌱') {
        crearMensaje('GANASTE')
        vidasEnemigo--
        $spanVidasEnemigo.innerHTML = vidasEnemigo
    } else if (ataqueJugador == 'AGUA💧💧💧' && ataqueEnemigo == 'FUEGO🔥🔥🔥') {
        crearMensaje('GANASTE')
        vidasEnemigo--
        $spanVidasEnemigo.innerHTML = vidasEnemigo
    } else if (ataqueJugador == 'TIERRA🌱🌱🌱' && ataqueEnemigo == 'AGUA💧💧💧') {
        crearMensaje('GANASTE')
        vidasEnemigo--
        $spanVidasEnemigo.innerHTML = vidasEnemigo
    } else {
        crearMensaje('PERDISTE')
        vidasJugador--
        $spanVidasJugador.innerHTML = vidasJugador
    }
    revisarVidas()
}

function revisarVidas() {
    if (vidasEnemigo == 0) {
        crearMensajeFinal('Felicitaciones Ganaste :)')
    } else if (vidasJugador == 0) {
        crearMensajeFinal('Felicitaciones Perdiste :(')
    }
}

function crearMensaje(resultado) {
    $sectionMensajes.innerHTML = resultado
    $nuevoAtaqueJugador.innerHTML = ataqueJugador
    $nuevoAtaqueEnemigo.innerHTML = ataqueEnemigo

    $ataquesJugador.appendChild($nuevoAtaqueJugador)
    $ataquesEnemigo.appendChild($nuevoAtaqueEnemigo)
}

function crearMensajeFinal(resultadoFinal) {
    $sectionMensajes.innerHTML = resultadoFinal

    $botonFuego.disabled = true
    $botonAgua.disabled = true
    $botonTierra.disabled = true

    $sectionReiniciar.style.display = 'block'

    $botonFuego.style.background = '#fff'
    $botonAgua.style.background = '#fff'
    $botonTierra.style.background = '#fff'
}

function reiniciarJuego() {
    location.reload()
}

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

muy buena clase para aprender otro tipo de opinion sobre js y otro tipo de variables, lo que hice fue dejar el documento anterior tal cual y crear otro para hacer las modificaciones 😃

La estructura del curso esta genial, de esta manera se comprende mejor el porqué de las cosas y para que la usamos.

Me dio paz mental y tranquilidad ver el código mejor ordenado aunque sigo sin entender del todo, TODO lo que he escrito XD. Aún así seguimos en la batalla.

woow, super muy buena clase

Uno de las herramientas de Visual Estudio Code es que podemos darle un formato al código al dar un “click derecho” a la pagina y luego “Dar formato al documento” o mediante su atajo del teclado " Shift + Alt + F "
Si el formato no te gusta puedes quitarlo con " Ctrl + Z "

El formato por defecto le pone " ; " al final de las líneas de código

WOW QUE GRAN PROFESOR QUE ERES DIEGO, TODO SE ENTIENDE RAPIDISIMO.

Excelente inicio del Profesor, para la optimización del código en JS. Muy claro y conciso al momento de explicar las mejores practicas y la diferencia entre let y const. 🧑🏼‍💻

JavaScript me rompe la cabeza ahora que estoy recién comenzando, pero el profesor Diego me la vuelve a armar.
Un genio y le entiendo todo.
Muchas gracias Diego

Les dejo este atajo, espero que les sirva.

Para MAC Option
Para Windows ALT

Para seleccionar varias líneas de código:

  1. Presionan Option
  2. Sin dejar de presionar Option irán marcando las líneas de código con el mouse.
Para evitar la repetición del mismo código en varias funciones, puedes seguir algunos enfoques comunes de organización y reutilización de código: 1. **Funciones Auxiliares**: Identifica partes del código que se repiten y extráelas en funciones auxiliares. Luego, llama a estas funciones desde tus funciones principales en lugar de repetir el código. 2. **Clases y Métodos**: Si estás trabajando en un contexto orientado a objetos (por ejemplo, JavaScript con clases), puedes encapsular el código repetido en métodos de clase y luego llamar a esos métodos cuando sea necesario. 3. **Parámetros Configurables**: Analiza el código repetido y determina qué partes son variables o configurables. Luego, pasa estas variables como parámetros a tus funciones en lugar de codificarlas directamente. 4. **Herencia y Polimorfismo**: Si estás trabajando en un lenguaje que soporta la herencia y el polimorfismo, considera si puedes crear una clase base con el código común y luego heredar de ella en tus clases específicas, sobrescribiendo solo lo que sea necesario. 5. **Patrones de Diseño**: Explora patrones de diseño como el patrón de diseño Singleton, el patrón de diseño Factory o el patrón de diseño Strategy, dependiendo de la situación y del problema que estés abordando. Estos patrones pueden ayudar a estructurar tu código de una manera que fomente la reutilización y la modularidad. 6. **Modularización**: Divide tu código en módulos o archivos separados y organízalos de manera que puedas importar y reutilizar funciones y clases según sea necesario. Al aplicar estos principios, puedes reducir la repetición de código y hacer tu código más mantenible, legible y escalable.

(ctrl + d ) estos teclados es para seleccionar en serie hacia abajo como hacia a los let.

cuando usamos la variable let : se puede modificar esta variable podrá modificarse es decir será dinámica durante un juego podría cambiar de texto etc.

cuando usamos const :es lo contrario se queda estable y no se modificara en el juego o en la pagina. puede servir para títulos.

esta fue la soliucion que logre antes de empezar esta clase 😃

// al crear una constante asignamos el $ con el fin de ahorrarno el texto del evento getElementById
const $ = selector => document.getElementById(selector)
let ataqueJugador 
let ataqueRival
let triunfosJugador = 3
let triunfosRival = 3
let sectionReiniciar = $('reiniciar')
let imgAvatar
let spanAvatar
let boton
let sectionSeleccionar
let alAzar

function iniciarJuego(){
    sectionSeleccionar = $('elegir-ataque')
    sectionSeleccionar.style.display = "none"
    
    sectionReiniciar.style.display = "none"

    //creación de variable con LET enlazando con el HTML el id del boton ( esto se podria ver como una conversión de HTML a JS)
    boton = $('boton-avatar') //nombre variable = objeto. tipo de metodo ('nombre de id en html')
    boton.addEventListener('click', seleccionarAvatarJugador) // nombre variable (el que se va manipular presente). tipo de metodo ( evento"argumento", variable que se va ejecutar después)
    
    boton = $('boton-aire')
    boton.addEventListener('click', ataqueAire)
    boton = $('boton-agua')
    boton.addEventListener('click', ataqueAgua)
    boton = $('boton-fuego')
    boton.addEventListener('click', ataqueFuego)
    boton = $('boton-tierra')
    boton.addEventListener('click', ataqueTierra)

    boton = $('boton-reiniciar')
    boton.addEventListener('click', reiniciarJuego)
}

// esta función permite identificar que avatar selecccionaste y dependiendo del valor verdadero dara a conocer tu elección
function seleccionarAvatarJugador(){
    sectionSeleccionar = $('elegir-avatar')
    sectionSeleccionar.style.display = "none"

    sectionSeleccionar = $('elegir-ataque')
    sectionSeleccionar.style.display = "flex"

    let inputAng = $('ang')
    let inputKatara = $('katara')
    let inputSuko = $('suko')
    let inputToph = $('toph')
    spanAvatar = $('avatar-jugador')
    imgAvatar = $('img-avatar-jugador')

    if(inputAng.checked){
        spanAvatar.innerHTML = 'Ang'
        imgAvatar.src = "../img/ang.png"
    } else if(inputKatara.checked){
        spanAvatar.innerHTML = 'Katara'
        imgAvatar.src = "../img/katara.png"
    } else if (inputSuko.checked){
        spanAvatar.innerHTML = 'Suko'
        imgAvatar.src = "../img/zuko.png"
    } else if(inputToph.checked){
        spanAvatar.innerHTML = 'Toph'
        imgAvatar.src = "../img/toph.png"
    } else{
        alert("Debes seleccionar un avatar para iniciar el juego.")
        reiniciarJuego()
    }

    seleccionarAvatarRival()
}

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

//Función para seleccionar rival la misma logica con el piedra, papel y tijeras
function seleccionarAvatarRival(){ 
    alAzar = (1,4)
    spanAvatar = $('avatar-rival')
    imgAvatar = $('img-avatar-rival')

    if(alAzar == 1){
        spanAvatar.innerHTML ='Ang'
        imgAvatar.src = "../img/ang.png"
    } else if(alAzar == 2){
        spanAvatar.innerHTML = 'Katara'
        imgAvatar.src = "../img/katara.png"
    } else if(alAzar == 3){
        spanAvatar.innerHTML = 'Suko'
        imgAvatar.src = "../img/zuko.png"
    } else if(alAzar == 4){
        spanAvatar.innerHTML = 'Toph'
        imgAvatar.src = "../img/toph.png"
    } else{
        alert("Debes seleccionar un avatar para dar inicio al juego.")
    }

}

function ataqueAire(){
    ataqueJugador = 'Aire'   
    seleccionarElementoRival()
}

function ataqueAgua(){
    ataqueJugador = 'Agua'
    seleccionarElementoRival()
}

function ataqueFuego(){
    ataqueJugador = 'Fuego'
    seleccionarElementoRival()
}

function ataqueTierra(){
    ataqueJugador = 'Tierra'
    seleccionarElementoRival()
}

function seleccionarElementoRival(){ 
    alAzar = Aleatorio(1,4)

    if(alAzar == 1){
        ataqueRival = 'Aire'
    } else if(alAzar == 2){
        ataqueRival = 'Agua'
    } else if(alAzar == 3){
        ataqueRival = 'Fuego'
    } else if(alAzar == 4){
        ataqueRival = 'Tierra'
    }

    combate()
}

function combate(){
    let spanVidasJugador = $('vida-jugador')
    let spanVidasRival = $('vida-rival')

    if( ataqueJugador == ataqueRival ){
        crearMensaje("Empataron")
    } else if((ataqueJugador == 'Aire' && ataqueRival == 'Agua')
    || (ataqueJugador == 'Tierra' && ataqueRival == 'Fuego') 
    || (ataqueJugador == 'Tierra' && ataqueRival == 'Aire')
    || (ataqueJugador == 'Fuego' && ataqueRival == 'Aire')
    || (ataqueJugador == 'Agua' && ataqueRival == 'Fuego')
    || (ataqueJugador == 'Agua' && ataqueRival == 'Tierra')){
        crearMensaje("Ganaste")
        triunfosRival --
        spanVidasRival.innerHTML = triunfosRival
    } else{
        crearMensaje("Perdiste")
        triunfosJugador --
        spanVidasJugador.innerHTML = triunfosJugador
    }

    revisarVidas()
}   

function revisarVidas(){
    if(triunfosRival == 0){
        crearMensajeFinal ('Felicitaciones, Ganaste! 🎆')
    } else if(triunfosJugador == 0){
        crearMensajeFinal ('A dado una gran pelea, pero tu rival a sido muy fuerte. Perdiste. 🙁')
    }
}

function crearMensaje(resultado){
    // en esta línea estamos ayudando a identificar createElement que etiqueta editar en HTML
    let sectionMensajes = $('resultado')
    let ataqueDelJugador = $('ataques-jugador')
    let ataqueDelRival = $('ataques-rival')

    // el metodo createElement permite editar el HTML desde JS cualquier etiqueta
    let nuevoAtaqueJugador = document.createElement('p')
    let nuevoAtaqueRival = document.createElement('p')
    
    sectionMensajes.innerHTML = resultado
    nuevoAtaqueJugador.innerHTML = ataqueJugador
    nuevoAtaqueRival.innerHTML = ataqueRival

    ataqueDelJugador.appendChild(nuevoAtaqueJugador)
    ataqueDelRival.appendChild(nuevoAtaqueRival)

}

function crearMensajeFinal(resultadoFinal){

    let sectionMensajes = $('resultado')

    sectionMensajes.innerHTML = resultadoFinal
    
    boton = $('boton-aire')
    boton.disabled = true
    boton = $('boton-agua')
    boton.disabled = true
    boton = $('boton-fuego')
    boton.disabled = true
    boton = $('boton-tierra')
    boton.disabled = true

    sectionReiniciar.style.display = "block"

}    

function reiniciarJuego(){
    location.reload()
}


//este metodo lo que hace es ejecutar la carga de la pagina después de haber invocado la funcion de la línea 1
window.addEventListener('load', iniciarJuego )

Intenté usar variables globales para ahorrar algunas líneas de código. Solo que, el juego está presentando errores con el botón de reiniciar y seleccionar la mascota 😐

yo lo que hice fue mandar todas las variables que usaba en 2 o mas funciones y las dejaba como global.

let ataqueJugador = ''
let ataqueEnemigo = ''
let vidaJugador = 3
let vidaEnemigo = 3
let sectionMensajeCombate  = document.getElementById('resultado')
let sectionSeleccionarAtaque = document.getElementById('seleccionar-ataque')
    sectionSeleccionarAtaque.style.display = 'none'
let sectionMensajeFinal = document.getElementById('mensajes')
    sectionMensajeFinal.style.display = 'none'
let btnReiniciar = document.getElementById('Reiniciar')
    btnReiniciar.style.display = 'none'  
let botonMascotaJugador = document.getElementById('boton-mascota')
    botonMascotaJugador.addEventListener('click', seleccionarMascotaJugador)
let botonFuego = document.getElementById('boton-fuego')
    botonFuego.addEventListener('click',ataqueFuego)
let botonAgua = document.getElementById('boton-agua')
    botonAgua.addEventListener('click',ataqueAgua)
let botonPlanta = document.getElementById('boton-planta') 
    botonPlanta.addEventListener('click',ataquePlanta)
let botonReiniciar = document.getElementById('reiniciar')
    botonReiniciar.addEventListener('click',reiniciarJuego)   
            


// función para saber que eleccion tomo el jugador
function seleccionarMascotaJugador(){
    let mokeponHipodoge = document.getElementById('hipodoge')
    let mokeponCapipepo = document.getElementById('capipepo')
    let mokeponRatigueya = document.getElementById('ratigueya')
    let mokeponLangostelvis = document.getElementById('langostelvis')
    let mokeponTucapalma = document.getElementById('tucapalma')
    let mokeponPydos = document.getElementById('pydos')
    let spanMascotaJugador = document.getElementById('mascota-jugador')
    let imagenMokeponCombate = document.getElementById('imagen-mokepon-jugador')
    let eleccionJugador= ''
    if(mokeponHipodoge.checked){         
        eleccionJugador = 'Hipodoge'
        imagenMokeponCombate.innerHTML = ('<img src="./imagenes/hipodoge.jpg" alt="">')        
    }else if(mokeponCapipepo.checked){
        eleccionJugador = 'Capipepo' 
        imagenMokeponCombate.innerHTML = ('<img src="./imagenes/capipepo.jpg" alt="">')         
    }else if(mokeponRatigueya.checked){
        eleccionJugador = 'Ratigueya' 
        imagenMokeponCombate.innerHTML = ('<img src="./imagenes/ratigueya.jpg" alt="">')   
    }else if(mokeponLangostelvis.checked){
        eleccionJugador = 'Langostelvis'
        imagenMokeponCombate.innerHTML = ('<img src="./imagenes/langostelvis.jpg" alt="">')   
    }else if(mokeponTucapalma.checked){
        eleccionJugador = 'Tucapalma' 
        imagenMokeponCombate.innerHTML = ('<img src="./imagenes/tucapalma.jpg" alt="">')  
    }else if(mokeponPydos.checked){
        eleccionJugador = 'Pydos'
        imagenMokeponCombate.innerHTML = ('<img src="./imagenes/pydos.jpg" alt="">')   
    }else{
        alert ('No seleccionaste a un Mokepon')
    }
    spanMascotaJugador.innerHTML = eleccionJugador
    if(eleccionJugador!=''){
        seleccionarMascotaEnemigo()
    }

    
}

//función para saber que mokepon elige la computadora
function seleccionarMascotaEnemigo(){
//mostramos la seccion ataque
    sectionSeleccionarAtaque.style.display = 'flex'
//ocultamos la seccion mascota
    let sectionSeleccionarMascota = document.getElementById('seleccionar-mascota')
        sectionSeleccionarMascota.style.display = 'none'
//la computadora elige un mokemon aleatorio con un numero de 1 a 6
    let eleccionEnemigo = aleatorio(1,6)
    let imagenMokeponCombate = document.getElementById('imagen-mokepon-enemigo')
    let spanMascotaEnemigo = document.getElementById('mascota-enemigo')
    if(eleccionEnemigo == 1){
        spanMascotaEnemigo.innerHTML = 'Hipodoge' 
        imagenMokeponCombate.innerHTML = ('<img src="./imagenes/hipodoge.jpg" alt="">')        
    }else if(eleccionEnemigo == 2){ 
        spanMascotaEnemigo.innerHTML = 'Capipepo' 
        imagenMokeponCombate.innerHTML = ('<img src="./imagenes/capipepo.jpg" alt="">')         
    }else if(eleccionEnemigo == 3){
        spanMascotaEnemigo.innerHTML = 'Ratigueya'
        imagenMokeponCombate.innerHTML = ('<img src="./imagenes/ratigueya.jpg" alt="">')   
    }else if(eleccionEnemigo == 4){
        spanMascotaEnemigo.innerHTML = 'Langostelvis'
        imagenMokeponCombate.innerHTML = ('<img src="./imagenes/langostelvis.jpg" alt="">')   
    }else if(eleccionEnemigo == 5){
        spanMascotaEnemigo.innerHTML = 'Tucapalma'
        imagenMokeponCombate.innerHTML = ('<img src="./imagenes/tucapalma.jpg" alt="">')   
    }else if(eleccionEnemigo == 6){
        spanMascotaEnemigo.innerHTML = 'Pydos' 
        imagenMokeponCombate.innerHTML = ('<img src="./imagenes/pydos.jpg" alt="">')  
    }        
    
}

// aca son las funciones de los 3 botones de ataque y se inicia la seleccion de ataque del enemigo
function ataqueFuego(){
    ataqueJugador = 'Fuego'
    fnAtaqueEnemigo()
}


function ataqueAgua(){
    ataqueJugador = 'Agua'
    fnAtaqueEnemigo()
}


function ataquePlanta(){
    ataqueJugador = 'Planta'
    fnAtaqueEnemigo()
}

//aca el enemigo genera un ataque aleatorio 1 es fuego 2 agua 3 planta
function fnAtaqueEnemigo(){
    let ataqueAleatorioEnemigo = aleatorio(1,3)
    if(ataqueAleatorioEnemigo == 1){
        ataqueEnemigo='Fuego'
    }else if(ataqueAleatorioEnemigo == 2){
        ataqueEnemigo='Agua'
    }else{
        ataqueEnemigo='Planta'
    } 
    combate()        
} 

//se inicia el combate y se da el mensaje del resultado, tambien se incia el contador de vidas 
function combate(){ 
    spanVidasJugador = document.getElementById('vida-jugador')
    spanVidasEnemigo = document.getElementById('vida-enemigo')
    if(ataqueJugador == ataqueEnemigo){
        crearMensaje('No hizo efecto')
    }else if(ataqueJugador == 'Fuego' && ataqueEnemigo == 'Planta'  ||  ataqueJugador == 'Agua' && ataqueEnemigo == 'Fuego'  ||  ataqueJugador == 'Planta' &&ataqueEnemigo == 'Agua'){
        crearMensaje('Fue: Muy eficaz')
        vidaEnemigo --
        spanVidasEnemigo.innerHTML=(vidaEnemigo)
    }else{
        crearMensaje('Fue: Poco eficaz')
        vidaJugador --
        spanVidasJugador.innerHTML=(vidaJugador)
    }
    revisarVidas()
}

//revisamos las vidas si algun jugador queda en 0 vidas se despliega la funcion mensaje final
function revisarVidas(){
    if (vidaJugador == 0 ){
        crearMensajeFinal('Perdiste')           
    }else if(vidaEnemigo == 0){
        crearMensajeFinal('Ganaste')
    }
}

 //aca creamos los mensajes del combate: ataque del jugador, enemigo y el resultado del mismo
 function crearMensaje(resultadoCombate){
    //creamos el parrafo y lo asignamos al id mensajes 
    let mensajeAtaqueJugador = document.getElementById('ataque-jugador')
    let mensajeAtaqueEnemigo = document.getElementById('ataque-enemigo')
    mensajeAtaqueJugador.innerHTML =(ataqueJugador)
    mensajeAtaqueEnemigo.innerHTML = (ataqueEnemigo)
    sectionMensajeCombate.innerHTML = (resultadoCombate)

}

//función mensaje final
function crearMensajeFinal(resultadoVidas){  
    //ocultamos el contenido del combate y mostramos el mensajes final en la misma ventana 
    sectionMensajeCombate.style.display = 'none'
    sectionMensajeFinal.style.display = 'flex'
    //mostramos boton reiniciar 
    btnReiniciar.style.display = 'flex'
    //creamos el parrafo y lo asignamos al id mensajes       
    let parrafoMensajeFinal = document.createElement('p')
    //enviamos el mensaje que se va a colocar en el parrafo creado anteriormente
    parrafoMensajeFinal.innerHTML = resultadoVidas
    sectionMensajeFinal.appendChild(parrafoMensajeFinal) 
    //deshabilitamos los botones de ataque
    botonAgua.disabled = true
    botonFuego.disabled = true
    botonPlanta.disabled = true
}

//función reinciar juego
function reiniciarJuego(){
    location.reload()
}

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

‘Por qué estos no las pusimes’, se oye al profesor en el minuto 16:35. Esa palabra no existe, es pusimos.

Esta fue mi solucion

const $ = (a)=> document.querySelector(a);

asi podemos seleccionar todos los elementos del html tanto por id como por clase

En muchas ocaciones, es importante diferenciar las variables globales de las locales, para ello se puede colocar una gv o una lv al inicio de la variable

Volviendo a repetir las clases 😥, tengo un error que no he logrado solucionar de clases más avanzadas

Esto es lo que necesitaba para poder aportar a mi código sin romperme la cabeza, ahora se siente ordenado y fácil de leer, muchas gracias :3

Un truco para seleccionar la línea mucho más rápido dando tres click rápidos seleccionas toda la línea, otro para borrar los espacios rápidamente al darle click en una línea y luego mantienes la tecla alt y le das click en otra línea vas a crear un nuevo cursor y luego que ya tengas todos los cursores en los espacios que deseas borrar solo debes de dar ctrl + x, y listo ya los espacios se han borrado

para optimizar este código(Cod1) lo solucione(Cod 2) de la siguiente forma

Cod1:

function crearMensajeEnemigo (){
  
  let parrafo = document.createElement('p')  
    parrafo.innerHTML = ataqueEnemigo
    mensajeEnemigo.appendChild(parrafo)
   }

function crearMensajeJugador (){

  let parrafo = document.createElement('p')
    parrafo.innerHTML = ataquejugador 
    mensajeJugador.appendChild(parrafo)
  }

Cod2

function crearMensaje (ataque,mensaje){
    let parrafo = document.createElement('p')  
    parrafo.innerHTML = ataque
    mensaje.appendChild(parrafo)
   }

En linux si quieren seleccionar diferentes partes del codigo presionen

Crtl+Shift+P

Despues busquen

Toggle Multi-Cursor Modifier

Presionen Enter y ya solo presionando Ctrl pueden seleccionar diferentes partes del codigo.

Fuente: https://stackoverflow.com/questions/60272595/vscode-multi-line-edit-select-on-linux-mint

Para leer mejor el código
En el menú View+Word Wrap
Mac Option+Z
Windows Alt+Z

Yo necesito un curso más básico que este =(

Muy útil lo de declarar variables al principio del código JS, lo que a mi entender quedarían como variables o constantes “globales”, las cuales podremos utilizar dentro de cualquier función.
Algo importante es nombrarlas de manera clara para dar una idea de a qué se refieren, así cuando las utilicemos dentro de las funciones será más fácil entender a qué hacen referencia.

let: una cajita donde podes ir guardando diferentes cosas

const: una caja fuerte donde solo puedes guardar una sola cosa para siempre

Hola!! Estoy presentando algunos problemas con esto de mover las variables, con el movimiento de las de la primera función se me rompió el juego y me empezó a aparecer este mensaje: ![](https://static.platzi.com/media/user_upload/image-f3893cf5-d5aa-443b-929d-ba75a99aaf27.jpg) Parece que hay un elemento no cargado en el DOM cuando se va a ejecutar esa función, revisé y tengo los nombres bien escritos y a diferencia del profe parece que ya no me funciona el `window.addEventListener('load', iniciarJuego)` que está al final. Ayuda please.
Hola tengo una duda al momento de escoger los ataques al principio no me aparece error en el momento en que empiezo a perder me aparece este error. He mirado como solucionarlo pero no doy con la solucion Mokemon.js:118 Uncaught TypeError: Cannot set properties of null (setting 'innerHTML') at combate (Mokemon.js:118:35) at ataqueAleatorioRival (Mokemon.js:97:5) at HTMLButtonElement.ataqueAgua (Mokemon.js:82:5)
un MASTER el profe
Dónde puedo dar like a esta clase !!! 💕💪🏻

Algo para que tengas en cuenta

Me hubiera gustado que eligieran otro juego más conocido :P pero en fin a seguir dandole
```js let ataqueJugador let ataqueEnemigo let vidasJugador = 3 let vidasEnemigo = 3 let seccionAtaque = document.getElementById('selecciona-ataque') let seccionReiniciar = document.getElementById('reiniciar') let botonFuego = document.getElementById('boton-fuego') let botonAgua = document.getElementById('boton-agua') let botonTierra = document.getElementById('boton-tierra') let sectionMensaje = document.getElementById('resultado') function iniciarJuego() { // let seccionAtaque = document.getElementById('selecciona-ataque') seccionAtaque.style.display = 'none' // let seccionReiniciar = document.getElementById('reiniciar') seccionReiniciar.style.display = 'none' let botonMascotaJugador = document.getElementById('boton-mascota'); botonMascotaJugador.addEventListener('click', seleccionarMascotajugador); // let botonFuego = document.getElementById('boton-fuego') botonFuego.addEventListener('click', ataqueFuego); // let botonAgua = document.getElementById('boton-agua') botonAgua.addEventListener('click', ataqueAgua); // let botonTierra = document.getElementById('boton-tierra') botonTierra.addEventListener('click', ataqueTierra); let botonReiniciar = document.getElementById('boton-reiniciar') botonReiniciar.addEventListener('click', reiniciarJuego) } function seleccionarMascotajugador() { let hipodoge = document.getElementById('hipodoge'); let capipepo = document.getElementById('capipepo'); let ratigueya = document.getElementById('ratigueya'); let spanMascotaJugador = document.getElementById('mascota-jugador') if(hipodoge.checked) { spanMascotaJugador.innerHTML = 'Hipodoge' } else if(capipepo.checked) { spanMascotaJugador.innerHTML = 'Capipepo' } else if(ratigueya.checked === true) { spanMascotaJugador.innerHTML = 'Ratigueya' } else { alert('Debes seleccionar una mascota para jugar 🕹️') return } seleccionarMascotaEnemigo() let seccionMascota = document.getElementById('seleccionar-mascota') seccionMascota.style.display = 'none' // let seccionAtaque = document.getElementById('selecciona-ataque') seccionAtaque.style.display = 'flex' // let seccionReiniciar = document.getElementById('reiniciar') seccionReiniciar.style.display = 'none' } function seleccionarMascotaEnemigo() { let mascotaAleatoria = aleatorio(1,3) let spanMascotaEnemigo = document.getElementById('mascota-enemigo') if(mascotaAleatoria === 1) { spanMascotaEnemigo.innerHTML = 'Hipodoge'; } else if(mascotaAleatoria === 2) { spanMascotaEnemigo.innerHTML = 'Capipepo'; } else { spanMascotaEnemigo.innerHTML = 'Ratigueya'; } } function ataqueFuego() { ataqueJugador = 'FUEGO' ataqueAleatorioEnemigo() } function ataqueAgua() { ataqueJugador = 'AGUA' ataqueAleatorioEnemigo() } function ataqueTierra() { ataqueJugador = 'TIERRA' ataqueAleatorioEnemigo() } function ataqueAleatorioEnemigo() { let ataqueAleatorio = aleatorio(1,3) if(ataqueAleatorio === 1) { ataqueEnemigo = 'FUEGO'; } else if(ataqueAleatorio === 2) { ataqueEnemigo = 'AGUA'; } else { ataqueEnemigo = 'TIERRA'; } combate() } function combate() { let spanVidasJugador = document.getElementById('vidas-jugador') let spanVidasEnemigo = document.getElementById('vidas-enemigo') if (ataqueJugador == ataqueEnemigo) { crearMensaje("EMPATE") } else if (ataqueJugador === 'FUEGO' && ataqueEnemigo === 'TIERRA' || ataqueJugador === 'AGUA' && ataqueEnemigo == 'FUEGO' || ataqueJugador === 'TIERRA' && ataqueEnemigo == 'AGUA') { crearMensaje("GANASTE") vidasEnemigo-- spanVidasEnemigo.innerHTML = vidasEnemigo } else { crearMensaje("PERDISTE") vidasJugador-- spanVidasJugador.innerHTML = vidasJugador } revisarVidas() } function revisarVidas() { if(vidasJugador === 0) { crearMensajeFinal('Lo siento, perdiste 😣') } else if(vidasEnemigo === 0) { crearMensajeFinal('Felicitaciones, ganaste 🏆') } } function crearMensaje(resultado) { // let sectionMensaje = document.getElementById('resultado') let ataqueDelJugador = document.getElementById('ataque-del-jugador') let ataqueDelEnemigo = document.getElementById('ataque-del-enemigo') let nuevoAtaqueDelJugador = document.createElement('p') let nuevoAtaqueDelEnemigo = document.createElement('p') sectionMensaje.innerHTML = resultado nuevoAtaqueDelJugador.innerHTML = ataqueJugador nuevoAtaqueDelEnemigo.innerHTML = ataqueEnemigo ataqueDelJugador.appendChild(nuevoAtaqueDelJugador) ataqueDelEnemigo.appendChild(nuevoAtaqueDelEnemigo) } function crearMensajeFinal(resultadoFinal) { // let sectionMensaje = document.getElementById('resultado') sectionMensaje.innerHTML = resultadoFinal // let botonFuego = document.getElementById('boton-fuego') botonFuego.disabled = true // let botonAgua = document.getElementById('boton-agua') botonAgua.disabled = true // let botonTierra = document.getElementById('boton-tierra') botonTierra.disabled = true // let seccionReiniciar = document.getElementById('reiniciar') seccionReiniciar.style.display = 'flex' } function reiniciarJuego() { location.reload(); } function aleatorio(min, max) { return Math.floor(Math.random() * (max - min + 1) + min) } window.addEventListener('load', iniciarJuego); ```
Me da muy buena impresión cuando en los recursos de la clase dejan contribuciones como la de *Kevin Fiorentino (Platzi Contributor)*. Esos resúmenes no son fáciles de hacer y puede pensarse que no hacen falta, pero en algunas clases y sobre todo al principio cambian por completo la experiencia porque siempre tienes el texto en el que apoyarte. Así que muchas gracias a Kevin y a todos que hacen este tipo de aportaciones para los cursos🤍
Nuevo aprendizaje
cc
vayv
mi mundo
hola alguien por españa, italia para hacer relaciones e intercambiar conocimiento, dejo mi perfil de instagram: <https://www.instagram.com/diego.martin.caballero/>
Código JS: ```js let btnPetPlayer = document.getElementById("btn-select-pet"); let btnFire = document.getElementById("btn-fire-attack"); let btnWater = document.getElementById("btn-water-attack"); let btnEarth = document.getElementById("btn-earth-attack"); let btnReset = document.getElementById("btn-reset-game"); let inputHipodoge = document.getElementById("hipodoge"); let inputCapipepo = document.getElementById("capipepo"); let inputRatigueya = document.getElementById("ratigueya"); let petPlayer = document.getElementById("pet-player"); let petEnemy = document.getElementById("pet-enemy"); let spanLifesPlayer = document.getElementById("lifes-player"); let spanLifesEnemy = document.getElementById("lifes-enemy"); let attackPlayer; let attackEnemy; let lifesPlayer = 3; let lifesEnemy = 3; function typeAttack(value) { let attack = ""; switch (value) { case 1: { attack = "Fuego 🔥"; break; } case 2: { attack = "Agua 💧"; break; } case 3: { attack = "Tierra 🌱"; break; } default: { attack = "ATTACK NOT FOUND"; break; } } return attack; } function changeDisplay(label, status) { var element = document.getElementById(label); if (element) { element.style.display = status; } } function changeStatusVisible(label, status) { let element = document.getElementById(label); if (element) { element.disabled = status; } } function petSelected(numberPet) { let pet = ""; switch (numberPet) { case 1: { pet = "Hipodoge"; break; } case 2: { pet = "Capipepo"; break; } case 3: { pet = "Ratigueya"; break; } default: { pet = "PET NO ENCONTRADA"; break; } } return pet; } function random(min, max) { return Math.floor(Math.random() * (max - min + 1) + min); } function selectPetPlayer() { if ( inputHipodoge.checked || inputCapipepo.checked || inputRatigueya.checked ) { selectPetEnemy(); changeDisplay("select-attack", "flex"); changeDisplay("select-pet", "none"); } if (inputHipodoge.checked) { petPlayer.innerHTML = petSelected(1); } else if (inputCapipepo.checked) { petPlayer.innerHTML = petSelected(2); } else if (inputRatigueya.checked) { petPlayer.innerHTML = petSelected(3); } else { alert("Error: No seleccionaste a tú mascota."); } } function selectPetEnemy() { let petEnemySelected = petSelected(random(1, 3)); petEnemy.innerHTML = petEnemySelected; } function resultCombat() { console("console-player", attackPlayer); console("console-enemy", attackEnemy); if (lifesEnemy > 0 && lifesPlayer > 0) { if (attackEnemy == attackPlayer) { overwriteConsole("Empate! 🤷‍♂️"); } else if (attackPlayer == "Fuego" && attackEnemy == "Tierra") { lifesEnemy--; overwriteConsole("Ganaste ronda 🎈🎉"); } else if (attackPlayer == "Agua" && attackEnemy == "Fuego") { lifesEnemy--; overwriteConsole("Ganaste ronda 🎈🎉"); } else if (attackPlayer == "Tierra" && attackEnemy == "Agua") { lifesEnemy--; overwriteConsole("Ganaste ronda 🎈🎉"); } else { lifesPlayer--; overwriteConsole("Perdiste ronda 😢"); } } else { changeStatusVisible("btn-fire-attack", true); changeStatusVisible("btn-water-attack", true); changeStatusVisible("btn-earth-attack", true); changeDisplay("reset-game", "flex"); if (lifesEnemy == 0) { overwriteConsole( "¡Ganaste la partida! 🎈🎉
- - - Juego finalizado - - -" ); } else if (lifesPlayer == 0) { overwriteConsole( "¡Perdiste la partida! 😭
- - - Juego finalizado - - -" ); } } spanLifesEnemy.innerHTML = lifesEnemy + " 💓"; spanLifesPlayer.innerHTML = lifesPlayer + " 💓"; } function console(label, msg) { let console = document.getElementById(label); let paragraph = document.createElement("p"); paragraph.innerHTML = msg; console.appendChild(paragraph); } function overwriteConsole(msg) { let console = document.getElementById("console"); console.innerHTML = msg; } function innitGame() { changeDisplay("select-attack", "none"); changeDisplay("reset-game", "none"); btnPetPlayer.addEventListener("click", selectPetPlayer); btnFire.addEventListener("click", () => { attackPlayer = typeAttack(1); attackEnemy = typeAttack(random(1, 3)); resultCombat(); }); btnWater.addEventListener("click", () => { attackPlayer = typeAttack(2); attackEnemy = typeAttack(random(1, 3)); resultCombat(); }); btnEarth.addEventListener("click", () => { attackPlayer = typeAttack(3); attackEnemy = typeAttack(random(1, 3)); resultCombat(); }); btnReset.addEventListener("click", () => { location.reload(); }); } window.addEventListener("load", innitGame); ```
Para eliminar espacios en blanco pongan Ctrl+F y en buscar "\n\n" y marcada la opción ".\* " y en remplazar "\n "y dan en Remplazar todo ![](https://static.platzi.com/media/user_upload/2023-12-29_23h10_04-bdf19147-5bab-4772-a4dc-aae153301c62.jpg)
```js buenos dias Nelson opina : a fin de no perderme quem variables corresponden con que funciones he dejado en el script sus variables correspondientes- como se ve en el script que acabo de enviar gracias Atentamentre Nelson Alfonso Gutierrez ```

lo estaba haciendo en la marcha, y cuando me salio el error de doble variable me asuste ya que hasta se perdió el centrado.

arriba! diego buena clase percibo que si eres un buen docente…

let playerAttack
let enemyAttack
let mascotaJugador
let mascotaEnemigo
let vidasJugador = 3
let vidasEnemigo = 3

function styleDisplay(htmlElementName, displayOption) {
    let variableSP = document.getElementById(htmlElementName)
    variableSP.style.display = displayOption
}

function eventListener(htmlElementName, event, functionName) {
    let variableAEL = document.getElementById(htmlElementName)
    variableAEL.addEventListener(event, functionName)
}

function inputChecked(htmlElementName) {
    let variableIC = document.getElementById(htmlElementName)
    if (variableIC.checked) {
        return true
    } else {
        return false
    }
}

function setDisabled(htmlElementName,state) {
    let variableSD = document.getElementById(htmlElementName)
    variableSD.disabled = state
}

function innerHTMLfunction(htmlElementName, text) {
    let variableIHTML = document.getElementById(htmlElementName)
    variableIHTML.innerHTML = text
}

function iniciarJuego() {
    styleDisplay('seleccionar-ataque', 'none')
    
    eventListener('boton-mascota', 'click', seleccionarMascotaJugador)

    eventListener('boton-fuego', 'click', ataqueFuego)
    eventListener('boton-agua', 'click', ataqueAgua)
    eventListener('boton-tierra', 'click', ataqueTierra)
    eventListener('boton-reiniciar', 'click', restartGame)
}

function ataqueFuego() {
    playerAttack = "🔥"
    enemyRandomAttack()
}

function ataqueAgua() {
    playerAttack = "💧"
    enemyRandomAttack()
}

function ataqueTierra() {
    playerAttack = "🌱"
    enemyRandomAttack()
}

function seleccionarMascotaJugador() {
    styleDisplay('reiniciar','none')

    if (inputChecked('hipodoge')) {
        innerHTMLfunction('mascota-jugador', 'Hipodoge')
        mascotaJugador = "Hipodoge"
        sectionsSwipe()
    } else if (inputChecked('capipepo')) {
        innerHTMLfunction('mascota-jugador', 'Capipepo')
        mascotaJugador = "Capipepo"
        sectionsSwipe()
    } else if (inputChecked('ratigueya')) {
        innerHTMLfunction('mascota-jugador', 'Ratigüeya')
        mascotaJugador = "Ratigüeya"
        sectionsSwipe()
    } else {
        alert("Seleccione su mascota")
    }

    seleccionarMascotaEnemiga()   
}

function seleccionarMascotaEnemiga() {
    let randNum = randomNumber(1,3)

    if (randNum == 1) {
        innerHTMLfunction('mascota-enemigo', 'Hipodoge')
        mascotaEnemigo = "Hipodoge"
    } else if (randNum == 2) {
        innerHTMLfunction('mascota-enemigo', 'Capipepo')
        mascotaEnemigo = "Capipepo"
    } else {
        innerHTMLfunction('mascota-enemigo', 'Ratigüeya')
        mascotaEnemigo = "Ratigüeya"
    }
}

function sectionsSwipe() {
    innerHTMLfunction('vidas-jugador', vidasJugador)
    innerHTMLfunction('vidas-enemigo', vidasEnemigo)
    styleDisplay('seleccionar-ataque','flex')
    styleDisplay('seleccionar-mascota','none')
}

function enemyRandomAttack() {
    let randomAttack = randomNumber(1,3)
    
    if (randomAttack == 1) {
        enemyAttack = "🔥"
    } else if (randomAttack == 2) {
        enemyAttack = "💧"
    } else {
        enemyAttack = "🌱"
    }
    combat()
}

function combat() {
    if (playerAttack == enemyAttack) {
        createMessage("¡EMPATE!")
    } else if (playerAttack == "🔥" && enemyAttack == "🌱") {
        createMessage("¡BATALLA GANADA!")
        vidasEnemigo--
        innerHTMLfunction('vidas-enemigo',vidasEnemigo)
    } else if (playerAttack == "💧" && enemyAttack == "🔥") {
        createMessage("¡BATALLA GANADA!")
        vidasEnemigo--
        innerHTMLfunction('vidas-enemigo',vidasEnemigo)
    } else if (playerAttack == "🌱" && enemyAttack == "💧") {
        createMessage("¡BATALLA GANADA!")
        vidasEnemigo--
        innerHTMLfunction('vidas-enemigo',vidasEnemigo)
    } else {
        createMessage("¡BATALLA PERDIDA!")
        vidasJugador--
        innerHTMLfunction('vidas-jugador',vidasJugador)
    }
    revisarVidas()
}

function revisarVidas() {
    if (vidasEnemigo == 0) {
        createFinalMessage("¡GANASTE LA GUERRA!")
        styleDisplay('reiniciar','block')
    } else if (vidasJugador == 0){
        createFinalMessage("¡PERDISTE LA GUERRA!")
        styleDisplay('reiniciar','block')
    }
}

function innerAndAppend(typeOfElement,text,HTMLelementName) {
    let variableIandA1 = document.createElement(typeOfElement)
    let variableIandA2 = document.getElementById(HTMLelementName)
    variableIandA1.innerHTML = text
    variableIandA2.appendChild(variableIandA1)
}

function createMessage(resultado) {
    innerHTMLfunction("resultado",resultado)
    innerAndAppend('p',playerAttack,"ataques-del-jugador")
    innerAndAppend('p',enemyAttack,"ataques-del-enemigo")
}

function createFinalMessage(finalResult) {
    innerHTMLfunction("resultado",finalResult)
    setDisabled('boton-fuego',true)
    setDisabled('boton-agua',true)
    setDisabled('boton-tierra',true)
}

function restartGame() {
    location.reload()
}

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

window.addEventListener('load', iniciarJuego)

wow para mi es otro level

gracias por el comentario

Me encantan todos los profesores de Platzi, contagian la energia!

don’t repeat yourself (dry) --> no te repitas

const --> constante
let --> variable

¡Gracias por la clase! Estuve un poco confundido con ciertas cosas, pero logré entenderlas. Este curso ha pasado de algo muy básico a cosas complejas. La evolución es evidente, pero los profesores explican de maravilla y te motivan a seguir hasta el final.

DRY, a trasladar el código repetido arriba , antes iniciar las funciones y así puede eliminar las repeticiones.

Yo lo hice así, remplacé todos los document.get.ElementById() por esta función.

function  returnElement(nameElement)
{
    let newElement = document.getElementById(nameElement)
    return newElement
}

Lo que yo hice fue crear más funciones para no tener tantas variables globales, se me hace más facil de leer y organizado.
Si se les ocurren mejoras avisen 😃

// Variables globales
let ataqueJugador = '';
let ataqueEnemigo = '';
let resultado = '';
let vidasJugador = 3;
let vidasEnemigo = 3;


function iniciarJuego() {
  ocultarElemento('container-juego');
  ocultarElemento('reiniciar');
  
  // Selección de mascota del jugador	
  evento('boton-mascota', 'click', seleccionarMascotaJugador);

  // Botones de ataque del jugador
  evento('boton-fuego', 'click', ataqueFuego);
  evento('boton-agua', 'click', ataqueAgua);
  evento('boton-tierra', 'click', ataqueTierra);

  // Reiniciar el juego
  evento('boton-reiniciar', 'click', reiniciarJuego);
}

// Funciones para la mascota del jugador
function seleccionarMascotaJugador() {
  let inputDragon = document.getElementById('dragon');
  let inputPerro = document.getElementById('perro');
  let inputPez = document.getElementById('pez');
  let spanMascotaJugador = document.getElementById('mascota-jugador');

  switch (true) {
    case inputDragon.checked:
      spanMascotaJugador.innerHTML = '🐉 Dragoncito';
      break;
    case inputPerro.checked:
      spanMascotaJugador.innerHTML = '🐕 Perrito';
      break;
    case inputPez.checked:
      spanMascotaJugador.innerHTML = '🦈 Pececito';
      break;
    default:
      alert('selecciona una mascota');
  }

  mostrarElemento('container-juego', 'flex');
  ocultarElemento('container-mascota');

  seleccionarMascotaEnemigo();
}

function ataqueFuego() {
  ataqueJugador = '🔥';
  elementoAtaqueEnemigo();
}
function ataqueAgua() {
  ataqueJugador = '💧';
  elementoAtaqueEnemigo();
}
function ataqueTierra() {
  ataqueJugador = '🌱';
  elementoAtaqueEnemigo()
}

// Funciones para la mascota enemiga
function seleccionarMascotaEnemigo() {
  let mascotaAleatoria = aleatorio(1, 3);
  let spanMascotaEnemigo = document.getElementById('mascota-enemigo');

  switch (mascotaAleatoria) {
    case 1:
      spanMascotaEnemigo.innerHTML = '🐉 Dragoncito';
      break;
    case 2:
      spanMascotaEnemigo.innerHTML = '🐕 Perrito';
      break;
    default:
      spanMascotaEnemigo.innerHTML = '🦈 Pececito';
      break;
  }
}

function elementoAtaqueEnemigo() {
  let ataqueAleatorio = aleatorio(1, 3);

  switch (ataqueAleatorio) {
    case 1:
      ataqueEnemigo = '🔥';
      break;
    case 2:
      ataqueEnemigo = '💧';
      break;
    default:
      ataqueEnemigo = '🌱';
      break;
  }
  
  combate();
}

// Combate
function combate() {
  switch (ataqueJugador, ataqueEnemigo) {
    case ataqueEnemigo, ataqueJugador:
      resultado = 'Empataste';
      break;
    case '🌱', '💧' || '💧', '🔥' || '🔥', '🌱':
      resultado = 'Ganaste';
      vidasEnemigo--;
      break;
    default:
      resultado = 'Perdiste';
      vidasJugador--;
      break;
  }

  actualizarVidas(vidasJugador, vidasEnemigo);

  crearMensaje(ataqueJugador, 'ataque-jugador');
  crearMensaje(ataqueEnemigo, 'ataque-enemigo');
  crearMensaje(resultado, 'resultado-ronda');

  if (revisarVidas() !== '') crearMensajeGanador(revisarVidas());
}

// Actualizar vidas
function actualizarVidas(vidasJugador, vidasEnemigo) {
  modificarMensaje(vidasJugador, 'vidas-jugador');
  modificarMensaje(vidasEnemigo, 'vidas-enemigo');
}

// document.getElementById(id).innerHTML = mensaje;
function crearMensajeGanador(ganador) {
  crearMensaje(`🏆 El ganador es ${ganador} 🏆`, 'resultado');

  // Desactivar botones para evitar ataques después de terminado el juego
  desactivarBotones('boton-fuego');
  desactivarBotones('boton-agua');
  desactivarBotones('boton-tierra');

  // Mostrar botón de reinicio
  mostrarElemento('reiniciar', 'flex');
}

function desactivarBotones(id) {
  document.getElementById(id).disabled = true;
}

function revisarVidas() {
  let ganador = '';
  switch (true) {
    case vidasJugador === 0:
      ganador = '🤬 Enemigo';
      break;
    case vidasEnemigo === 0:
      ganador = '😂 Jugador';
      break;
  }
  return ganador;
}

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

// Funciones auxiliares
function evento(id, evento, funcion) {
  document.getElementById(id).addEventListener(evento, funcion);
}

function ocultarElemento(id) {
  document.getElementById(id).style.display = 'none';
}

function mostrarElemento(id, display) {
  document.getElementById(id).style.display = display;
}

function crearMensaje(mensaje, id) {
  let parrafo = document.createElement('p');
  parrafo.innerHTML = mensaje;
  document.getElementById(id).appendChild(parrafo);
  document.getElementById(id).scrollTop = document.getElementById(id).scrollHeight;
}

function modificarMensaje(mensaje, id) {
  document.getElementById(id).innerHTML = mensaje;
}

function aleatorio(min, max) { 
  return Math.floor(Math.random() * (max - min + 1) + min) ;
}
window.addEventListener('load', iniciarJuego);

Buenos días: hice a si;
let botonFuego = document.getElementById(‘boton-fuego’,‘boton-agua’,‘boton-tierra’)
botonFuego.disabled = true
let spanVidasJugador = document.getElementById(‘vidas-jugador’,‘vidas-enemigo’)

EL resto no me atreví a tocarlo 😐

(DRY)

<code> function crearMensajeFinal(resultadoFinal) {
    
    let sectionMensajes = document.getElementById('resultado')

    sectionMensajes.innerHTML = resultadoFinal

    var buttonPoderes = ['boton-fuego', 'boton-flechas', 'boton-esqueletos']

    buttonPoderes.forEach(function(ataques){
       var botones= document.getElementById(ataques);
       botones.disabled = true;
    })

    let sectionReiniciar = document.getElementoById('reiniciar')
    sectionReiniciar.style.display = 'block'
}

En vez del ataque me aparece [HTMLDIVELEMENT] ?

Llevo atrapado en esta parte bastante tiempo y la verdad no se como solucionar. mil gracias

Nunca había sentido tanto placer por el orden y la no repetición. :v

Los docentes de platzi son muy bien seleccionados. Son carismáticos; saben transpolar su conocimiento, que es mucho, para que uno como estudiante pueda entender. Además, generan mucha emoción al expresar sus ideas.

Felicito en gran medida a su equipo de trabajo.

Yo crearía variables globales o funciones que me permitan acceder a variables que se deban usar una y otra vez.

lo primero que se me vino a la cabeza fue esto

function crearMensaje(resultado, ataqueJugador, ataqueEnemigo) {
    const sectionMensajes = document.getElementById('resultado');
    sectionMensajes.innerHTML = resultado;

Otra manera muy sencilla y rápida de seleccionar una línea entera es haciendo 3 clicks rápidos sobre la línea en cualquier punto.

Sirve también para seleccionar varias líneas a la vez con mantener presionada la tecla Alt así como hace el profesor Diego.

Entonces JDC nos creco un monton de variables repetidas… tocara hablar seriamente con él.

Espero poder ayudarle a quien tenga alguna duda con el reto del profesor.

En el código se repetían demasiados…

document.getElementById();.

En la primera función que corre cuando el html ha cargado por completo tenía algunas secciones configuradas para que no se muestren, como un ejemplo tenemos:

let seccion2 = document.getElementById("seccionElegirAtaque");
seccion2.style.display = "none";

//Este código se repetía algunas otras veces más junto con más secciones en el resto del código//
.
Lo que hice para optimizar y no volver a repetir el mismo código fue hacer la siguiente función:

function seccion2(x) {
let seccion2 = document.getElementById("seccionElegirAtaque");
seccion2.style.display = x;
}

Y listo, ahora en la primera función que corre en el script, a la cual yo reconozco como la principal tengo el siguiente código:

//Para ocultar la seccion...
seccion2("none"); 

//Para mostrar la seccion con el display tipo flex...
seccion2("flex");

A partir de aquí remplazé esta misma función por las partes de mi código donde se repetía todo el código.

Espero les haya ayudado compañeros 😃

Con "CTRL + F " pueden abrir el buscador de palabras del visual studio, así pueden identificar más rápido esas variables repetidas.

Ya me parecía raro tantas variables iguales dentro de funciones, yo en un inicio pensaba dejarlas afuera y no lo hice por el tema que los profes no lo hacían.

Que increible es Diego, de verdad que da una seguridad escucharlo, y mostrar como es que programa, increible.

Desde el inicio no sé porqué pero no seguí el código y estas dos últimas clases no tuve que editarlo, lo tengo como al final de esta clase 😁

VAR vs LET vs CONST

la variable const quiere decir que no se puede volver a reasignar, cuando el valor de una variable const es un array o object estos si pueden ser mutables

Un consejo…ya que a partir de acá se va a modificar el código inicial de JavaScript…creen otro archivo .js, copien todo a ese nuevo archivo y en el HTML llaman a ese nuevo archivo en script…de esta manera tendrán el código mejorado y lo podrán comparar con el anterior.

💪 Evita repetir el MISMO código varias veces, esto para tener un código limpio y fácil de escalar.
 
Aprendí que:

  • Let para variables que pueden modificar su valor varias veces
  • Const para variables que cuando reciban su valor se quede fijo.

Es interesante el proceso de depuración que sucede ya en esta etapa. Es importante ir paso a paso, declarar las variables que vamos a ir utilizando y siempre luego si revisar nuestro código para saber como optimizarlo sin que falle.

Lo que veo es que el Profe Diego es de muy cortar y pegar para hacer optimizaciones. En este punto ya me hace mucha falta entender del control de versión en GitHub, por ahora tuve que crear una carpeta aparte con una copia del proyecto anterior.
Solo hago esto porque no se como llevar el control de versiones ahora mismo y siento que en cualquier momento voy a romper el código.

Es interesante la forma en que se usaron todas las variables “ID” como una declaracion de variables globales. Sabia de estos, pero nunca como usarlos en las practicas. Ahora si me quedo claro el como se deben aplicar. Espero seguir aprendiendo mas sobre esto.

Que pedazo de crack que es el profe diego. Lo banco a muerte en 2 clases me demostró que es un monstro!