Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Oppiskele Arvauspeli-Konsolisovelluksen Rakentaminen | Konsolisovellusten Rakentaminen Node.js:llä
Backend-kehitys Node.js:llä ja Express.js:llä

Arvauspeli-Konsolisovelluksen Rakentaminen

Pyyhkäise näyttääksesi valikon

Tässä luvussa pääset kehittämään konsolisovellustaitojasi luomalla jännittävän Arvaa luku -pelin. Tämä interaktiivinen peli haastaa pelaajat käyttämään intuitiotaan arvaamalla satunnaisesti valitun luvun ennalta määritellyltä alueelta. Samalla tutustutaan keskeisiin käsitteisiin, kuten

  • Satunnaislukujen generointi;
  • Syötteen validointi;
  • Käyttäjän vuorovaikutus;
  • Pelitulosten tallentaminen tiedostoon.

Haaste

Kuvittele sovellus, joka lupaa jännitystä ja arvoituksellisuutta. Pelaajat kutsutaan arvaamaan salaperäisesti valittu luku ennalta määritellyltä alueelta. Sovellus antaa välitöntä palautetta jokaisesta arvauksesta ja pitää tarkkaa kirjaa yrityksistä.

Tämä käytännön esimerkki tarjoaa mahdollisuuden hioa taitoja CLI-sovellusten rakentamisessa ja esittelee interaktiivisten ohjelmien toteutuksen taidon.

Lopputulos

Katso, miten sovellus toimii! Alla oleva GIF havainnollistaa jännittävää Arvaa luku -peliä, jonka tulet rakentamaan:

Arvauspeli-konsolisovelluksen rakentaminen

Edessäsi on kaksi polkua. Ensimmäinen vaihtoehto kutsuu sinut aloittamaan matkan ilman apua, kun taas toinen tarjoaa hyödyllisen oppaan onnistumisesi varmistamiseksi. Valitsitpa rohkean hyppäyksen tai rakenteellisen ohjeen seuraamisen, edessäsi on kiehtova kokemus, jonka lopputuloksena on toimiva ja mukaansatempaava konsolisovellus.

Pääsuunnitelma

  • Vaihe 1: Alustus ja valmistelut;
  • Vaihe 2: Pelin parametrien määrittely;
  • Vaihe 3: Apufunktioiden määrittely;
  • Vaihe 4: Pelilogiikka;
  • Vaihe 5: Pelituloksen tallennus;
  • Vaihe 6: Pelin käynnistys;
  • Yhteenveto;
  • Koko sovelluksen koodi.

Vaihe 1: Alustus ja valmistelut

Valmistele pohja luomalla uusi hakemisto ja tiedosto nimeltä app.js. Tässä tiedostossa otetaan käyttöön tarvittavat moduulit:

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

Luo Readline-rajapinta:

const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout
});
Koodin kuvaus
expand arrow
  • readline: tarjoaa käyttöliittymän syötteen lukemiseen ja tulosteen kirjoittamiseen konsoliin;

  • readline.createInterface({ ... }): luo readline.Interface-luokan instanssin. Ottaa vastaan olion, jossa on input- ja output-ominaisuudet;

  • input: process.stdin: asettaa syötevirraksi process.stdin, jolloin ohjelma voi lukea käyttäjän syötteen näppäimistöltä;

  • output: process.stdout: asettaa tulostevirraksi process.stdout, jolloin ohjelma voi näyttää tekstiä konsolissa.

Selitys: Tuodaan tarvittavat moduulit: readline käyttäjän kanssa vuorovaikutukseen ja fs.promises tiedostojen käsittelyyn. Luodaan Readline-rajapinta nimeltä rl syötteen ja tulosteen hallintaan.

Vaihe 2: Pelin parametrien määrittely

Aseta pienin ja suurin numero:

const minNumber = 1;
const maxNumber = 100;

Salaisen numeron generointi:

const secretNumber =
  Math.floor(Math.random() * (maxNumber - minNumber + 1)) + minNumber;
