57 - Desafío 4: Examen múltiple opciones con banderas del mundo


Problema: Consumir la API pública con la información de los distintos paises del mundo del problema anterior.

Se debe mostrar al azar una bandera y cuatro nombres de países en una serie de botones.

Contar la cantidad de respuestas correctas e incorrectas.

El sitio:

https://restcountries.eu

tiene una API pública que nos permite consultar todos los nombres de paises, banderas, capitales etc.

La dirección que debemos acceder para recuperar un archivo JSON con dicha información es:

https://restcountries.eu/rest/v2/all

Los datos que retorna tienen el siguiente formato:

Se debe mostrar la bandera y cuatro paises (uno de ellos correctos):

Solución

La lectura de la solución debería efectuarse luego de haber intentado resolverlo en forma individual.

index.html

<!DOCTYPE html>
<html lang="es">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Prueba</title>
    <link rel="stylesheet" href="estilos.css">
</head>

<body>
    <div id="juego">
        <div id="contenedor"></div>
        <div id="botones"></div>
        <div id="resultados"></div>
    </div>
    <script src="funciones.js"></script>
</body>

</html>

La hoja de estilo para mostrar la información.

estilos.css

* {
    margin: 0;
    padding: 0;
}

#juego {
    margin: 0 auto;
    width: 820px;
    display: flex;
    flex-direction: column;
    justify-content: center;
    height: 100vh;
}

img {
    width: 820px;
    height: 400px;
    border: 1px solid black;
    box-shadow: 0 0 10px black;
    margin-bottom: 1rem;
}

.boton {
    width: 204px;
    height: 100px;
    font-family: 'Lucida Sans', 'Lucida Sans Regular', 'Lucida Grande', 'Lucida Sans Unicode', Geneva, Verdana, sans-serif;
    font-size: 1.2rem;
    white-space: normal;
    box-shadow: 0 0 10px black;
}

#botones {
    display: flex;
    margin-bottom: 1rem;
}

#resultados {
    font-size: 2.5em;
    font-family: Georgia, 'Times New Roman', Times, serif;
    border: 1px solid black;
    box-shadow: 0 0 10px black;
    padding: 20px;
}

Toda la funcionalidad se encuentra en el archivo JavaScript.

funciones.js

function proximaBandera() {
    const paises = []
    let cant = 0
    do {
        let aleatorio = Math.trunc(Math.random() * 250)
        if (!paises.includes(aleatorio)) {
            paises.push(aleatorio)
            cant++
        }
    } while (cant < 4);
    let correcta = Math.trunc(Math.random() * 4)
    let pos = paises[correcta]
    let pregunta = `<img src="${datos[pos].flag}">`
    const d = document.querySelector("#contenedor")
    d.innerHTML = pregunta

    pregunta = `
            <input class="boton" type="button" value="${datos[paises[0]].name}" id="b1">
            <input class="boton" type="button" value="${datos[paises[1]].name}" id="b2">
            <input class="boton" type="button" value="${datos[paises[2]].name}" id="b3">
            <input class="boton" type="button" value="${datos[paises[3]].name}" id="b4">
        `
    const b = document.querySelector("#botones")
    b.innerHTML = pregunta
    for (let f = 1; f <= 4; f++)
        document.querySelector(`#b${f}`).addEventListener('click', evt => {
            if (correcta == `${f - 1}`)
                correctas++
                else {
                    incorrectas++
                    alert(`Es la bandera de ${datos[paises[correcta]].name}`)
                }
            actualizarResultados()
        })
}

function actualizarResultados() {
    document.querySelector("#resultados").innerHTML = `
        <p>Correctas: ${correctas}</p>
        <p>Incorrectas: ${incorrectas}</p>`
    proximaBandera()
}

let correctas = 0
let incorrectas = 0
let datos = null
fetch("https://restcountries.eu/rest/v2/all")
    .then(response => response.json())
    .then(bande => {
        datos = bande
        actualizarResultados()
    })

definimos tres variables globales para los contadores de correctas e incorrectas y la variable que almacenará la referencia al arreglo de datos que se recuperará del servidor:

let correctas = 0
let incorrectas = 0
let datos = null

Hacemos seguidamente la petición al servidor de todos los datos de países, donde actualizamos la variable 'datos' y llamamos a la función 'actualizarResultados':

fetch("https://restcountries.eu/rest/v2/all")
    .then(response => response.json())
    .then(bande => {
        datos = bande
        actualizarResultados()
    })

La función 'actualizarResultados' muestra la cantidad de preguntas correctas e incorrectas hasta este momento y pasa a llamar a la función 'proximaBandera':

function actualizarResultados() {
    document.querySelector("#resultados").innerHTML = `
        <p>Correctas: ${correctas}</p>
        <p>Incorrectas: ${incorrectas}</p>`
    proximaBandera()
}

La función 'proximaBandera' define un vector donde almacenaremos al azar 4 números aleatorios entre 0 y 249 (que debemos controlar que no se repitan):

function proximaBandera() {
    const paises = []
    let cant = 0
    do {
        let aleatorio = Math.trunc(Math.random() * 250)
        if (!paises.includes(aleatorio)) {
            paises.push(aleatorio)
            cant++
        }
    } while (cant < 4);

Ahora generamos un valor entre 0 y 3, el mismo representa la posición de la bandera que debe adivinar el usuario:

    let correcta = Math.trunc(Math.random() * 4)
    let pos = paises[correcta]

Mostramos la bandera generando una etiqueta 'img' y recuperando de la variable datos la bandera:

    let pregunta = `<img src="${datos[pos].flag}">`
    const d = document.querySelector("#contenedor")
    d.innerHTML = pregunta

Ahora generamos los cuatro botones con los nombre de países que hemos elegido al azar (uno de ellos es el correcto):

    pregunta = `
            <input class="boton" type="button" value="${datos[paises[0]].name}" id="b1">
            <input class="boton" type="button" value="${datos[paises[1]].name}" id="b2">
            <input class="boton" type="button" value="${datos[paises[2]].name}" id="b3">
            <input class="boton" type="button" value="${datos[paises[3]].name}" id="b4">
        `
    const b = document.querySelector("#botones")
    b.innerHTML = pregunta

Debemos registrar el evento 'click' para cada uno de los cuatro botones y dentro del mismo veriridar si coincide con la bandera correcta, aumentando en uno el contador respectivo y proceder a llamar a 'actualizarResultados' para que se muestre la siguiente bandera:

    for (let f = 1; f <= 4; f++)
        document.querySelector(`#b${f}`).addEventListener('click', evt => {
            if (correcta == `${f - 1}`)
                correctas++
                else {
                    incorrectas++
                    alert(`Es la bandera de ${datos[paises[correcta]].name}`)
                }
            actualizarResultados()
        })

Retornar