Kluizenaar is een strategiespel voor twee spelers. Het wordt gespeeld op een spelbord met $$n \times n$$ vierkante velden die gerangschikt zijn in een vierkant rooster met $$n$$ rijen en $$n$$ kolommen. Bij aanvang van een spel is het spelbord leeg. Naast het spelbord ligt een voorraad balkvormige blokken met afmetingen van $$1 \times 1 \times 2$$ eenheden, waarbij een eenheid ongeveer even lang is als de zijde van een veld op het spelbord. De blokken hebben drie verschillende kleuren: rood, geel en blauw.
Elke speler kiest om de beurt een blok van een bepaalde kleur. Het blok mag rechtopstaand op het bord geplaatst worden zodat het slechts één veld bedekt of op een lange kant neergelegd worden zodat het twee aangrenzende velden bedekt.
Blokken mogen alleen maar op lege velden geplaatst worden. Ze mogen ook niet raken aan een blok van dezelfde kleur, ook niet diagonaal. In onderstaand schema liggen er al blokken op dezelfde posities als op de foto hierboven. De gele cirkels geven de enige mogelijkheden aan om nog een blok te plaatsen: een geel blok dat rechtopstaand geplaatst wordt op positie $$(1, 0)$$ of positie $$(3, 0)$$.
De eerste speler die geen enkel blok meer kan plaatsen, verliest het spel. Gelijkspel is niet mogelijk.
Om naar de velden op een Kluizenaar spelbord te kunnen verwijzen, worden de rijen van boven naar onder genummerd en de kolommen van links naar rechts, telkens vanaf nul. De positie van een veld op het spelbord wordt aangeduid met een tuple $$(r, k)$$, waarbij $$r \in \mathbb{N}$$ (int) het rijnummer en $$k \in \mathbb{N}$$ (int) het kolomnummer aanduidt.
De kleur van een blok wordt aangeduid met een hoofdletter: Y (geel), B (blauw) of R (rood).
De plaatsing van een blok wordt aangeduid met een hoofdletter: U (rechtopstaand), H (horizontaal) of V (verticaal).
Definieer een klasse Kluizenaar waarmee het verloop van een spelletje Kluizenaar kan gesimuleerd worden. Bij het aanmaken van een nieuw spel (Kluizenaar) moet de dimensie $$n$$ (int) van het spelbord doorgegeven worden. Bij aanvang van het spel staan er nog geen blokken op het spelbord.
Als er een spel (Kluizenaar) wordt doorgegeven aan de ingebouwde functie str, dan moet een stringvoorstelling (str) van het spelbord teruggegeven worden. Daarin vormt elke rij een afzonderlijke regel. Lege velden worden voorgesteld door een punt (.) en velden waarop een blok ligt door de hoofdletter die de kleur van het blok aanduidt. De voorstellingen van aangrenzende velden op dezelfde rij worden telkens van elkaar gescheiden door één spatie.
Daarnaast moeten op een spel $$s$$ (Kluizenaar) minstens de volgende methoden kunnen aangeroepen worden:
Een methode posities waaraan twee argumenten moeten doorgegeven worden: i) de positie $$(r, k)$$ van een veld op het spelbord en ii) de plaatsing $$P$$ (str) van een blok. De methode moet een verzameling (set) teruggeven met alle posities die bedekt zouden worden door een blok dat in plaatsing $$P$$ met zijn linkerbovenhoek op veld $$(r, k)$$ van het spelbord zou geplaatst worden. Een blok dat rechtopstaand geplaatst wordt, bedekt enkel veld $$(r, k)$$, een blok dat horizontaal geplaatst wordt bedekt velden $$(r, k)$$ en $$(r, k + 1)$$ en een blok dat verticaal geplaatst wordt bedekt velden $$(r, k)$$ en $$(r + 1, k)$$.
De methode posities moet geen rekening houden met de dimensie van het spelbord: de verzameling (set) die wordt teruggegeven kan posities bevatten die buiten het spelbord liggen. De methode moet ook geen rekening houden met andere blokken die eventueel al op het spelbord geplaatst werden.
Een methode isgeldig waaraan twee argumenten moeten doorgegeven worden: i) de kleur $$K$$ (str) van een blok en ii) de positie $$(r, k)$$ van een veld op het spelbord. De methode moet een Booleaanse waarde (bool) teruggeven die aangeeft of positie $$(r, k)$$ een leeg veld binnen het rooster van het spelbord aanduidt dat niet grenst (ook diagonaal) aan een ander veld met kleur $$K$$.
Een methode zet waaraan drie argumenten moeten doorgegeven worden: i) de kleur $$K$$ (str) van een blok, ii) de positie $$(r, k)$$ van een veld op het spelbord en iii) de plaatsing $$P$$ (str) van een blok. De methode moet een blok van kleur $$K$$ met zijn linkerbovenhoek op veld $$(r, k)$$ van het spelbord plaatsen in plaatsing $$P$$, en moet een verwijzing teruggeven naar het spel $$s$$ waarop de methode werd aangroepen. Als er volgens de spelregels geen blok kan geplaatst worden op de aangegeven positie, dan mag er geen blok geplaatst worden en moet de methode een AssertionError opwerpen met de boodschap ongeldige zet.
Een methode mogelijke_zetten waaraan geen argumenten moeten doorgegeven worden. De methode moet een verzameling (set) teruggeven met alle mogelijke manieren waarop in de volgende beurt een blok op het spelbord kan geplaatst worden. Daarbij wordt een manier om een blok op het spelbord te plaatsen voorgesteld als een tuple met drie elementen die corresponderen met de drie argumenten die aan de methode zet kunnen doorgegeven worden.
>>> spelbord = Kluizenaar(4)
>>> print(spelbord)
. . . .
. . . .
. . . .
. . . .
>>> spelbord.posities((0, 0), 'H')
{(0, 0), (0, 1)}
>>> spelbord.isgeldig('R', (0, 0))
True
>>> spelbord.isgeldig('R', (0, 1))
True
>>> print(spelbord.zet('R', (0, 0), 'H'))
R R . .
. . . .
. . . .
. . . .
>>> print(spelbord.zet('R', (1, 2), 'V'))
Traceback (most recent call last):
AssertionError: ongeldige zet
>>> print(spelbord.zet('B', (0, 2), 'U').zet('Y', (1, 2), 'U'))
R R B .
. . Y .
. . . .
. . . .
>>> print(spelbord.zet('R', (3, 1), 'U').zet('Y', (3, 2), 'H'))
R R B .
. . Y .
. . . .
. R Y Y
>>> print(spelbord.zet('R', (1, 3), 'V').zet('B', (2, 0), 'H'))
R R B .
. . Y R
B B . R
. R Y Y
>>> spelbord.mogelijke_zetten()
{('Y', (1, 0), 'U'), ('Y', (3, 0), 'U')}
>>> print(spelbord.zet('Y', (3, 0), 'U'))
R R B .
. . Y R
B B . R
Y R Y Y
>>> spelbord.mogelijke_zetten()
{('Y', (1, 0), 'U')}
>>> print(spelbord.zet('Y', (1, 0), 'U'))
R R B .
Y . Y R
B B . R
Y R Y Y
>>> spelbord.mogelijke_zetten()
set()