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
});
-
readline: fornece uma interface para ler entradas e escrever saídas no console; -
readline.createInterface({ ... }): cria uma instância da classereadline.Interface. Aceita um objeto com as propriedadesinputeoutput; -
input: process.stdin: define o fluxo de entrada comoprocess.stdin, permitindo que o programa leia a entrada do usuário pelo teclado; -
output: process.stdout: define o fluxo de saída comoprocess.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;
-
Math.random(): gera um número de ponto flutuante aleatório entre0(inclusivo) e1(exclusivo); -
maxNumber - minNumber + 1: calcula o intervalo de números possíveis. Adicionar1garante que tantominNumberquantomaxNumberestejam incluídos no intervalo; -
Math.random() * (maxNumber - minNumber + 1): gera um número aleatório entre0e 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 emminNumberem vez de0.
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;
}
-
!isNaN(guess): verifica seguessé um número válido. A funçãoisNaN()retornafalsepara números válidos, e o operador!inverte paratrue; -
guess >= minNumber: verifica seguessé maior ou igual aminNumber, garantindo que não esteja abaixo do intervalo permitido; -
guess <= maxNumber: verifica seguessé menor ou igual amaxNumber, 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 sertruepara que a expressão inteira seja avaliada comotrue.
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();
}
});
}
-
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 theguess`; -
if (isValidGuess(guess)) { ... }: verifica se o valor inserido é um palpite válido usando a funçãoisValidGuess(); -
attempts++;: incrementa o contadorattemptspara acompanhar quantos palpites o jogador fez; -
const guessNumber = parseInt(guess);: converte a entrada do usuário de string para inteiro usandoparseInt(); -
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 interfacereadlinee encerra o jogo; -
else if (guessNumber < secretNumber) { ... }: informa ao jogador que o número secreto é maior e chamaplayGame()novamente para continuar o jogo; -
else { ... }: informa ao jogador que o número secreto é menor e chamaplayGame()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, chamaplayGame()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.');
}
}
-
async function saveGameResult(result) { ... }: define uma função assíncrona chamadasaveGameResult()que aceita um parâmetroresulte permite o uso da palavra-chaveawaitdentro 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 providedresultfollowed 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 blococatch.
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();
-
Linhas 1-2: importação do módulo interno
readlinee da APIfsdo módulopromisespara operações assíncronas de arquivos; -
Linhas 4-7: criação de uma interface readline chamada
rlpara 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
attemptspara 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 arquivogame_results.txte 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.
Obrigado pelo seu feedback!
Pergunte à IA
Pergunte à IA
Pergunte o que quiser ou experimente uma das perguntas sugeridas para iniciar nosso bate-papo