(P) Muistipeli¶
Tavoite: Harjoittelen vektorin käyttöä, olio-ohjelmointia sekä Gitin käyttöä. Lisäksi opin noudattamaan ohjelmoinnin tyylisääntöjä.
Ohjeita:
Hae ohjelmakoodipohja: templates/04/pairs
-> student/04/pairs
.
Ohjelmakoodipohjassa on valmiina tiedostot main.cpp
ja pairs.pro
sekä luokat Card
(card.hh
, card.cpp
) ja Player
(player.hh
, player.cpp
).
Tehtävänä on täydentää koodia niin, että lopputuloksena on muistipeli.
Myös koodipohjien olemassa olevaa koodia saa muuttaa.
Attention
Ennen kuin aloitat, lue huolellisesti koko tehtävänanto. Huomaa erityisesti vaaditut commitit.
Attention
Tämän projektin saa (mutta ei ole pakko) tehdä parityönä. Paripalautusta varten tulee muodostaa ryhmä palauttamalla lomake, joka löytyy vasemman puolen valikosta otsikolla “Luo uusi ryhmä”. Lisäksi tämän sivun alaosan palautuslaatikkossa on näkyvissä kaksi vaihtoehtoa: “Palauta yksin” / “Palauta ryhmässä”. Ole tarkkana, että valitset oikean vaihtoehdon, koska valintaa ei voi myöhemmin perua. Palautuslaatikkoon tulee vain jommankumman jäsenen Git-repositorion osoite. Kirjoittakaa kooditiedoston kommentteihin molempien nimet ym. muut tiedot.
Ryhmää voi etsiä Kooditorion Discord-linkin kautta (ks. Aikataulu & linkit).
Alkukommentti ja palautteen kieli¶
Tämän osion kohdassa Arviointi vaaditaan kooditiedoston alkukommentti. Sillä tarkoitetaan esimerkiksi seuraavan tyylistä kommenttia:
/* Muistipeli
*
* Kuvaus:
* Ohjelma toteuttaa muistipelin. Pelissä on vaihteleva määrä kortteja ja
* pelaajia. Pelin alussa käyttäjältä kysytään myös siemenluku, koska kortit
* arvotaan satunnaisesti pelilaudalle.
* Joka kierroksella vuorossa oleva pelaaja antaa kahden kortin
* koordinaatit (yhteensä neljä lukua), minkä jälkeen kyseiset kortit
* käännetään näkyviin ja kerrotaan, ovatko ne parit vai ei.
* Jos pelaaja sai parit, kortit poistetaan pelilaudalta, pelaajan
* pistesaldoa kasvatetaan, ja hän saa uuden vuoron. Jos pelaaja ei saanut
* pareja, kortit käännetään takaisin piiloon, ja vuoro siirtyy seuraavalle
* pelaajalle.
* Ohjelma tarkistaa pelaajan antamat koordinaatit. Koordinaattien pitää
* olla sellaiset, että niiden määrä kortti löytyy pelilaudalta.
* Muutosten jälkeen pelilauta tulostetaan aina uudelleen. Kortit kuvataan
* kirjaimina alkaen A:sta niin pitkälle, kuin kortteja on. Kun pelilauta
* tulostetaan, näkyvissä oleva kortti kuvataan kyseisellä kirjaimella.
* Piiloon käännettyä korttia kuvaa risuaita (#), ja laudalta poistetun
* kortin kohdalle tulostetaan piste.
* Peli päättyy, kun kaikki parit on löydetty, ja pelilauta on tyhjä.
* Tällöin kerrotaan, kuka tai ketkä voittivat eli saivat eniten pareja.
*
* Ohjelman kirjoittaja ( Täytä omilla tiedoillasi )
* Nimi: Teemu Teekkari
* Opiskelijanumero: 123456
* Käyttäjätunnus: teekkart ( Git-repositorion hakemistonimi. )
* E-Mail: teemu.teekkari@tuni.fi
*
* Huomioita ohjelmasta ja sen toteutuksesta:
*
* */
Lisää siis yllä olevan tapainen kommentti tiedoston main.cpp
ihan alkuun.
Koska kooditiedostoja on useita,
opiskelijakohtaiset tiedot pitää olla niissä kaikissa.
Kuvausosuutta ei tarvitse toistaa jokaisessa tiedostossa, riittää, että se
on pääohjelmatiedostossa.
Voit kirjoittaa kommentin myös englanniksi (ks. englannikielinen tehtävänanto), mutta kirjoita kaikki kommentit samalla kielellä. Pohjakoodi on kommentoitu sekä suomeksi että englanniksi, voit poistaa tarpeettomat kommentit. Muista vaihtaa yllä olevaan kommenttiin omat henkilökohtaiset tietosi.
Palautteen kieli valitaan palautuslaatikossa (tämän sivun lopussa). Palautteen kielenä on oletuksena suomi, mutta voit vaihtaa sen, jos haluat assistenttien antaman palautteen englanniksi. Kielivalinta määräytyy sen perusteella, minkä kielivalinnan olet tehnyt viimeisimmän palautuksen palautuslaatikossa.
Jos teette parityötä, muistakaa lisätä molempien henkilökohtaiset tiedot.
Pelin säännöt¶
Tarkoituksena on kerätä mahdollisimman paljon pareja. Jos vuorossa oleva pelaaja saa parit, kortit poistetaan pelilaudalta, pelaajan pistesaldoa kasvatetaan, ja hän saa uuden vuoron. Jos pelaaja ei saanut pareja, kortit käännetään takaisin piiloon, ja vuoro siirtyy seuraavalle pelaajalle.
Peli päättyy, kun kaikki parit ovat löytyneet. Voittaja on se, joka on saanut kerättyä eniten pareja.
Muistipeli vs vesipisarapeli¶
Tällä kierroksella kuvataan vesipisarapeli,
jossa on myös käytetty vektoreita, jonka alkiot ovat vektoreita.
Edelleen sisemmän vektorin alkiot ovat ruutuja (Square
).
Muistipeli-projektissa on samanlainen rakenne, mutta sisemmän vektorin alkiot
ovat kortteja (Card
).
Vesipisarapelissä jokaisella ruudulla on osoitin pelilautaan,
koska jokaisen ruudun pitää tuntea viereiset ruudut.
Muistipelissä tällaiseen ei ole tarvetta, koska muistipelin korttien
ei tarvitse tuntea viereisiä kortteja.
Tässä tehtävässä et välttämättä tarvitse osoittimia lainkaan.
Tarvittaessa voit käyttää pelaajaosoitinta samaan tapaan kuin edellisen
kierroksen Mölkky-pelitehtävässä,
jossa osoitin in_turn
osoitti vuorossa olevaan pelaajaan.
Muistipelissä on mahdollista olla useita pelaajia, ja aina joku heistä
on vuorossa.
Koska pelaajia voi olla mikä määrä tahansa, ne kannattaa tallettaa vektoriin.
Voit siis käyttää vektorin indeksiä kertomaan vuorossa olevan pelaajan,
sen sijaan että käyttäisit osoitinta.
Vesipisarapelissä olisi ollut luontevaa olla pisaraolioita eikä ruutuolioita.
Ongelmanana oli kuitenkin se, että peliruudukossa oli mahdollista olla
myös tyhjiä kohtia.
Jos oliot olisivat olleet pisaroita, miten olisi voinut kuvata tyhjän kohdan?
Muistipelissä on oikeastaan sama ongelma.
Pelilaudalle jää tyhjä kohta, kun pelaaja on löytänyt parit.
Pelilaudan kannalta olisi luontevampaa, että oliot olisivat kortin paikkoja
eikä kortteja.
Kortit kuitenkin siirtyvät pelilaudalta pelaajille, joten pelaajan kannalta
on luontevampaa pitää oliot kortteina.
Tästä syystä korttiluokassa (Card
) on myös vaihtoehto “tyhjälle” kortille,
mikä oikeastaan tarkoittaa tyhjää kohtaa pelilaudalla.
Tehtävänanto¶
Tehtävänä on toteuttaa ohjelma, joka toimii kuten yllä kuvattu muistipeli.
Ohjelman alussa käyttäjältä kysytään:
- korttien lukumäärä
- siemenluku
- pelaajien lukumäärä.
Korttien lukumäärän perusteella kortit ladotaan pelilaudalle mahdollisimman paljon neliötä muistuttavaksi suorakulmioksi (vrt. 2-kierroksen tehtävä Läheisimmät tekijät). Siemenluvun perusteella arvotaan pelilaudan sijainteja: ensimmäiseksi arvottuun sijaintiin sijoitetaan kortti A, toiseksi arvottuun sijoitetaan toinen A, kolmanneksi arvottuun sijoitetaan B, neljänneksi arvottuun toinen B jne. Kun pelaajien lukumäärä on annettu, ohjelma lukee tämän lukumäärän verran merkkijonoja, jotka tallennetaan pelaajien nimiksi. Samannimiset pelaajat sallitaan, mutta tällöin pelin kulkua on vaikeampi seurata.
Koodipohja sisältää valmiina toiminnot pelilaudan alustamiseen ja tulostamiseen. Toisin sanoen sinun ei tarvitse välittää korttien arpomisesta, latomisesta tai pelilaudan piirtämisestä.
Sinun tehtäväksesi jää toteuttaa pelin varsinainen kulku.
Tähän sisältyy myös pelaajien lukumäärän ja heidän nimiensä kysyminen.
Näiden tietojen perusteella luodaan tarvittava määrä pelaajaolioita, ja
talletetaan ne vektoriin.
Pääasiassa koodia kirjoitetaan tiedostoon main.cpp
, mutta joitakin
pieniä osia pitää kirjoittaa annettuihin luokkiin (Card
ja Player
).
Vuorossa olevalta pelaajalta kysytään, mitkä kortit hän haluaa kääntää. Tällöin käyttäjä luettelee kahden kortin x- ja y-koordinaatit eli yhteensä neljä lukua.
Jos käyttäjän antamat koordinaatit ovat laillisia, kortit käännetään. Tämä tapahtuu piirtämällä pelilauta uudelleen. Jos koordinaatit eivät ole laillisia, ohjelma ilmoittaa virheellisestä syötteestä. Tarkemmat virheilmoitukset näkyvät esimerkkiajoissa.
Pelilauta kuvataan ohjelmassa ruudukkona eli vektorina, jonka alkiot ovat vektoreita. Ohjelmassa käytetään graafisen käyttöliittymän sijaan ASCII-grafiikkaa, jolloin pelilauta voi näyttää esimerkiksi tältä:
=================
| | 1 2 3 4 5 |
-----------------
| 1 | C # # # # |
| 2 | I # # # . |
| 3 | . # # # # |
| 4 | # # # # # |
=================
Yllä oleva pelilauta on tilanteesta:
- Korttien määrä on 20.
- Kohdista (5, 2) ja (1, 3) on löytynyt parit, ja nämä kortit on poistettu: niiden kohdalla on piste.
- Kohdissa (1, 1) ja (1, 2) olevat kortit on käännetty näkyviin: niiden kirjaimet on tulostettu näkyviin, joten huomataan, että ne eivät ole parit.
Tulostuksessa siis risuaita (#
) tarkoittaa piiloon käännettyä korttia ja
piste tyhjää kohtaa eli poistettua korttia.
Jos kortti on näkyvissä, tulostetaan sen kirjain.
Käyttäjän antamista koordinaateista tutkitaan seuraavat asiat.
- Annettujen koordinaattien pitää olla lukuja.
- Annettujen koordinaattien määrämien kohtien pitää sijaita pelilaudalla. Toisin sanoen koordinaatin pitää olla vähintään 1, eikä se saa ylittää pelilauden rivien/sarakkeiden määrää. Esimerkiksi yllä olevalla pelilaudalla ei voi antaa kohtaa (5, 5).
- Annettuja koordinaatteja vastaavan kortin pitää olla pelilaudalla. Toisin sanoen kyseinen kortti ei saa olla poistettu. Esimerkiksi yllä olevalla pelilaudalla ei voi antaa korttia (1, 3).
- Annettuja koordinaatteja vastaavat kortit eivät saa olla samoja. Esimerkiksi ei ole sallittua antaa kortteja (2, 3) ja (2, 3) samassa syötteessä.
Jos jokin yllä mainittu ehto ei päde, ohjelma tulostaa:
Invalid card.
Jos annetut koordinaatit ovat laillisia, ohjelma tulostaa pelilaudan, jossa koordinaattien määräämät kortit ovat näkyvissä. Lisäksi se tulostaa joko:
Pairs found.
tai:
Pairs not found.
Tämän jälkeen ohjelma tulostaa kunkin pelaajan tiedot eli nimen ja kerättyjen parien määrän. Sitten tulostetaan pelilauta uudelleen kaikki jäljellä olevat kortit piilotettuina, ja kysytään seuraavaksi käännettävät kortit.
Koordinaattien (neljän luvun) sijasta käyttäjä voi antaa komennon
q
(quit), jolloin peli lopetetaan kesken.
Ohjelma tulostaa:
Why on earth you are giving up the game?
ja lopettaa suorituksensa paluuarvoon EXIT_SUCCESS
.
Kun kaikki parit ovat löytyneet, peli päättyy, ja ohjelma tulostaa ilmoituksen:
Game over!
sekä voittajan/voittajien keräämien parien määrän. Tulostus on hieman erilainen, jos yksi pelaaja voittaa kuin jos useamman pelaajan kesken tulee tasapeli.
Ohjelman tarkempi toiminta näkyy alla olevissa esimerkkiajossa:
Enter the amount of cards (an even number): xxx
Enter the amount of cards (an even number): 11
Enter the amount of cards (an even number): 0
Enter the amount of cards (an even number): 12
Enter a seed value: 1
Enter the amount of players (one or more): yyy
Enter the amount of players (one or more): 0
Enter the amount of players (one or more): 3
List 3 players: Maarit Minna Eliisa
===============
| | 1 2 3 4 |
---------------
| 1 | # # # # |
| 2 | # # # # |
| 3 | # # # # |
===============
Maarit: Enter two cards (x1, y1, x2, y2), or q to quit: 1 1 5 5
Invalid card.
Maarit: Enter two cards (x1, y1, x2, y2), or q to quit: 1 1 a b
Invalid card.
Maarit: Enter two cards (x1, y1, x2, y2), or q to quit: 1 2 1 2
Invalid card.
Maarit: Enter two cards (x1, y1, x2, y2), or q to quit: 1 1 2 1
===============
| | 1 2 3 4 |
---------------
| 1 | C A # # |
| 2 | # # # # |
| 3 | # # # # |
===============
Pairs not found.
*** Maarit has 0 pair(s).
*** Minna has 0 pair(s).
*** Eliisa has 0 pair(s).
===============
| | 1 2 3 4 |
---------------
| 1 | # # # # |
| 2 | # # # # |
| 3 | # # # # |
===============
Minna: Enter two cards (x1, y1, x2, y2), or q to quit: 1 1 3 1
===============
| | 1 2 3 4 |
---------------
| 1 | C # C # |
| 2 | # # # # |
| 3 | # # # # |
===============
Pairs found.
*** Maarit has 0 pair(s).
*** Minna has 1 pair(s).
*** Eliisa has 0 pair(s).
===============
| | 1 2 3 4 |
---------------
| 1 | . # . # |
| 2 | # # # # |
| 3 | # # # # |
===============
Minna: Enter two cards (x1, y1, x2, y2), or q to quit: 2 1 4 1
===============
| | 1 2 3 4 |
---------------
| 1 | . A . F |
| 2 | # # # # |
| 3 | # # # # |
===============
Pairs not found.
*** Maarit has 0 pair(s).
*** Minna has 1 pair(s).
*** Eliisa has 0 pair(s).
===============
| | 1 2 3 4 |
---------------
| 1 | . # . # |
| 2 | # # # # |
| 3 | # # # # |
===============
Eliisa: Enter two cards (x1, y1, x2, y2), or q to quit: 2 1 2 3
===============
| | 1 2 3 4 |
---------------
| 1 | . A . # |
| 2 | # # # # |
| 3 | # A # # |
===============
Pairs found.
*** Maarit has 0 pair(s).
*** Minna has 1 pair(s).
*** Eliisa has 1 pair(s).
===============
| | 1 2 3 4 |
---------------
| 1 | . . . # |
| 2 | # # # # |
| 3 | # . # # |
===============
Eliisa: Enter two cards (x1, y1, x2, y2), or q to quit: 1 2 2 2
===============
| | 1 2 3 4 |
---------------
| 1 | . . . # |
| 2 | E B # # |
| 3 | # . # # |
===============
Pairs not found.
*** Maarit has 0 pair(s).
*** Minna has 1 pair(s).
*** Eliisa has 1 pair(s).
===============
| | 1 2 3 4 |
---------------
| 1 | . . . # |
| 2 | # # # # |
| 3 | # . # # |
===============
Maarit: Enter two cards (x1, y1, x2, y2), or q to quit: 1 1 2 2
Invalid card.
Maarit: Enter two cards (x1, y1, x2, y2), or q to quit: 4 1 4 2
===============
| | 1 2 3 4 |
---------------
| 1 | . . . F |
| 2 | # # # F |
| 3 | # . # # |
===============
Pairs found.
*** Maarit has 1 pair(s).
*** Minna has 1 pair(s).
*** Eliisa has 1 pair(s).
===============
| | 1 2 3 4 |
---------------
| 1 | . . . . |
| 2 | # # # . |
| 3 | # . # # |
===============
Maarit: Enter two cards (x1, y1, x2, y2), or q to quit: 3 3 4 3
===============
| | 1 2 3 4 |
---------------
| 1 | . . . . |
| 2 | # # # . |
| 3 | # . D E |
===============
Pairs not found.
*** Maarit has 1 pair(s).
*** Minna has 1 pair(s).
*** Eliisa has 1 pair(s).
===============
| | 1 2 3 4 |
---------------
| 1 | . . . . |
| 2 | # # # . |
| 3 | # . # # |
===============
Minna: Enter two cards (x1, y1, x2, y2), or q to quit: 2 2 3 2
===============
| | 1 2 3 4 |
---------------
| 1 | . . . . |
| 2 | # B B . |
| 3 | # . # # |
===============
Pairs found.
*** Maarit has 1 pair(s).
*** Minna has 2 pair(s).
*** Eliisa has 1 pair(s).
===============
| | 1 2 3 4 |
---------------
| 1 | . . . . |
| 2 | # . . . |
| 3 | # . # # |
===============
Minna: Enter two cards (x1, y1, x2, y2), or q to quit: 1 2 1 3
===============
| | 1 2 3 4 |
---------------
| 1 | . . . . |
| 2 | E . . . |
| 3 | D . # # |
===============
Pairs not found.
*** Maarit has 1 pair(s).
*** Minna has 2 pair(s).
*** Eliisa has 1 pair(s).
===============
| | 1 2 3 4 |
---------------
| 1 | . . . . |
| 2 | # . . . |
| 3 | # . # # |
===============
Eliisa: Enter two cards (x1, y1, x2, y2), or q to quit: 1 3 3 3
===============
| | 1 2 3 4 |
---------------
| 1 | . . . . |
| 2 | # . . . |
| 3 | D . D # |
===============
Pairs found.
*** Maarit has 1 pair(s).
*** Minna has 2 pair(s).
*** Eliisa has 2 pair(s).
===============
| | 1 2 3 4 |
---------------
| 1 | . . . . |
| 2 | # . . . |
| 3 | . . . # |
===============
Eliisa: Enter two cards (x1, y1, x2, y2), or q to quit: 1 2 4 3
===============
| | 1 2 3 4 |
---------------
| 1 | . . . . |
| 2 | E . . . |
| 3 | . . . E |
===============
Pairs found.
*** Maarit has 1 pair(s).
*** Minna has 2 pair(s).
*** Eliisa has 3 pair(s).
===============
| | 1 2 3 4 |
---------------
| 1 | . . . . |
| 2 | . . . . |
| 3 | . . . . |
===============
Game over!
Eliisa has won with 3 pairs.
Jos peli olisi päättynyt kolmen pelaajan tasapeliin, ohjelma olisi tulostanut:
Game over!
Tie of 3 players with 2 pairs.
Yllä olevan pitkän tulostuksen alusta huomataan, että ohjelmaa kysyy toistuvasti korttien määrää, kunnes käyttäjä syöttää parillisen nollaa suuremman luvun. Samoin pelaajien lukumäärää kysytään, kunnes annetaan positiivinen luku. Myös siemenluvuksi voi yrittää antaa jotakin muuta kuin luvun, jolloin siemenluvuksi tulee nolla. Tällöin ei siis toistuvasti kysytä uutta siemenlukua, vaan mikä tahansa syöte hyväksytään, mutta ei-numeerinen syöte tulkitaan nollaksi.
Alkuosassa näkyy myös erilaisia virheellisiä koordinaatteja. Jäljempänä huomataan sama virheilmoitus, jos koordinaattien määräämä kortti on jo poistettu pelilaudalta.
Vain yhdestä virheellisyydestä ilmoitetaan, vaikka syötteessä olisi useitakin vikoja. Esimerkiksi jos koordinaatit olisivat sekä samoja että liian suuria, annettaisiin vain yksi virheilmoitus.
Syötteiden tyypeistä ja lukemisesta¶
Pohjakoodissa luvut (korttien lukumäärä ja siemenluku) on luettu
ensin merkkijonona ja muutettu sitten kokonaisluvuiksi
kutsumalla annettua funktiota stoi_with_check
.
Näin voidaan varmistua syötteiden oikeellisuudesta.
Pelaajien lukumäärän lukemista ei ole pohjakoodissa, vaan sen toteuttaminen
jää sinun tehtäväksesi.
Suositeltavaa on lukea pelaajien määrä vastaavalla tavalla kuin korttien
määrä.
Pelaajien nimet ovat merkkijonoja, joten niiden lukemiseen on kaksi tapaa:
operaattori >>
ja funktio getline
.
Pelaajat luetaan samalta riviltä.
Jos käytät funktiota getline
, joudut erottelemaan pelaajat, koska
getline
lukee yhden kokonaisen rivin, joka sisältää kaikki pelaajat.
Jos taas käytät operaattoria >>
(pelaajien lukumäärän verran), sinun
ei tarvitse erotella pelaajia, vaan saat ne suoraan eri merkkijonoiksi.
Jälkimmäinen tapa voi siis olla yksinkertaisempi, mutta tämä voi olla
myös makuasia.
Voit olettaa, että pelaajien nimiä annetaan se määrä, mikä aikaisemmin
kerrottiin.
Koordinaatit on pakko lukea merkkijonoina (tai yhtenä merkkijonona), koska
syötteenä saattaa olla myös lopetuskomento q
.
Tässäkin on vaihtoina käyttää funktiota getline
tai operaattoria >>
neljä kertaa.
Voit olettaa, että lopetuskomento on aina syötteen alussa, eli riittää,
tarkistaa, onko ensiksi annettu merkki/merkkijono q
.
Huomaa, että koodipohjassa on valmiina funktio stoi_with_check
,
jota voit käyttää merkkijonoluvun muuntamiseen kokonaisluvuksi.
Jos muuntaminen ei onnistu (merkkijono ei koostunut numeroista),
funktio palauttaa nollan.
Kun myöhemmin tutkit koordinaattien oikeellisuutta, nolla havaitaan
virheelliseksi, koska koordinaatit eivät voi olla ykköstä pienempiä.
Ohjelmakoodipohjat¶
Koodipohjassa on annettu tiedostot pairs.pro
ja main.cpp
sekä
luokat Card
ja Player
.
Pääasiassa koodi kirjoitetaan tiedostoon main.cpp
.
Luokka Card
on muuten valmis, mutta metodi print
on toteuttamatta.
Se kannattaa toteuttaa ihan ensimmäiseksi, jotta saat koko pelilaudan
tulostuksen kuntoon.
Luokan Player
julkinen rajapinta on valmis, mutta sinun pitää
kirjoittaa annetuille metodeille toteutukset (1-2 riviä koodia kuhunkin
metodiin) saman tyylisesti kuin Mölkky-pelin Player
-luokalla.
Mitä attribuutteja luokka tarvitsee?
Jos tulee tarvetta, niin luokkiin Player
ja Card
saa lisätä
uusia metodeita.
Toisaalta jos jokin näiden luokkien metodeista tuntuu turhalta,
sitä ei ole pakko käyttää.
Toteutuksen voi silloin jättää tyhjäksi.
Jos käyttämätön parametri aiheuttaa varoituksia, poista parametrin nimi
tai kommentoi se pois.
Älä kuitenkaan poista parametrin tyyppiä.
Tiedostossa main.cpp
on valmiina funktiot:
stoi_with_check
init_with_empties
next_free
init_with_cards
print_line_with_char
print
ask_product_and_calculate_factors
.
Näiden funktioiden toiminta selitetään alla, mutta ei haittaa, vaikka et ymmärtäisikään niiden koodia yksityiskohtaisesti. Halutessasi voit ohittaa tämän osion loppuosan ja siirtyä suoraan kohtaan “Projektin vaiheet”.
C++:ssa on valmiiksi määritelty funktio stoi
, joka muuntaa parametrina
annetun (numeerisen) merkkijonon vastaavaksi kokonaisluvuksi.
Jos annettu merkkijono ei ole numeerinen, aiheutuu poikkeus.
Poikkeuksia ei käsitellä tällä kurssilla.
Funktio stoi_with_check
toimii suunnilleen
samalla tavalla kuin stoi
, mutta se tarkistaa, onko parametrina
annettu merkkijono numeerinen.
Jos se on numeerinen, tehdään muunnos kutsumalla valmista stoi
-funktiota.
Jos se ei ole numeerinen, funktio palauttaa nollan.
Tässä tapauksessa (mutta ei yleisesti) nolla on hyvä paluuarvo, koska se ei
tässä kelpaa koordinaatiksi.
Funktio init_with_empties
alustaa kaikki kortit tyhjiksi ja lisää ne
pelilautavektoriin vektorioperaation push_back
avulla.
Kun pelilautavektori on täytetty alkioilla (millä tahansa alkioilla), sen
indekseihin voidaan myöhemmin viitata at
-funktiolla ja näin sijoittaa
varsinaiset kortit paikoilleen.
Funktio next_free
palauttaa ensimmäisen vapaan (ei-tyhjän) paikan
pelilaudalta alkaen annetusta indeksistä.
Jos vapaan paikan etsinnässä saavutetaan pelilaudan viimeinen sijainti
(oikea alakulma), mutta vapaata paikkaa ei ole löytynyt, etsintää
jatketaan pelilaudan alusta (oikeasta yläkulmasta).
Näin voi käydä, kun melkein koko pelilauta on täytetty korteilla.
Vapaa paikka löytyy kuitenkin aina, koska pelilaudan koko on sama kuin
korttien määrä.
Funktio toimii apufunktiona funktiolle init_with_cards
, joka täyttää
pelilaudan oikeilla korteilla.
Funktio init_with_cards
käyttää satunnaislukugeneraattoria arpomaan
sijainteja.
Ensimmäisenä arvottuunn sijaintiin sijoitetaan kortti A, toiseen toinen A,
kolmanteen B, neljänteen toinen B jne.
Koska arvottavaksi sijainniksi voisi tulla sellainen sijainti, johon on
jo sijoitettu kortti, tarvitaan funktiota next_free
, joka palauttaa
seuraavan tyhjän kohdan, jos arvonta osui jo käytettyyn sijaintiin.
Koska pelilauta täytetään tällä tavalla ripotellen, ei voida käyttää
operaatiota push_back
, ja siksi pelilauta on alustettu ensin
tyhjillä (funktiossa init_with_empties
).
Funktio print_line_with_char
saa parametrinaan tulostettavan merkin
ja rivin pituuden.
Funktio tulostaa näiden perusteella rivin, joka koostuu annetusta määrästä
annettua merkkiä.
Funktio print
tulostaa halutun kokoisen pelilaudan (leveydeltään ja
korkeudeltaan).
Se käyttää apunaan funktiota print_line_with_char
.
Funktio ask_product_and_calculate_factor
toimii vastaavalla tavalla
kuin 2-kierroksella toteutettu koodi (Läheisimmät tekijät).
Toisin sanoen funktio kysyy käyttäjältä tulon ja laskee sen perusteella
sellaiset tulon tekijät, jotka ovat mahdollisimman lähellä toisiaan.
Projektin vaiheet¶
Käytä versionhallintaa projektia tehdessäsi siten, että versionhallinnasta löytyy vähintään viisi committia seuraavasti:
- Ohjelma kysyy ja lukee pelaajien määrän ja nimet.
- Ohjelma tarkistaa annettujen koordinaattien oikeellisuuden.
- Ohjelma kääntää kortin, jos mahdollista.
- Lisäksi sinun on tehtävä vähintään kaksi muuta committia.
Edellä mainitut välivaiheet pitää myös olla commit-viesteissä mainittu selkeästi, jotta assistentti löytää ne helposti työtä tarkastaessaan.
Vinkkejä tehtävän tekemiseen:
- Aloita täydentämällä luokat
Card
jaPlayer
valmiiksi, minkä jälkeen pääset kokeilemaan, miten pohjakoodi toimii. - Pohjakoodissa pelilaudan tulostusfunktiota (funktio
print
tiedostossamain.cpp
) ei kutsuta missään. Kokeile kutsua sitä esimerkiksi pääohjelmassa (funktiomain
). - Tämän jälkeen voit aloittaa kysymyllä ja lukemalla pelaajien määrän ja nimet.
Arviointi¶
Jotta työ päätyisi assistenttien arvioitavaksi, sen pitää ensin läpäistä automaattitestit. Jos saat automaattitesteistä 0 pistettä, myös lopullinen pistemääräsi on 0, eikä työ mene assistenttien arvioitavaksi.
Assistentti arvioi ja pisteyttää automaattitestit läpäisseistä (= 1 p) töistä viimeisen määräajan puitteissa tehdyn commitin seuraavien arviointikriteerien mukaan:
- Ratkaisun yleisperiaate: 0-20 pistettä:
- Tehtävän osaamistavoitteet on saavutettu.
- Ohjelmakoodi on jaettu funktioita, luokkia ja/tai metodeita käyttäen loogisiksi kokonaisuuksiksi, jotka ovat sopivan pituisia.
- Luokat ja oliot on toteutettu olio-ohjelmoinnin periaatteita noudattaen (ks. edellinen materiaaliosio: Tyyliseikkoja, erityisesti kohta Olio-ohjelmointi).
- Tietorakenne ei sisällä toisteista eikä turhaa tietoa. Valittuja tietorakenteita on käytetty järkevästi.
- Ohjelmakoodi ei sisällä turhaa toisteisuutta eikä muutakaan turhaa.
- Ohjelmakoodi ei sisällä tarpeettomia rajoitteita tai oletuksia tai muita väkinäisiä ratkaisuita.
- Ohjelmarakenteet on toteutettu helposti ymmärrettäviksi.
- Ohjelmakoodissa ei ole käytetty globaaleja muuttujia (globaalit const-vakiot ovat OK).
- Ohjelman toimintaa ei lopeteta
exit
-funktiota käyttäen.
- Ohjelmointityyli: 0-20 pistettä:
- Muuttujat ja funktiot nimetty selkeästi ja kuvaavasti.
- Koodissa on käytetty nimettyjä vakioita taikalukujen sijasta.
- Ohjelmakoodi on asemoitu siististi.
- Ohjelmakoodirivit ovat enintään 80 merkkiä pitkiä.
- Jokaisen tiedoston alussa on kommentti, josta käy ilmi tiedoston tarkoitus, työn tekijä(t) ja muut tarvittavat tiedot (ks. kohta Alkukommentti).
- Jokaisen funktion/metodin alussa (otsikkotiedostossa jos mahdollista) on kommentti, joka kuvaa sen toiminnan, paluuarvon ja parametrit.
- Kommentteja on muutenkin tarpeellisissa kohdissa.
- Kommentit liittyvät toteutettuun ohjelmaan eivätkä johonkin sen vanhempaan versioon.
- Kaikki muuttujat on alustettu.
- Kääntäjä ei anna koodia käännettäessä varoituksia.
- Versionhallinnan käyttö: 0-10 pistettä:
- Committeja on riittävä määrä.
- Commit-viestien sisältö on selkeä ja kuvaava.
Attention
Tarkemmat tyylivaatimukset löytyvät tämän kierroksen edellisestä materiaaliosiosta.
A+ esittää tässä kohdassa tehtävän palautuslomakkeen.