Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Leer Een Raadspel-Console-App Bouwen | Consoletoepassingen Bouwen met Node.js
Backendontwikkeling met Node.js en Express.js

Een Raadspel-Console-App Bouwen

Veeg om het menu te tonen

In dit hoofdstuk maak je je klaar om je vaardigheden in het bouwen van console-applicaties te verbeteren terwijl we aan de slag gaan met het maken van een spannend Raad het Getal-spel. Dit interactieve spel daagt spelers uit om hun intuïtie te gebruiken door een willekeurig gegenereerd getal binnen een vooraf bepaald bereik te raden. Onderweg ontrafelen we de basisprincipes zoals:

  • Willekeurige getalgeneratie;
  • Invoercontrole;
  • Gebruikersinteractie;
  • Zelfs het opslaan van spelresultaten in een bestand.

Uitdaging

Stel je voor dat je een app verkent die spanning en mysterie belooft. Spelers worden uitgenodigd om een geheimzinnig gekozen getal binnen een vooraf bepaald bereik te raden. De app geeft direct feedback op elke gok en houdt nauwkeurig het aantal pogingen bij.

Dit praktijkvoorbeeld biedt de kans om je vaardigheden in het bouwen van CLI-apps te verfijnen en laat zien hoe je interactieve programma's ontwikkelt.

Resultaat App

Bekijk de magie in actie! Hieronder zie je een GIF die de spannende Raad het Getal-spelapp illustreert die je gaat bouwen:

Een Raadspel Console App Bouwen

Je staat voor twee paden. De eerste optie nodigt je uit om het avontuur zelfstandig aan te gaan, terwijl de tweede een behulpzame gids biedt om je succes te verzekeren. Of je nu moedig zelf aan de slag gaat of de gestructureerde gids volgt, je staat een boeiende ervaring te wachten die resulteert in een functionele en aantrekkelijke console-app.

Masterplan

  • Stap 1: Setup en Initialisaties;
  • Stap 2: Spelparameters Definiëren;
  • Stap 3: Hulpfuncties Definiëren;
  • Stap 4: Spellogica;
  • Stap 5: Spelresultaat Opslaan;
  • Stap 6: Het Spel Starten;
  • Conclusie;
  • Volledige App Code.

Stap 1: Setup en Initialisaties

Bereid het canvas voor door een nieuwe map en een bestand genaamd app.js aan te maken. In dit bestand halen we de benodigde modules op:

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

Maak een Readline-interface aan:

const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout
});
Codebeschrijving
expand arrow
  • readline: biedt een interface voor het lezen van invoer en het schrijven van uitvoer naar de console;

  • readline.createInterface({ ... }): maakt een instantie van de readline.Interface klasse aan. Accepteert een object met de eigenschappen input en output;

  • input: process.stdin: stelt de invoerstroom in op process.stdin, waardoor het programma gebruikersinvoer van het toetsenbord kan lezen;

  • output: process.stdout: stelt de uitvoerstroom in op process.stdout, waardoor het programma tekst in de console kan weergeven.

Uitleg: We importeren de benodigde modules: readline voor gebruikersinteractie en fs.promises voor bestandsbewerkingen. Vervolgens maken we een Readline-interface met de naam rl aan om invoer en uitvoer te verwerken.

Stap 2: Spelparameters definiëren

Stel het minimum- en maximumgetal in:

const minNumber = 1;
const maxNumber = 100;

Genereer het geheime nummer:

const secretNumber =
  Math.floor(Math.random() * (maxNumber - minNumber + 1)) + minNumber;
Codebeschrijving
expand arrow
  • Math.random(): genereert een willekeurig drijvend-kommagetal tussen 0 (inclusief) en 1 (exclusief);

  • maxNumber - minNumber + 1: berekent het bereik van mogelijke getallen. Door 1 toe te voegen worden zowel minNumber als maxNumber in het bereik opgenomen;

  • Math.random() * (maxNumber - minNumber + 1): genereert een willekeurig getal tussen 0 en het berekende bereik;

  • Math.floor(...): rondt het gegenereerde drijvend-kommagetal naar beneden af tot het dichtstbijzijnde gehele getal, zodat het resultaat een geheel getal binnen het gewenste bereik is;

  • ... + minNumber: verschuift het gegenereerde getal zodat het bereik begint bij minNumber in plaats van 0.

Initialiseer de pogingen teller:

let attempts = 0;

Uitleg: Het bereik van getallen (minNumber en maxNumber) wordt gedefinieerd waarbinnen het geheime getal wordt gegenereerd. Het geheime getal wordt willekeurig gegenereerd met Math.random() en toegewezen aan secretNumber. De variabele attempts wordt geïnitialiseerd om het aantal pogingen van de gebruiker bij te houden.

Stap 3: Hulpfuncties definiëren

Voorzien van een hulpfunctie voor foutloze validatie:

function isValidGuess(guess) {
  return !isNaN(guess)
    && guess >= minNumber
    && guess <= maxNumber;
}
Codebeschrijving
expand arrow
  • !isNaN(guess): controleert of guess een geldig getal is. De functie isNaN() retourneert false voor geldige getallen, en de !-operator keert dit om naar true;

  • guess >= minNumber: verifieert dat guess groter dan of gelijk aan minNumber is, zodat het niet onder het toegestane bereik valt;

  • guess <= maxNumber: verifieert dat guess kleiner dan of gelijk aan maxNumber is, zodat het niet boven het toegestane bereik valt;

  • &&: combineert alle voorwaarden met de logische AND-operator. Elke voorwaarde moet true zijn zodat de gehele expressie als true wordt geëvalueerd.