Koodin kuvaus
expand arrow
  • Math.random(): generoi satunnaisen liukuluvun väliltä 0 (sisällytetty) ja 1 (ei sisällytetty);

  • maxNumber - minNumber + 1: laskee mahdollisten lukujen vaihteluvälin. Lisäämällä 1 varmistetaan, että sekä minNumber että maxNumber sisältyvät vaihteluväliin;

  • Math.random() * (maxNumber - minNumber + 1): generoi satunnaisen luvun väliltä 0 ja laskettu vaihteluväli;

  • Math.floor(...): pyöristää generoidun liukuluvun alaspäin lähimpään kokonaislukuun, jolloin tulos on halutulla vaihteluvälillä oleva kokonaisluku;

  • ... + minNumber: siirtää generoidun luvun niin, että vaihteluväli alkaa arvosta minNumber eikä 0.

Yritysten laskurin alustaminen:

let attempts = 0;

Selitys: Määritellään lukujen vaihteluväli (minNumber ja maxNumber), jonka sisällä salainen numero arvotaan. Salainen numero luodaan satunnaisesti käyttäen Math.random()-funktiota ja tallennetaan muuttujaan secretNumber. Muuttuja attempts alustetaan käyttäjän yritysten seuraamiseksi.

Vaihe 3: Apufunktioiden määrittely

Varustaudu apufunktiolla virheettömään validointiin:

function isValidGuess(guess) {
  return !isNaN(guess)
    && guess >= minNumber
    && guess <= maxNumber;
}
Koodin kuvaus
expand arrow
  • !isNaN(guess): tarkistaa, onko guess kelvollinen numero. isNaN()-funktio palauttaa arvon false kelvollisille numeroille, ja !-operaattori kääntää sen arvoksi true;

  • guess >= minNumber: varmistaa, että guess on suurempi tai yhtä suuri kuin minNumber, jolloin arvaus ei ole sallitun alueen alapuolella;

  • guess <= maxNumber: varmistaa, että guess on pienempi tai yhtä suuri kuin maxNumber, jolloin arvaus ei ole sallitun alueen yläpuolella;

  • &&: yhdistää kaikki ehdot loogisella JA-operaattorilla. Kaikkien ehtojen tulee olla true, jotta koko lauseke palauttaa arvon true.

Selitys: isValidGuess-funktio tarkistaa, onko käyttäjän arvaus kelvollinen numero määritellyllä välillä (minNumbermaxNumber).

Vaihe 4: Pelilogiikka

