Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Aprende Creación de una Aplicación de Consola de Adivinanzas | Creación de Aplicaciones de Consola con Node.js
Desarrollo Backend con Node.js y Express.js

Creación de una Aplicación de Consola de Adivinanzas

Desliza para mostrar el menú

En este capítulo, prepárate para mejorar tus habilidades en aplicaciones de consola mientras exploramos la creación de un emocionante juego de Adivina el Número. Este juego interactivo desafía a los jugadores a poner a prueba su intuición adivinando un número generado aleatoriamente dentro de un rango predefinido. A lo largo del proceso, se abordarán conceptos fundamentales como:

  • Generación de números aleatorios;
  • Validación de entradas;
  • Interacción con el usuario;
  • Incluso guardar los resultados del juego en un archivo.

Desafío

Imagina sumergirte en una aplicación que promete emoción e intriga. Los jugadores están invitados a adivinar un número elegido misteriosamente dentro de un rango predefinido. La aplicación ofrece retroalimentación instantánea en cada intento y lleva un registro detallado de los intentos realizados.

Este ejemplo práctico es una oportunidad para perfeccionar habilidades en la construcción de aplicaciones CLI y demuestra el arte de crear programas interactivos.

Aplicación resultante

¡Observa la magia en acción! A continuación se muestra un GIF que ilustra la emocionante aplicación del juego Adivina el Número que estarás creando:

Creación de una aplicación de consola para un juego de adivinanzas

Se presentan dos caminos. La primera opción invita a embarcarse en el viaje sin ayuda, mientras que la segunda ofrece una guía útil para asegurar el éxito. Ya sea que te lances con valentía o sigas la guía estructurada, te espera una experiencia fascinante que te dejará con una aplicación de consola funcional y atractiva.

Plan maestro

  • Paso 1: Configuración e inicializaciones;
  • Paso 2: Definir los parámetros del juego;
  • Paso 3: Definir funciones utilitarias;
  • Paso 4: Lógica del juego;
  • Paso 5: Guardar el resultado del juego;
  • Paso 6: Iniciar el juego;
  • Conclusión;
  • Código completo de la aplicación.

Paso 1: Configuración e inicializaciones

Prepara el entorno creando un nuevo directorio y un archivo llamado app.js. Dentro de este archivo, incluimos los módulos necesarios:

const readline = require('readline');
const fs = require('fs').promises;

Crear una interfaz de Readline:

const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout
});
Descripción del código
expand arrow
  • readline: proporciona una interfaz para leer la entrada y escribir la salida en la consola;

  • readline.createInterface({ ... }): crea una instancia de la clase readline.Interface. Acepta un objeto con las propiedades input y output;

  • input: process.stdin: establece el flujo de entrada en process.stdin, permitiendo que el programa lea la entrada del usuario desde el teclado;

  • output: process.stdout: establece el flujo de salida en process.stdout, permitiendo que el programa muestre texto en la consola.

Explicación: Se importan los módulos necesarios: readline para la interacción con el usuario y fs.promises para operaciones con archivos. Luego, se crea una interfaz Readline llamada rl para gestionar la entrada y salida.

Paso 2: Definir los parámetros del juego

Establecer los números mínimo y máximo:

const minNumber = 1;
const maxNumber = 100;

Generar el número secreto:

const secretNumber =
  Math.floor(Math.random() * (maxNumber - minNumber + 1)) + minNumber;
Descripción del código
expand arrow
  • Math.random(): genera un número aleatorio de punto flotante entre 0 (incluido) y 1 (excluido);

  • maxNumber - minNumber + 1: calcula el rango de números posibles. Al sumar 1 se asegura que tanto minNumber como maxNumber estén incluidos en el rango;

  • Math.random() * (maxNumber - minNumber + 1): genera un número aleatorio entre 0 y el rango calculado;

  • Math.floor(...): redondea el número de punto flotante generado hacia abajo al entero más cercano, asegurando que el resultado sea un número entero dentro del rango deseado;

  • ... + minNumber: desplaza el número generado para que el rango comience en minNumber en lugar de 0.

Inicializar el contador de intentos:

let attempts = 0;