Uitleg: De functie isValidGuess controleert of de gok van de gebruiker een geldig getal is binnen het opgegeven bereik (minNumber tot maxNumber).

Stap 4: Spel Logica

De kernmechanica van het spel via de functie 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();
    }
  });
}
Codebeschrijving
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` aan de callbackfunctie doorgegeven;

  • if (isValidGuess(guess)) { ... }: controleert of de ingevoerde waarde een geldige gok is met behulp van de functie isValidGuess();

  • attempts++;: verhoogt de teller attempts om bij te houden hoeveel pogingen de speler heeft gedaan;

  • const guessNumber = parseInt(guess);: zet de invoer van de gebruiker om van een string naar een geheel getal met parseInt();

  • if (guessNumber === secretNumber) { ... }: controleert of de gok van de speler overeenkomt met het geheime getal. Als dat zo is, toont het spel een succesbericht, slaat het resultaat op, sluit de readline-interface en beëindigt het spel;

  • else if (guessNumber < secretNumber) { ... }: geeft aan dat het geheime getal hoger is en roept opnieuw playGame() aan om verder te gaan;

  • else { ... }: geeft aan dat het geheime getal lager is en roept opnieuw playGame() aan om verder te gaan;

  • else { ... } (na de validatiecontrole): behandelt ongeldige invoer door de speler te vragen een geldig getal binnen het toegestane bereik in te voeren en roept vervolgens opnieuw playGame() aan.

Uitleg: De functie playGame vormt de kern van de spel-lus. Deze gebruikt rl.question om de gebruiker om een gok te vragen. Als de gok geldig is, controleert de functie of de gok overeenkomt met het geheime nummer. Zo niet, dan geeft het feedback aan de gebruiker en gaat de spel-lus recursief verder.

Stap 5: Spelresultaat opslaan

Implementeer de logica om de spelprestaties van de gebruiker op te slaan in het bestand 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.');
  }
}
Codebeschrijving
expand arrow
  • async function saveGameResult(result) { ... }: definieert een asynchrone functie genaamd saveGameResult() die een parameter result accepteert en het gebruik van het await-sleutelwoord binnen de functie mogelijk maakt;

  • try { ... } catch (err) { ... }: behandelt mogelijke fouten die kunnen optreden tijdens de asynchrone bestandsbewerking;

  • await fs.appendFile('game_results.txt', \${result}\n`);: appends the provided resultfollowed by a newline character to thegame_results.txtfile. Theawait` pauzeert de uitvoering totdat de bestandsbewerking succesvol is afgerond;

  • console.log('Game result saved.');: toont een bevestigingsbericht wanneer het spelresultaat succesvol naar het bestand is geschreven;

  • console.log('Failed to save game result.');: toont een foutmelding als de bestandsbewerking mislukt en een uitzondering wordt opgevangen door het catch-blok.

Uitleg: De functie saveGameResult gebruikt fs.promises om het spelresultaat toe te voegen aan een bestand genaamd game_results.txt. Geeft feedback over het succes of falen van het opslaan van het resultaat.

Stap 6: Start het spel

Maak het welkomstbericht en start het spel:

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

Uitleg: We tonen een welkomstbericht en starten de spel-lus door de functie playGame aan te roepen.

Volledige app-code

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();
Codebeschrijving
expand arrow
  • Regels 1-2: importeren van de ingebouwde module readline en de fs API van de promises module voor asynchrone bestandsbewerkingen;

  • Regels 4-7: aanmaken van een readline-interface genaamd rl voor het lezen van gebruikersinvoer en het tonen van uitvoer in de console;

  • Regels 9-10: definiëren van de minimale en maximale waarden voor het te raden bereik;

  • Regels 12-13: genereren van een willekeurig geheim getal binnen het opgegeven bereik met behulp van Math.random();

  • Regel 14: initialiseren van de teller attempts om het aantal pogingen van de speler bij te houden;

  • Regels 16-18: definiëren van de functie isValidGuess() om te controleren of de ingevoerde waarde een getal is binnen het toegestane bereik;

  • Regels 20-47: definiëren van de recursieve functie playGame() die:

    • de speler vraagt om een gok in te voeren;
    • de ingevoerde waarde valideert;
    • controleert of de gok overeenkomt met het geheime getal;
    • feedback geeft als de gok te hoog of te laag is;
    • het spel voortzet door zichzelf opnieuw aan te roepen indien nodig;
    • het resultaat opslaat en het spel beëindigt wanneer het juiste getal is geraden;
  • Regels 49-56: definiëren van de asynchrone functie saveGameResult() die het spelresultaat opslaat in het bestand game_results.txt en mogelijke fouten afhandelt;

  • Regel 58: tonen van een welkomstbericht aan de speler;

  • Regel 59: starten van het spel door de functie playGame() aan te roepen.

Samenvatting

Dit programma maakt een getallenraadspel. De speler probeert een willekeurig gegenereerd getal binnen een opgegeven bereik te raden. Het spel geeft na elke gok feedback, houdt het aantal pogingen bij en slaat succesvolle resultaten op in een tekstbestand via asynchrone bestandsbewerkingen.

Was alles duidelijk?

Hoe kunnen we het verbeteren?

Bedankt voor je feedback!

Sectie 2. Hoofdstuk 8

Vraag AI

expand

Vraag AI

ChatGPT

Vraag wat u wilt of probeer een van de voorgestelde vragen om onze chat te starten.

Sectie 2. Hoofdstuk 8
some-alt