Pelin ydintoiminnallisuus playGame-funktion kautta:

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();
    }
  });
}
Koodin kuvaus
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`-argumenttina;

  • if (isValidGuess(guess)) { ... }: tarkistaa, onko syötetty arvo kelvollinen arvaus käyttämällä isValidGuess()-funktiota;

  • attempts++;: kasvattaa attempts-laskuria, joka seuraa pelaajan arvausten määrää;

  • const guessNumber = parseInt(guess);: muuntaa käyttäjän syötteen merkkijonosta kokonaisluvuksi parseInt()-funktion avulla;

  • if (guessNumber === secretNumber) { ... }: tarkistaa, vastaako pelaajan arvaus salaisuutta numeroa. Jos vastaus on oikea, peli näyttää onnistumisviestin, tallentaa tuloksen, sulkee readline-rajapinnan ja lopettaa pelin;

  • else if (guessNumber < secretNumber) { ... }: ilmoittaa pelaajalle, että salainen numero on suurempi, ja kutsuu playGame()-funktiota uudelleen pelin jatkamiseksi;

  • else { ... }: ilmoittaa pelaajalle, että salainen numero on pienempi, ja kutsuu playGame()-funktiota uudelleen pelin jatkamiseksi;

  • else { ... } (tarkistuksen jälkeen): käsittelee virheellisen syötteen pyytämällä pelaajaa syöttämään kelvollisen numeron sallitulla välillä ja kutsuu sitten playGame()-funktiota uudelleen.

Selitys: playGame-funktio muodostaa pelin ydinsilmukan. Se käyttää rl.question-metodia pyytääkseen käyttäjältä arvausta. Jos arvaus on kelvollinen, funktio tarkistaa, vastaako arvaus salaisuusnumeroa. Muussa tapauksessa se antaa palautetta käyttäjälle ja jatkaa pelisilmukkaa rekursiivisesti.

Vaihe 5: Pelituloksen tallentaminen

Toteuta logiikka, jolla käyttäjän pelisaavutukset tallennetaan tiedostoon 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.');
  }
}
Koodin kuvaus
expand arrow
  • async function saveGameResult(result) { ... }: määrittelee asynkronisen funktion nimeltä saveGameResult(), joka ottaa vastaan parametrin result ja mahdollistaa await-avainsanan käytön funktion sisällä;

  • try { ... } catch (err) { ... }: käsittelee mahdolliset virheet, joita voi esiintyä asynkronisen tiedosto-operaation aikana;

  • await fs.appendFile('game_results.txt', \${result}\n`);: appends the provided resultfollowed by a newline character to thegame_results.txtfile. Theawait`-avainsana pysäyttää suorituksen, kunnes tiedosto-operaatio on onnistuneesti suoritettu;

  • console.log('Game result saved.');: näyttää vahvistusviestin, kun pelitulos on onnistuneesti kirjoitettu tiedostoon;

  • console.log('Failed to save game result.');: näyttää virheilmoituksen, jos tiedosto-operaatio epäonnistuu ja poikkeus jää kiinni catch-lohkoon.

Selitys: saveGameResult-funktio käyttää fs.promises-kirjastoa lisätäkseen pelituloksen tiedostoon nimeltä game_results.txt. Funktio antaa palautetta siitä, onnistuiko tuloksen tallennus vai ei.

Vaihe 6: Pelin käynnistäminen

Luo tervetuloviesti ja käynnistä peli:

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

Selitys: Näytetään tervetuloviesti ja käynnistetään pelisilmukka kutsumalla playGame-funktiota.

Sovelluksen koko koodi

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();
Koodin kuvaus
expand arrow
  • Rivit 1-2: tuodaan sisäänrakennettu readline-moduuli sekä fs-moduulin promises-rajapinta asynkronisia tiedostotoimintoja varten;

  • Rivit 4-7: luodaan readline-rajapinta nimeltä rl käyttäjän syötteen lukemista ja tulosteen näyttämistä varten konsolissa;

  • Rivit 9-10: määritellään arvattavan luvun pienin ja suurin arvo;

  • Rivit 12-13: arvotaan satunnainen salainen luku määritellyltä väliltä käyttäen Math.random()-funktiota;

  • Rivi 14: alustetaan attempts-laskuri seuraamaan pelaajan arvausten määrää;

  • Rivit 16-18: määritellään isValidGuess()-funktio, joka tarkistaa, että syötetty arvo on sallituilla rajoilla oleva numero;

  • Rivit 20-47: määritellään rekursiivinen playGame()-funktio, joka:

    • pyytää pelaajaa arvaamaan luvun;
    • tarkistaa syötetyn arvon;
    • tarkistaa, vastaako arvaus salaista lukua;
    • antaa palautetta, jos arvaus on liian suuri tai pieni;
    • jatkaa peliä kutsumalla itseään uudelleen tarvittaessa;
    • tallentaa tuloksen ja lopettaa pelin, kun oikea luku on arvattu;
  • Rivit 49-56: määritellään asynkroninen saveGameResult()-funktio, joka tallentaa pelin tuloksen tiedostoon game_results.txt ja käsittelee mahdolliset virheet;

  • Rivi 58: näyttää tervetuloviestin pelaajalle;

  • Rivi 59: käynnistää pelin kutsumalla playGame()-funktiota.

Yhteenveto

Tämä ohjelma toteuttaa numeronarvauspelin. Pelaaja yrittää arvata satunnaisesti arvotun luvun määritellyltä väliltä. Peli antaa palautetta jokaisen arvauksen jälkeen, seuraa arvausten määrää ja tallentaa onnistuneet tulokset tekstitiedostoon asynkronisesti.

Oliko kaikki selvää?

Miten voimme parantaa sitä?

Kiitos palautteestasi!

Osio 2. Luku 8

Kysy tekoälyä

expand

Kysy tekoälyä

ChatGPT

Kysy mitä tahansa tai kokeile jotakin ehdotetuista kysymyksistä aloittaaksesi keskustelumme

Osio 2. Luku 8
some-alt