Explicación: Se define el rango de números (minNumber y maxNumber) dentro del cual se generará el número secreto. El número secreto se genera aleatoriamente utilizando Math.random() y se asigna a secretNumber. La variable attempts se inicializa para llevar el registro de los intentos del usuario.

Paso 3: Definir funciones utilitarias

Incorporación de una función utilitaria para una validación impecable:

function isValidGuess(guess) {
  return !isNaN(guess)
    && guess >= minNumber
    && guess <= maxNumber;
}
Descripción del código
expand arrow
  • !isNaN(guess): verifica si guess es un número válido. La función isNaN() devuelve false para números válidos, y el operador ! lo invierte a true;

  • guess >= minNumber: verifica que guess sea mayor o igual que minNumber, asegurando que no esté por debajo del rango permitido;

  • guess <= maxNumber: verifica que guess sea menor o igual que maxNumber, asegurando que no esté por encima del rango permitido;

  • &&: combina todas las condiciones utilizando el operador lógico AND. Todas las condiciones deben ser true para que la expresión completa se evalúe como true.

Explicación: La función isValidGuess verifica si la suposición del usuario es un número válido dentro del rango especificado (minNumber a maxNumber).

Paso 4: Lógica del juego

La mecánica central del juego a través de la función playGame:

function playGame() {
  rl.question(`Guess a number between ${minNumber} and ${maxNumber}: `, guess => {
    if (isValidGuess(guess)) {
      attempts++;
      const guessNumber = parseInt(guess);

      if (guessNumber === secretNumber) {
        console.log(`Congratulations! You guessed the number in ${attempts} attempts.`);
        saveGameResult(`Player won in ${attempts} attempts.`);
        rl.close();
      } else if (guessNumber < secretNumber) {
        console.log('Try higher.');
        playGame();
      } else {
        console.log('Try lower.');
        playGame();
      }
    } else {
      console.log('Please enter a valid number within the specified range.');
      playGame();
    }
  });
}
Descripción del código
expand arrow
  • rl.question(\Guess a number between ${minNumber} and ${maxNumber}: `, guess => { ... }): prompts the user to enter a number within the specified range. The user's input is passed to the callback function as the guess`;

  • if (isValidGuess(guess)) { ... }: verifica si el valor ingresado es una suposición válida usando la función isValidGuess();

  • attempts++;: incrementa el contador attempts para registrar cuántos intentos ha realizado el jugador;

  • const guessNumber = parseInt(guess);: convierte la entrada del usuario de cadena a entero usando parseInt();

  • if (guessNumber === secretNumber) { ... }: verifica si la suposición del jugador coincide con el número secreto. Si es así, el juego muestra un mensaje de éxito, guarda el resultado, cierra la interfaz de readline y finaliza el juego;

  • else if (guessNumber < secretNumber) { ... }: informa al jugador que el número secreto es mayor y llama nuevamente a playGame() para continuar el juego;

  • else { ... }: informa al jugador que el número secreto es menor y llama nuevamente a playGame() para continuar el juego;

  • else { ... } (después de la validación): gestiona la entrada no válida solicitando al jugador que ingrese un número válido dentro del rango permitido y luego llama nuevamente a playGame().

Explicación: La función playGame constituye el bucle principal del juego. Utiliza rl.question para solicitar al usuario una suposición. Si la suposición es válida, la función verifica si coincide con el número secreto. Si no es así, proporciona retroalimentación al usuario y continúa el bucle del juego de forma recursiva.

Paso 5: Guardar el resultado del juego

Implementación de la lógica para guardar los logros del usuario en el archivo game_results.txt.

async function saveGameResult(result) {
  try {
    await fs.appendFile('game_results.txt', `${result}\n`);
    console.log('Game result saved.');
  } catch (err) {
    console.log('Failed to save game result.');
  }
}
Descripción del código
expand arrow
  • async function saveGameResult(result) { ... }: define una función asíncrona llamada saveGameResult() que acepta un parámetro result y permite el uso de la palabra clave await dentro del cuerpo de la función;

  • try { ... } catch (err) { ... }: gestiona posibles errores que pueden ocurrir durante la operación asíncrona de archivos;

  • await fs.appendFile('game_results.txt', \${result}\n`);: appends the provided resultfollowed by a newline character to thegame_results.txtfile. Theawait` pausa la ejecución hasta que la operación de archivo se complete correctamente;

  • console.log('Game result saved.');: muestra un mensaje de confirmación cuando el resultado del juego se escribe correctamente en el archivo;

  • console.log('Failed to save game result.');: muestra un mensaje de error si la operación de archivo falla y una excepción es capturada por el bloque catch.

Explicación: La función saveGameResult utiliza fs.promises para agregar el resultado del juego a un archivo llamado game_results.txt. Proporciona retroalimentación sobre el éxito o fallo al guardar el resultado.

Paso 6: Iniciar el juego

Crear el mensaje de bienvenida e iniciar el juego:

console.log('Welcome to the Guess the Number game!');
playGame();

Explicación: Se muestra un mensaje de bienvenida y se inicia el ciclo del juego llamando a la función playGame.

Código completo de la aplicación

const readline = require("readline");
const fs = require("fs").promises;

const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
});

