|
Maak vanaf het begin gebruik van een aantal voorbeeldfiles, van waaruit de opgave stap voor stap kan worden gedaan. De files zijn allereerst (zie verderop voor gebruik met Code::Blocks, op eigen risico):
Het spel Koffiesweeper, een getrouwe kopie van het welbekende Minesweeper, verloopt als volgt. De speler ziet een rechthoek met m (hoogte) bij n (breedte) vakjes, alle gesloten. Op een aantal vakjes staat (verborgen) een kop koffie of thee. De speler krijgt te horen hoeveel dat er in totaal zijn. De speler kan een vakje selecteren door de coordinaten te geven. Als hier een kop koffie staat heeft de speler onmiddellijk verloren: de koffie moet meteen worden opgedronken. Zo niet, dan ziet de speler een getal tussen 0 en 8: het aantal directe buurvakjes, horizontaal, verticaal en diagonaal, dat een kop koffie bevat.
We spelen het spel als volgt.
Eerst mag de grootte van het bord gekozen worden:
het aantal rijen m en het aantal kolommen n,
en welk percentage van de vakjes (ongeveer) gevuld is met een kop koffie
(gebruik random ( ) uit <cstdlib>; denk aan srand ( );
en gebruik de functie leesgetal van de derde opgave);
het exacte aantal wordt aan de speler bekend gemaakt.
De speler kan kiezen of hij/zij zelf één spelletje speelt,
of dat er volledig random wordt gespeeld, waarbij het aantal spelletjes gekozen mag worden (steeds met een nieuwe beginconfiguratie).
Het eerst geopende vakje bevat nooit een kop koffie.
Als de mens speelt wordt steeds de stand —in eenvoudig
formaat— op het scherm
getoond, en kan de speler zijn/haar zet doen (een vakje openen),
of juist de laatste
zet terugnemen (zie straks), of een random zet laten doen,
of een vakje markeren met een 'K'.
Als er een reeds eerder geopende plek wordt geselecteerd, moet
de speler natuurlijk opnieuw kiezen.
Het aantal gedane zetten wordt ook steeds getoond.
De menselijke speler kan een vakje markeren waarvan hij/zij denkt dat het een kop koffie bevat;
deze vorm van selecteren telt niet mee voor het aantal zetten.
Als een vakje met 0 koffie-buren wordt geopend, kunnen al diens buren veilig worden opgevraagd.
Schrijf hiertoe een recursieve functie die dit automatisch doet.
De speler wint als alle vakjes die geen kop koffie bevatten zijn geopend.
Als het programma volledig random speelt, wordt in een tweetal arrays, één voor de gewonnen en één voor de verloren spelletjes, bijgehouden hoeveel zetten het telkens duurde. Na afloop wordt dan geprint hoeveel spelletjes z zetten duurden (z = 0, 1, ...), ten behoeve van een grafiek, zie onder.
Schrijf een functie voor de klasse koffiebord die een pointerstructuur aanlegt, waarbij ieder vakje, naast bijvoorbeeld een int en enkele bool's als inhoud, tevens een array met 8 pointers naar de onmiddellijke buren heeft: middenboven (0), rechtsboven (1), rechts (2), rechtsonder (3), middenonder (4), linksonder (5), links (6) en linksboven (7). De vakjes aan de randen bevatten uiteraard diverse nullptr's. Het bord is dus niet een m bij n array, maar een zeer ingewikkelde pointerstructuur.
Bij de menselijke speler moeten alle complete borden op een stapel worden bijgehouden, en deze kunnen daarmee teruggenomen worden. Zodra een speler zet, wordt een kopie van het bord opgeslagen. Dit onderdeel is zeker niet eenvoudig; mocht het ontbreken, dan kost dat een punt.
Het is de bedoeling om een vijftal files te produceren:
de eerste bevat main en het menutje,
de tweede (zeg koffiebord.h, zie boven) bevat de klasse-definitie voor koffiebord,
en de derde (zeg koffiebord.cc, zie boven) bevat de functies uit die klasse.
Evenzo zijn er files stapel.h en stapel.cc, indien van toepassing.
Maak als het kan ook een makefile.
Code::Blocks-gebruikers: doe deze opgave liever op een Linux-machine.
Maar het kan wel: open een nieuw project via
"File -- New project -- Empty project", vul wat in,
en voeg de drie files toe via "Project -- Add files",
en daarna het project compileren op de gebruikelijke manier.
Of, op eigen risco, lees
over projecten.
Opmerkingen
Gebruik geschikte (member)functies.
Bij deze opgave mogen wederom bij
elke functie tussen begin-{ en
eind-} hooguit circa 30 niet al te volle of complexe regels staan!
Elke functie dient van commentaar voorzien te zijn.
Als uitzondering mag main langer zijn, als daarin met het menu gewerkt wordt.
Let op goed parametergebruik: alle parameters, met uitzondering van membervariabelen, in de heading doorgeven, en de
variabele-declaraties zowel bij main als bij de
andere functies aan het begin.
De enige te gebruiken headerfile is in principe
iostream, en eventueel ctime en cstdlib (voor de random-generator).
Zeer ruwe indicatie voor de lengte van de gezamenlijke C++-files: 600 regels.
Denk aan het infoblokje.
Uiterste inleverdatum: maandag 13 december 2021, 17:00 uur.
Manier van inleveren: