⌛⌛ Sanan arvaus

Tiedostot saat käyttöösi nyhtämällä ne versionhallinnasta. Ne sijaitsevat repositoriossa student_template_project. Koodit nyhtääksesi student_template_project tulee laittaa paikalliseen repositorioosi remoteksi. Tässä harjoituksessa tarvitsemasi koodit ovat hakemistossa Round5/wordgame. Huomaa, sinulla ei ole oikeuksia päivittää repositoriota. Aseta vastauksesi tiedostoihin WordGame.java ja GameStateException.java hakemistossa Round5/wordgame.

Johdanto

Eräs klassinen sanan arvauspeli etenee alla kuvatulla tavalla. Pelissä on osapuolina pelinjohtaja (voi olla esim. tietokone) sekä pelaaja.

  1. Pelinjohtaja valitsee jonkin sanan näyttämättä sitä pelaajalle, ja lisäksi on määritetty suurin sallittu virheiden (eli virheellisten arvausten) määrä. Tämän jälkeen askelia 2 ja 3 toistetaan vuorotellen niin kauan, kunnes joko pelaaja arvaa koko sanan, tai pelaajan tekemien virheiden määrä ylittää suurimman sallitun määrän.

  2. Pelinjohtaja näyttää pelaajalle valitsemansa sanan nykytilanteen niin, että jokaisen toistaiseksi oikein arvaamattoman kirjaimen kohdalla on merkki ‘_’.

  3. Pelaajan vuoro. Pelaaja arvaa joko yksittäisen kirjaimen tai koko sanan.

    1. Jos pelaaja päättää arvata koko sanan, pitää arvauksen mennä täsmälleen oikein.

      1. Ellei pelaajan arvaus ole täsmälleen oikein, tulkitaan arvaus virheeksi. Tällöin virheiden määrää kasvatetaan yhdellä eikä sanasta paljasteta mitään lisätietoa (ellei peli pääty; kts. alla).

      2. Jos arvattu sana oli täsmälleen oikein, peli päättyy pelaajan voittoon.

    2. Jos pelaaja arvaa yksittäisen kirjaimen, niin:

      1. Jos kirjain esiintyy pelinjohtajan sanassa, pelinjohtaja paljastaa kaikki kyseisen kirjaimen esiintymät sanasta. Jos sana tulee oikein arvatun kirjaimen myötä kokonaan arvatuksi, peli päättyy pelaajan voittoon.

      2. Jos kirjainta ei esiinny sanassa tai kirjain oli jo aiemmin arvattu, on kyseessä virhe. Tällöin virheiden määrää kasvatetaan yhdellä.

    3. Jos pelaajan virheiden määrä ylittää suurimman sallitun määrän, loppuu peli pelaajan häviöön. Samalla pelinjohtaja paljastaa valitsemansa sanan kokonaisuudessaan pelaajalle.

Varsinainen tehtävänanto

Toteuta sanan arvauspeli luokkana WordGame, jolla on seuraavat julkiset ominaisuudet:

  • Sisäinen staattinen luokka WordGameState, jonka olioon voi tallettaa pelin tilanteen: sanan, tehtyjen virheiden lukumäärän, suurimman sallitun virheiden lukumäärän sekä sanan toistaiseksi tuntemattomien kirjainten (paljastamattomien merkkien ‘_’) lukumäärän.

    • Tilaan talletetaan sana sellaisena, kuin se näytettäisiin pelaajalle: arvaamattomat kirjaimet esitetään merkeillä ‘_’.

    • Ei yhtään julkista rakenninta!

    • Julkiset funktiot String getWord(), int getMistakes(), int getMistakeLimit() ja int getMissingChars(), jotka palauttavat asianomaiset arvot.

  • Rakennin WordGame(String wordFilename), joka lukee pelissä käytettävissä olevat sanat parametrin ilmoittamasta tiedostosta.

    • Tiedoston oletetaan sisältävän yhden sanan per rivi ilman ylimääräistä tyhjää tilaa.

    • Rakentimen tulee tallettaa sanat WordGame-olioon samassa järjestyksessä kuin ne ovat tiedostossa (esim. ArrayList<String> lienee sopiva tietorakenne).

    • Alempana viitataan sanan indeksiin. Ensimmäisen luetun sanan indeksi on 0, toiseksi luetun sanan indeksi on 1, jne. Lisäksi alempana oletetaan, että sanojen kokonaislukumäärä on N.

  • Jäsenfunktio void initGame(int wordIndex, int mistakeLimit), joka alustaa uuden pelin käyttäen arvattavana sanana rakentimen alustaman sanataulukon indeksin wordIndex % N omaavaa sanaa ja sallien korkeintaan mistakeLimit virhettä. Uusi peli alustetaan välittömästi riippumatta siitä, oliko aiempi peli mahdollisesti vielä käynnissä.

  • Jäsenfunktio boolean isGameActive(), joka palauttaa tiedon, onko peli parhaillaan käynnissä.

  • Jäsenfunktio WordGameState getGameState(), joka palauttaa pelin tämänhetkisen tilanteen kuvaavan WordGameState-olion.

    • Heittää poikkeuksen GameStateException("There is currently no active word game!"), ellei peli ole parhaillaan käynnissä.

  • Jäsenfunktio WordGameState guess(char c), joka päivittää pelin tilan vastaamaan kirjaimen c arvausta ja palauttaa päivitetyn tilan kuvaavan WordGameState-olion.

    • Heittää poikkeuksen GameStateException("There is currently no active word game!"), ellei peli ole parhaillaan käynnissä.

  • Jäsenfunktio WordGameState guess(String word), joka päivittää pelin tilan vastaamaan sanan word arvausta ja palauttaa päivitetyn tilan kuvaavan WordGameState-olion.

    • Heittää poikkeuksen GameStateException("There is currently no active word game!"), ellei peli ole parhaillaan käynnissä.

Edellä viitattiin tyyppiä GameStateException oleviin poikkeuksiin. Tällaista poikkeusluokkaa ei ole valmiina vaan sekin pitää toteuttaa erikseen. Toteuta siis edellisten lisäksi luokka GameStateException, joka perii Javan luokkakirjaston luokan Exception ja jonka ainoa jäsen on julkinen muotoa GameStateException(String msg) oleva rakennin, joka ainoastaan välittää parametrin “msg” yliluokan rakentimelle. Kyseessä on siis varsin yksinkertainen luokka.

Alla tarjottu testimateriaali selventänee luokalta WordGame odotettua toimintaa.

Toteutuksen testaus

Voit testata luokkiasi tiedostossa WordGameTest.java annetun valmiin testiohjelman, tiedostoissa words.txt, input1.txt ja input2.txt annettujen testidatojen, ja tiedostoissa output1.txt ja output2.txt annettujen esimerkkitulosteiden avulla. Aseta nämä tiedostot sekä omat luokkatoteutuksesi samaan hakemistoon, käännä ohjelma esim. tapaan javac *.java, ja suorita ensimmäinen testi tapaan java WordGameTest words.txt input1.txt ja toinen testi tapaan java WordGameTest words.txt input2.txt. Suoritusten pitäisi tuottaa tiedostoissa output1.txt ja output2.txt kuvatut tulosteet. Huomaa, että kaikki tulostukset tapahtuvat testiohjelmassa. Luokan WordGame funktiot eivät tulosta mitään.

A+ esittää tässä kohdassa tehtävän palautuslomakkeen.