Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Aprenda Construindo um Aplicativo de Adivinhação no Console | Construindo Aplicações de Console com Node.js
Desenvolvimento Backend com Node.js e Express.js

Construindo um Aplicativo de Adivinhação no Console

Deslize para mostrar o menu

Neste capítulo, prepare-se para aprimorar suas habilidades em aplicações de console enquanto exploramos a criação de um empolgante aplicativo de jogo Adivinhe o Número. Este jogo interativo desafiará os jogadores a exercitar sua intuição ao tentar adivinhar um número gerado aleatoriamente dentro de um intervalo predefinido. Ao longo do caminho, vamos desvendar os mistérios de conceitos fundamentais como:

  • Geração de números aleatórios;
  • Validação de entrada;
  • Interação com o usuário;
  • Até mesmo salvar os resultados do jogo em um arquivo.

Desafio

Imagine explorar um aplicativo que promete emoção e suspense. Os jogadores são convidados a adivinhar um número misteriosamente escolhido dentro de um intervalo predefinido. O aplicativo oferece feedback instantâneo a cada tentativa e mantém um registro detalhado das tentativas realizadas.

Este exemplo prático é a sua oportunidade de aprimorar suas habilidades na construção de aplicativos CLI e demonstra a arte de criar programas interativos.

Aplicativo Final

Veja a mágica acontecendo! Abaixo está um GIF ilustrando o empolgante aplicativo de jogo Adivinhe o Número que você irá desenvolver:

Construindo um Aplicativo de Adivinhação no Console

Você se depara com dois caminhos. A primeira opção convida você a embarcar na jornada sem assistência, enquanto a segunda oferece um guia útil para garantir seu sucesso. Seja mergulhando com ousadia ou seguindo o guia estruturado, você terá uma experiência fascinante que resultará em um aplicativo de console funcional e envolvente.

Plano Mestre

  • Passo 1: Configuração e Inicializações;
  • Passo 2: Definir Parâmetros do Jogo;
  • Passo 3: Definir Funções Utilitárias;
  • Passo 4: Lógica do Jogo;
  • Passo 5: Salvar Resultado do Jogo;
  • Passo 6: Iniciar o Jogo;
  • Conclusão;
  • Código Completo do Aplicativo.

Passo 1: Configuração e Inicializações

Prepare o ambiente criando um novo diretório e um arquivo chamado app.js. Dentro deste arquivo, importamos os módulos necessários:

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

Crie uma interface Readline:

const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout
});
Descrição do código
expand arrow
  • readline: fornece uma interface para ler entradas e escrever saídas no console;

  • readline.createInterface({ ... }): cria uma instância da classe readline.Interface. Aceita um objeto com as propriedades input e output;

  • input: process.stdin: define o fluxo de entrada como process.stdin, permitindo que o programa leia a entrada do usuário pelo teclado;

  • output: process.stdout: define o fluxo de saída como process.stdout, permitindo que o programa exiba texto no console.

Explicação: Importação dos módulos necessários: readline para interação com o usuário e fs.promises para operações com arquivos. Em seguida, criação de uma interface Readline chamada rl para gerenciar entrada e saída.

Etapa 2: Definir parâmetros do jogo

Definição dos números mínimo e máximo:

const minNumber = 1;
const maxNumber = 100;

Gerar o número secreto:

const secretNumber =
  Math.floor(Math.random() * (maxNumber - minNumber + 1)) + minNumber;
Descrição do código
expand arrow
  • Math.random(): gera um número de ponto flutuante aleatório entre 0 (inclusivo) e 1 (exclusivo);

  • maxNumber - minNumber + 1: calcula o intervalo de números possíveis. Adicionar 1 garante que tanto minNumber quanto maxNumber estejam incluídos no intervalo;

  • Math.random() * (maxNumber - minNumber + 1): gera um número aleatório entre 0 e o intervalo calculado;

  • Math.floor(...): arredonda o número de ponto flutuante gerado para baixo até o inteiro mais próximo, garantindo que o resultado seja um número inteiro dentro do intervalo desejado;

  • ... + minNumber: desloca o número gerado para que o intervalo comece em minNumber em vez de 0.

Inicializar o contador de tentativas:

let attempts = 0;

Explicação: Definimos o intervalo de números (minNumber e maxNumber) dentro do qual o número secreto será gerado. O número secreto é gerado aleatoriamente usando Math.random() e atribuído à variável secretNumber. A variável attempts é inicializada para acompanhar as tentativas do usuário.

Passo 3: Definir Funções Utilitárias

Disponibilização de uma função utilitária para validação precisa:

function isValidGuess(guess) {
  return !isNaN(guess)
    && guess >= minNumber
    && guess <= maxNumber;
}
Descrição do código
expand arrow
  • !isNaN(guess): verifica se guess é um número válido. A função isNaN() retorna false para números válidos, e o operador ! inverte para true;

  • guess >= minNumber: verifica se guess é maior ou igual a minNumber, garantindo que não esteja abaixo do intervalo permitido;

  • guess <= maxNumber: verifica se guess é menor ou igual a maxNumber, garantindo que não esteja acima do intervalo permitido;

  • &&: combina todas as condições usando o operador lógico AND. Todas as condições devem ser true para que a expressão inteira seja avaliada como true.