const minNumber = 1;
const maxNumber = 100;

const secretNumber =
  Math.floor(Math.random() * (maxNumber - minNumber + 1)) + minNumber;
let attempts = 0;

function isValidGuess(guess) {
  return !isNaN(guess) && guess >= minNumber && guess <= maxNumber;
}

function playGame() {
  rl.question(
    `Guess a number between ${minNumber} and ${maxNumber}: `,
    (guess) => {
      if (isValidGuess(guess)) {
        attempts++;
        const guessNumber = parseInt(guess);

        if (guessNumber === secretNumber) {
          console.log(
            `Congratulations! You guessed the number in ${attempts} attempts.`
          );
          saveGameResult(`Player won in ${attempts} attempts.`);
          rl.close();
        } else if (guessNumber < secretNumber) {
          console.log("Try higher.");
          playGame();
        } else {
          console.log("Try lower.");
          playGame();
        }
      } else {
        console.log("Please enter a valid number within the specified range.");
        playGame();
      }
    }
  );
}

async function saveGameResult(result) {
  try {
    await fs.appendFile("game_results.txt", `${result}\n`);
    console.log("Game result saved.");
  } catch (err) {
    console.log("Failed to save game result.");
  }
}

console.log("Welcome to the Guess the Number game!");
playGame();
Descripción del código
expand arrow
  • Líneas 1-2: importación del módulo incorporado readline y la API fs del módulo promises para operaciones de archivos asíncronas;

  • Líneas 4-7: creación de una interfaz readline llamada rl para leer la entrada del usuario y mostrar la salida en la consola;

  • Líneas 9-10: definición de los valores mínimo y máximo para el rango de adivinanza;

  • Líneas 12-13: generación de un número secreto aleatorio dentro del rango especificado usando Math.random();

  • Línea 14: inicialización del contador attempts para registrar la cantidad de intentos realizados por el jugador;

  • Líneas 16-18: definición de la función isValidGuess() para validar que el valor ingresado sea un número dentro del rango permitido;

  • Líneas 20-47: definición de la función recursiva playGame() que:

    • solicita al jugador que ingrese un número;
    • valida el valor ingresado;
    • verifica si la adivinanza coincide con el número secreto;
    • proporciona retroalimentación si la adivinanza es demasiado alta o baja;
    • continúa el juego llamándose a sí misma cuando sea necesario;
    • guarda el resultado y finaliza el juego cuando se adivina el número correcto;
  • Líneas 49-56: definición de la función asíncrona saveGameResult() que guarda el resultado del juego en el archivo game_results.txt y maneja posibles errores;

  • Línea 58: muestra un mensaje de bienvenida al jugador;

  • Línea 59: inicia el juego llamando a la función playGame().

Resumen

Este programa crea un juego de adivinanza de números. El jugador intenta adivinar un número generado aleatoriamente dentro de un rango especificado. El juego proporciona retroalimentación después de cada intento, registra la cantidad de intentos y guarda los resultados exitosos en un archivo de texto utilizando operaciones de archivos asíncronas.

¿Todo estuvo claro?

¿Cómo podemos mejorarlo?

¡Gracias por tus comentarios!

Sección 2. Capítulo 8

Pregunte a AI

expand

Pregunte a AI

ChatGPT

Pregunte lo que quiera o pruebe una de las preguntas sugeridas para comenzar nuestra charla

Sección 2. Capítulo 8
some-alt