Programmeermethoden 2022
Derde programmeeropgave: LightsOut
De
derde programmeeropgave van het vak
Programmeermethoden
in het najaar van 2022
heet
LightsOut;
zie ook het
zevende werkcollege,
en lees geregeld deze pagina op WWW.
De opgave
Het is de bedoeling om een C++-programma te maken dat de gebruiker
in staat stelt
LightsOut te spelen via een menu-systeem.
Dat betekent dat de gebruiker van het programma kan kiezen
uit een aantal mogelijkheden, de zogeheten
opties.
Er zijn drie submenus, waarin ook weer enkele opties zijn.
De bedoeling is dat het hele menu steeds op één regel staat,
onder de puzzel (zie verderop).
De opties worden gekozen door de eerste letter van de betreffende
optie in te toetsen
(gevolgd door Enter), bijvoorbeeld een
s of
S om te stoppen.
Uiteraard wordt een en ander
duidelijk en ondubbelzinnig aan de gebruiker meegedeeld.
Gebruik
geen recursie!
Alle door de gebruiker
ingetoetste symbolen moeten gecontroleerd worden, dat wil zeggen dat
er binnen redelijke grenzen geen foute invoer geaccepteerd wordt.
Zo zal het intoetsen van bijvoorbeeld X of & in het hoofdmenu genegeerd worden.
Verder moet bij getalleninvoer karakter voor
karakter ingelezen worden
(met cin.get ( );
als je elders ook nog cin >> ... gebruikt
krijg je overigens
soms problemen met "hangende Enter's"; gebruik dus overal
cin.get ( )). Er moet ook op gelet worden
dat er geen te grote getallen worden ingevoerd.
Schrijf dus een geschikte functie leesgetal die de gelezen karakters
(cijfers) omzet in een getal
(tip: negeer alle "voorloop-Enter's"; verwerk alles tot en met de eerstvolgende enter,
en maak hiervan zo goed mogelijk een getal, van een maximale grootte;
zo kan abc123defg999h, als je een getal kleiner dan 10000
wilt, bijvoorbeeld verwerkt worden tot 1239),
en een functie leesoptie
die netjes één karakter inleest en Enter's afhandelt!
Aan de gebruiker mogen "redelijke" beperkingen worden gevraagd,
bijvoorbeeld dat de in te voeren getallen maximaal 42 is,
Het programma moet dan echter wel bestand zijn tegen pogingen
grotere getallen in te voeren. Ook het invoeren van
letters in plaats van cijfers moet geen problemen opleveren.
Houd het simpel!
Maak ook een functie leesoptie die de
eerste niet-Enter ophaalt. De functie geeft een char terug.
Het spel LightsOut heeft simpele spelregels, zie bijvoorbeeld
Wikipedia,
en de referenties daar.
In een 2-dimensionaal rechthoekig rooster, (zeg) 4 bij 6, de puzzel,
bevindt zich in ieder vakje een lamp die aan of uit is.
Doel is ze allemaal uit krijgen.
Als je een vakje kiest, klapt het lampje daar om tussen aan en uit, evenals de lampjes in de direct horizontaal en verticaal aangrenzende buren.
Maximale grootte is 20 bij 20.
In het hoofdmenu kun je kiezen tussen de volgende opties
[P]arameters, p[U]zzelmenu en [T]ekenen, die alle drie naar een submenu leiden.
En uiteraard [S]toppen.
Het pUzzelmenu heeft de volgende opties:
- Terug naar het hoofdmenu.
- Volg. De lampen in de puzzel (geen torus) worden rij voor rij van links naar rechts en
van boven af uitgedaan (behalve de onderste),
door automatisch "onder" de lampen die aan zijn te selecteren.
De tussenstappen komen alle in beeld.
- Los een 5 bij 5 puzzel (geen torus) op — als dat kan. Na de optie Volg gebruikt te hebben,
moet alleen de onderste rij nog worden opgelost. Zie bijvoorbeeld
Wikipedia
voor aanwijzingen op een 5 bij 5 bord.
Onderscheid verschillende gevallen, en doe daarna opnieuw Volg.
- Speel de "oplossing" af.
- Doe een zet, na eerst een vakje geselecteerd te hebben.
Gebruik hierbij de schaakbord-notatie: hoofdletters A, B, ... voor kolommen en getallen 1,2 ... voor rijen. Linksonder zit A1.
Zetten worden geteld, de teller staat steeds naast het bord afgedrukt.
Doe deze zet ook in de "oplossing".
Het Tekenmenu heeft de volgende opties:
- Terug naar het hoofdmenu.
- Schoon. Maak de puzzel leeg (alle lampen gaan uit). rest ook de oplossing.
- Random. Maak de puzzel eerst schoon. Zet daarna random lampen aan.
Gebruik een zelfgemaakte random-generator (nou ja, random),
zie Hoofdstuk 3.9.3 uit het dictaat, gedeelte "aantekeningen bij de hoorcolleges".
- Toggle. Klapt de lamp op de "cursorpositie" om: van aan naar uit, of juist omgekeerd.
(Je doet dus niet de zet, zoals in het pUzzelmenu.)
Deze positie kan met vier toetsen omhoog/omlaag/naar links/rechts (bijvoorbeeld W/A/S/Z) gewijzigd worden.
- Genereer. Maak een puzzel met een gegeven "moeilijkheidsgraad",
zeg g. Doe dit door random g verschillende lampen te selecteren (met de optie uit het pUzzelmenu),
te beginnen met een situatie waar alle lampen uit zijn.
Onthoud de gekozen lampen in de "oplossing" (in een apart Booleaans 2-dimensionaal array), zodat deze later gespeeld kan worden.
Er zijn verschillende parameters, in te stellen via het gelijknamige submenu:
- De hoogte en breedte van het bord, beide maximaal 20.
- Het percentage lampen dat aan moet gaan bij de optie Random (bij benadering).
- De twee verschillende karakters aan/uit die op het scherm gebruikt worden voor de lampen.
- Is het (j/n) een torus = fietsband of een gewone rechthoek met randen?
- Een pen (0/1/2) die aangeeft of je bij het lopen ook nog meteen lampen aan doet (1) of juist uit (2).
Kies zelf verstandige grenswaarden voor deze parameters, en gebruik
leesgetal of
leesoptie.
De bedoeling is een klasse (class) puzzel te maken,
met daarin onder meer functies die ieder voor zich een
menuoptie afhandelen. De parameters zijn typisch membervariabelen.
Gebruik nog geen eigen headerfiles,
alles moet deze keer in één file staan.
Opmerkingen
Gebruik geschikte (member)functies.
Bij deze opgave mogen bij
elke functie (zelfs main) tussen begin-{ en
eind-} hooguit circa 30 niet al te volle regels staan!
Vooruit, bij maximaal drie functie
(zoals afdrukken of 5 bij 5 oplossen) mogen het er wat meer zijn.
Elke functie dient van commentaar voorzien te zijn, bij voorkeur
één regel boven de functie.
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 headerfiles zijn in principe
iostream, fstream, cstdlib en string.
Zeer ruwe indicatie voor de lengte van het C++-programma: 500 regels.
Denk aan het infoblokje.
Uiterste inleverdatum: maandag 14 november 2022, 17:00 uur.
Manier van inleveren:
- Digitaal de C++-code
inleveren: stuur een email naar
pm@liacs.leidenuniv.nl.
Stuur geen executable's,
lever alleen de C++-file digitaal in! Noem deze bij voorkeur zoiets als
jansentilanus3.cc, dit voor de derde opdracht van het duo Jansen-Tilanus.
De laatst voor de deadline ingeleverde versie wordt nagekeken.
- En ook een papieren versie van het verslag
(inclusief de C++-code) deponeren
in de speciaal daarvoor bestemde doos "Programmeermethoden"
bij kamer 159 van het Snellius-gebouw.
Overal duidelijk datum en namen van de (maximaal twee) makers vermelden,
in het bijzonder als commentaar in de eerste regels van de C++-code.
Het verslag (uiteraard weer in LaTeX,
zie de eerdere opgaven) moet het volgende bevatten: een
beschrijving van het programma (waarin LightsOut kort maar duidelijk wordt uitgelegd),
een plaatje van een niet al te zwart
screenshot (in Linux: Shift-PrintScreen) van het eigen programma,
een beschrijving van punten waarop het programma faalt (indien van toepassing),
en een tabel met gewerkte uren, uitgesplitst per week en per persoon.
Geef ook minstens twee citaties = referenties (in LaTeX: "\cite"),
één bij de uitleg over het spel,
en bijvoorbeeld één naar een wiskunde-artikel over het spel.
Zie hier hoe
je een plaatje verwerkt, en hoe een citatie = referentie gemaakt wordt
(en zo ziet dat eruit).
Te gebruiken compiler: als hij maar C++ vertaalt;
het programma moet in principe zowel op een Linux-machine
(met
g++) als onder Code::Blocks draaien.
Test dus in principe op beide systemen!
Het programma wordt doorgaans nagekeken met behulp van de compiler
die (uiteraard) in het commentaar bovenin het programma vermeld staat.
Normering: layout 1; commentaar (inclusief verslag) 2; modulariteit (OOP, functies) 3;
werking 4.
Eventuele aanvullingen en verbeteringen: lees de huidige WWW-bladzijde:
www.liacs.leidenuniv.nl/~kosterswa/pm/op3pm.php.