Explicação: A função isValidGuess verifica se o palpite do usuário é um número válido dentro do intervalo especificado (minNumber a maxNumber).

Etapa 4: Lógica do Jogo

A mecânica central do jogo por meio da função 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();
    }
  });
}
Descrição do 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 se o valor inserido é um palpite válido usando a função isValidGuess();

  • attempts++;: incrementa o contador attempts para acompanhar quantos palpites o jogador fez;

  • const guessNumber = parseInt(guess);: converte a entrada do usuário de string para inteiro usando parseInt();

  • if (guessNumber === secretNumber) { ... }: verifica se o palpite do jogador corresponde ao número secreto. Se corresponder, o jogo exibe uma mensagem de sucesso, salva o resultado, fecha a interface readline e encerra o jogo;

  • else if (guessNumber < secretNumber) { ... }: informa ao jogador que o número secreto é maior e chama playGame() novamente para continuar o jogo;

  • else { ... }: informa ao jogador que o número secreto é menor e chama playGame() novamente para continuar o jogo;

  • else { ... } (após a verificação de validação): trata entradas inválidas solicitando ao jogador que insira um número válido dentro do intervalo permitido e, em seguida, chama playGame() novamente.

Explicação: A função playGame constitui o loop principal do jogo. Ela utiliza rl.question para solicitar um palpite do usuário. Se o palpite for válido, a função verifica se o palpite corresponde ao número secreto. Caso contrário, fornece um feedback ao usuário e continua o loop do jogo de forma recursiva.

Etapa 5: Salvar o Resultado do Jogo

Implementação da lógica para salvar as conquistas do usuário no arquivo 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.');
  }
}
Descrição do código
expand arrow
  • async function saveGameResult(result) { ... }: define uma função assíncrona chamada saveGameResult() que aceita um parâmetro result e permite o uso da palavra-chave await dentro do corpo da função;

  • try { ... } catch (err) { ... }: trata possíveis erros que podem ocorrer durante a operação assíncrona de arquivo;

  • await fs.appendFile('game_results.txt', \${result}\n`);: appends the provided resultfollowed by a newline character to thegame_results.txtfile. Theawait` pausa a execução até que a operação de arquivo seja concluída com sucesso;

  • console.log('Game result saved.');: exibe uma mensagem de confirmação quando o resultado do jogo é gravado com sucesso no arquivo;

  • console.log('Failed to save game result.');: exibe uma mensagem de erro caso a operação de arquivo falhe e uma exceção seja capturada pelo bloco catch.

Explicação: A função saveGameResult utiliza fs.promises para adicionar o resultado do jogo a um arquivo chamado game_results.txt. Fornece um retorno sobre o sucesso ou falha ao salvar o resultado.

Etapa 6: Iniciar o Jogo

Criar a mensagem de boas-vindas e iniciar o jogo:

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

Explicação: Exibimos uma mensagem de boas-vindas e iniciamos o loop do jogo chamando a função playGame.

Código Completo do Aplicativo

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();
Descrição do código
expand arrow
  • Linhas 1-2: importação do módulo interno readline e da API fs do módulo promises para operações assíncronas de arquivos;

  • Linhas 4-7: criação de uma interface readline chamada rl para ler a entrada do usuário e exibir a saída no console;

  • Linhas 9-10: definição dos valores mínimo e máximo para o intervalo de adivinhação;

  • Linhas 12-13: geração de um número secreto aleatório dentro do intervalo especificado usando Math.random();

  • Linha 14: inicialização do contador attempts para rastrear o número de tentativas feitas pelo jogador;

  • Linhas 16-18: definição da função isValidGuess() para validar se o valor inserido é um número dentro do intervalo permitido;

  • Linhas 20-47: definição da função recursiva playGame() que:

    • solicita ao jogador que insira um palpite;
    • valida o valor inserido;
    • verifica se o palpite corresponde ao número secreto;
    • fornece feedback se o palpite for muito alto ou muito baixo;
    • continua o jogo chamando a si mesma novamente quando necessário;
    • salva o resultado e encerra o jogo quando o número correto é adivinhado;
  • Linhas 49-56: definição da função assíncrona saveGameResult() que salva o resultado do jogo no arquivo game_results.txt e trata possíveis erros;

  • Linha 58: exibição de uma mensagem de boas-vindas ao jogador;

  • Linha 59: início do jogo chamando a função playGame().

Resumo

Este programa cria um jogo de adivinhação de números. O jogador tenta adivinhar um número gerado aleatoriamente dentro de um intervalo especificado. O jogo fornece feedback após cada tentativa, registra o número de tentativas e salva os resultados bem-sucedidos em um arquivo de texto utilizando operações assíncronas de arquivos.

Tudo estava claro?

Como podemos melhorá-lo?

Obrigado pelo seu feedback!

Seção 2. Capítulo 8

Pergunte à IA

expand

Pergunte à IA

ChatGPT

Pergunte o que quiser ou experimente uma das perguntas sugeridas para iniciar nosso bate-papo

Seção 2. Capítulo 8
some-alt