Heb je ooit het spelletje mijnenveger1 gespeeld? Het wordt meegeleverd met een besturingssysteem waarvan de naam ons nu niet direct te binnen schiet. Nu ja, de bedoeling van het spel is te ontdekken waar alle mijnen verborgen liggen in een rechthoekig $$m\times n$$ speelveld met $$m$$ rijen en $$n$$ kolommen. Om je te helpen, worden getallen in de hokjes van het speelveld weergegeven. Deze geven aan hoeveel mijnen er in aangrenzende hokjes liggen. Hierbij worden zowel horizontaal, verticaal als diagonaal aangrenzende hokjes in rekening gebracht. Veronderstel bijvoorbeeld dat er in een $$4\times 5$$ speelveld twee mijnen verborgen liggen (hun locatie wordt aangegeven met een sterretje):

*....
..*..
.....
.....

Indien we nu in de lege hokjes (aangegeven met een puntje) aangeven hoeveel mijnen er in aangrenzende hokjes liggen, dan krijgen we de volgende voorstelling van het speelveld:

*2110
12*10
01110
00000

Zoals je al zou kunnen opgemerkt hebben, heeft elk hokje ten hoogste 8 aangrenzende hokjes.

Opgave

Definieer een klasse Mijnenveger waarmee het speelveld van een spelletje mijnenveger kan voorgesteld worden. Deze klasse moet ondersteuning bieden aan de volgende methoden:

Methoden waaraan een postie op het speelveld moet doorgegeven worden (isMijn, mijnToevoegen, mijnVerwijderen en naburigeMijnen), moeten telkens nagaan of deze positie binnen de grenzen van het speelveld valt. Indien dit niet het geval is, moet hiervoor een AssertionError opgeworpen worden met een passende foutboodschap zoals aangegeven in onderstaand voorbeeld.

Voorbeeld

>>> speelveld = Mijnenveger(4, 5, [(0, 0), (1, 2)])
>>> print(speelveld)
*2110
12*10
01110
00000
>>> speelveld.rijen()
4
>>> speelveld.kolommen()
5
>>> speelveld.isMijn(0, 0)
True
>>> speelveld.naburigeMijnen(1, 0)
1
>>> speelveld.naburigeMijnen(1, 1)
2
>>> speelveld.mijnToevoegen(3, 3)
>>> print(speelveld)
*2110
12*10
01221
001*1
>>> speelveld.mijnVerwijderen(0, 0)
>>> print(speelveld.isMijn(0, 0))
False
>>> print(speelveld)
01110
01*10
01221
001*1
>>> speelveld
Mijnenveger(4, 5, [(1, 2), (3, 3)])

>>> speelveld.isMijn(4, 4)
Traceback (most recent call last):
AssertionError: ongeldige positie (4, 4)
>>> speelveld = Mijnenveger(1, 1)
Traceback (most recent call last):
AssertionError: speelveld moet minstens twee rijen hebben
>>> speelveld = Mijnenveger(2, 1)
Traceback (most recent call last):
AssertionError: speelveld moet minstens twee kolommen hebben