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.

kluizenaarbeginopstelling

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.

plaatsing

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)$$.

mogelijke zetten

De eerste speler die geen enkel blok meer kan plaatsen, verliest het spel. Gelijkspel is niet mogelijk.

Opgave

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:

Voorbeeld

>>> 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()