Het spelletje "∞ lus" wordt gespeeld met $$m \times n$$ tegels, gerangschikt in een $$m \times n$$ rooster met $$m$$ rijen en $$n$$ kolommen. Er zijn in totaal 16 verschillende tegelconfiguraties:

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

Elke tegel kan met andere woorden aansluitingen hebben naar boven, naar rechts, naar beneden, en naar links. De tegelconfiguraties worden gevormd door alle mogelijke combinaties van aansluitingen in deze vier richtingen, inclusief de tegel zonder aansluitingen.

Bij aanvang van het spel wordt het rooster gevuld met een selectie van tegels. De speler kiest vervolgens een tegel, en draait die 90° in wijzerzin of tegenwijzerzin. Als we bijvoorbeeld tegel in wijzerin draaien dan bekomen we tegel , tegel wordt , maar tegel blijft . De speler kan deze procedure eindeloos blijven herhalen.

Het doel van het spel is om gesloten circuits te vormen: elke aansluiting moet connecteren op een aansluiting van de naburige tegel langs dezelfde zijde. Als een tegel bijvoorbeeld een aansluiting naar rechts heeft, dan moet de tegel rechts daarvan in het rooster een aansluiting naar links hebben. Bij wijze van illustratie toont onderstaand videofragment een speler die puzzels uit het spelletje "∞ lus" probeert op te lossen.

Opgave

Een eenvoudige manier om de tegels voor te stellen — zonder gebruik te moeten maken van Unicode-karakters — is door gebruik te maken van een bitmasktechniek. Hierbij wordt elke tegel voorgesteld als een natuurlijk getal uit het interval $$[0, 15]$$ door gebruik te maken van de volgende code:

Grafisch ziet dat er als volgt uit:

tegel
Bitmaptechniek waarmee elke tegel kan voorgesteld worden als een natuurlijk getal uit het interval $$[0, 15]$$.

Op die manier kan de tegel voorgesteld worden als het getal $$1 + 4 + 8 = 13$$. Als we de binaire voorstelling van het getal bekijken, dan zien we dat

Zo komt 13 overeen met het binaire getal 1101, waaruit we direct kunnen afleiden dat de tegel aansluitingen heeft naar alle richtingen behalve naar rechts.

Tegel

Definieer een klasse Tegel waarmee tegels uit het spelletje "∞ lus" kunnen voorgesteld worden. Bij het aanmaken van een nieuwe tegel (Tegel) kan een natuurlijk getal (Number; standaardwaarde: 0) doorgegeven worden, dat de tegel beschrijft op basis van de bitmasktechniek die hierboven werd beschreven. Als het gegeven getal niet in het interval $$[0, 15]$$ ligt, dan moet een Error opgeworpen worden met de boodschap ongeldige tegel.

Een tegel $$t$$ (Tegel) moet minstens de volgende eigenschappen hebben:

Daarnaast moet je op een tegel $$t$$ (Tegel) minstens de volgende methoden kunnen aanroepen:

OneindigeLus

Definieer ook nog een klasse OneindigeLus waarmee een puzzel van het spelletje "∞ lus" kan voorgesteld worden. Bij het aanmaken van een nieuwe puzzel (OneindigeLus) moeten twee argumenten doorgegeven worden: i) een reeks (Array) met natuurlijke getallen (Number) uit het interval $$[0, 15]$$ die de tegels in het rooster voorstellen, uitgelezen in de leesrichting (van links naar rechts en van boven naar onder), en ii) een natuurlijk getal (Number) dat aangeeft hoeveel kolommen het rooster telt. Als deze argumenten niet corresponderen met een geldig rooster van tegels, dan moet een Error opgeworpen worden met de boodschap ongeldig rooster.

Op een puzzel $$p$$ (OneindigeLus) moet je minstens de volgende methoden kunnen aanroepen:

Voorbeeld

>>> const tegel = new Tegel(11)
>>> tegel.boven
true
>>> tegel.rechts
true
>>> tegel.onder
false
>>> tegel.links
true
>>> tegel.toString()
"┻"
>>> tegel.draai().toString()
"┣"
>>> tegel.draai().draai().toString()
"┫"
>>> tegel.draai(false).toString()
"┳"
>>> tegel.draai(false).draai(false).toString()
"┻"

>>> const spel = new OneindigeLus([9, 12, 12, 6, 10, 13, 13, 5, 3, 3, 9, 3], 4)
>>> console.log(spel.toString())
┛┓┓┏
━┫┫┃
┗┗┛┗
>>> spel.opgelost()
false
>>> console.log(spel.draai(0, 0).draai(0, 0).draai(0, 2, false).draai(0, 3).toString())
┏┓┏┓
━┫┫┃
┗┗┛┗
>>> spel.opgelost()
false
>>> console.log(spel.draai(1, 0).draai(1, 1).draai(1, 1).toString())
┏┓┏┓
┃┣┫┃
┗┗┛┗
>>> spel.opgelost()
false
>>> console.loo(spel.draai(2, 1, false).draai(2, 2).draai(2, 3, false).toString())
┏┓┏┓
┃┣┫┃
┗┛┗┛
>>> spel.opgelost()
true