Voor deze programmeeropgave gaan we het spel Othello
programmeren, of
zoals het ook wel genoemd wordt: Reversi.
Het is de bedoeling een klasse OthelloBord te maken,
die onder meer memberfuncties heeft als afdrukken, spelerzet
en computerzet.
Uiteraard heeft deze klasse ook een constructor en een destructor.
Verder moeten gedane zetten met behulp van een stapel
ongedaan gemaakt kunnen worden, en kan het aantal
vervolgpartijen worden uitgerekend.
Het "normale" spel Othello gaat als volgt.
Op een 8 bij 8 bord wordt gespeeld met schijfjes die
aan de ene kant wit en aan de andere kant zwart zijn.
Om de beurt leggen de spelers -wit W en zwart
Z geheten-
een schijfje met hun eigen kleur naar boven
op een nog leeg vakje.
Dit mag alleen op een plek waar stenen van de tegenstander
geslagen worden.
Stenen van de tegenstander die ingesloten raken, hetzij horizontaal, of
verticaal, of diagonaal, tussen eigen stenen, worden geslagen:
ze worden omgekeerd, en krijgen dus de eigen kleur.
Zwart begint.
Als een speler niet kan zetten, moet hij/zij passen.
Het spel is afgelopen als geen van de spelers
meer kan zetten, bijvoorbeeld als het bord vol is.
Winnaar is degene met de meeste stenen in zijn of haar kleur;
gelijk spel is mogelijk.
Kijk eens op
http://www.litefaden.com/marvin/
voor een mooie werkende Othello
(voor de vierde programmeeropgave hoeft het niet grafisch,
en het programma hoeft niet zo goed te spelen!).
De beginconfiguratie voor Othello staat links hieronder
(voor Reversi is deze overigens iets anders),
gevolgd door enkele voorbeeldzetten:
. . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . .
. . . W Z . . . . . . W Z . . . . . . W Z . . .
. . . Z W . . . . . . Z Z Z . . . . . Z W Z . .
. . . . . . . . . . . . . . . . . . . . . W . .
. . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . .
In één zet kunnen stenen uit verschillende richtingen tegelijk
geslagen worden. De stenen moeten echt aan beide zijden
ingesloten raken om geslagen te worden. In een richting
kunnen meerdere stenen tegelijk geslagen worden.
We spelen het spel met aangepaste regels.
Allereerst mag de speler zijn/haar kleur kiezen;
de computer speelt dan voor de andere kleur.
Daarna mag ook de grootte van het bord gekozen worden:
het aantal rijen m en het aantal kolommen n,
beide minstens 2.
Normaal geldt dus dat m=8 en n=8.
De vier beginschijven staan op vakje (m/2,n/2),
en de vakjes daar rechts/onder.
Als de speler aan zet is, wordt de stand -in eenvoudig
formaat- op het scherm
getoond, en kan de speler zijn/haar zet doen, of juist de laatste
eigen zet
(en meteen de tussenliggende computerzet) terugnemen,
of het aantal mogelijke vervolgpartijen voor de huidige stand laten
uitrekenen.
De mogelijke zetten worden opgesomd
(bijvoorbeeld als 1: C2, 2: F5, 3: A8)
zodat de speler eenvoudig kan kiezen.
De door de speler uitgekozen zet wordt gedaan, waarna de computer een
willekeurige, maar uiteraard wel toegestane, zet doet.
Denk aan het verplichte "passen".
Liefhebbers mogen natuurlijk hun eigen creativiteit inzetten,
door bijvoorbeeld de computerzet waarbij de meeste stenen geslagen
worden te kiezen.
Schrijf een constructor voor de klasse OthelloBord die
een pointerstructuur aanlegt,
waarbij ieder vakje, naast bijvoorbeeld een char als inhoud,
tevens een array met 8 pointers naar
de onmiddellijke buren heeft: linksboven, middenboven,
rechtsboven, rechts, rechtsonder,
middenonder, linksonder en links. De vakjes aan de randen
bevatten uiteraard diverse NULL-pointers.
Het bord is dus niet een m bij n array,
maar een zeer ingewikkelde pointerstructuur.
Alle tussenstanden moeten
op een stapel worden bijgehouden, en spelerzetten kunnen
daarmee zelfs herhaald teruggenomen worden.
Hiertoe moeten dus alle standen
(en niet de zetten) worden onthouden,
of liever gezegd: zodra de speler zet, wordt de oude stand
(het complete bord) opgeslagen.
Er moet dus een memberfunctie kopieer
gemaakt worden, die de gehele pointerstructuur kopieert!
Verder dient er een recursieve memberfunctie
vervolg geschreven te worden
die gegeven een zekere stand het totale
aantal mogelijke vervolgpartijen, dat overigens erg groot
kan zijn, uitrekent.
Hiervoor moeten alle mogelijke
zetten van beide spelers doorgerekend worden.
Dit onderdeel is zeker niet eenvoudig;
mocht het ontbreken, dan kost dat een halve punt.
Enkele algemene opmerkingen:
Vragen en/of opmerkingen kunnen worden gestuurd
naar: kosters@liacs.nl.
6 november 2000 - http://www.liacs.nl/home/kosters/pm/op4pm00.html