Have you ever played a game of minesweeper1? It is provided in an operating system the name of which escapes us. Oh well, the intention of the game is to discover where all mines are hidden in a rectangular $$m\times n$$ field with $$m$$ rows and $$n$$ columns. To make things a little more easy, the numbers are given in the boxes of the field. These indicate the number of mines that are hidden in adjacent boxes. Here, both horizontally, vertically and diagonally adjacent boxes count. Suppose, for example, that two mines are hidden in a $$4\times 5$$ field (their location is indicated with an asterisk):

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

If we were to indicate the amount of mines in adjacent boxes in the empty boxes (indicated with a full stop), we would obtain the following representation of the field:

*2110
12*10
01110
00000

As you can see, every box has a maximum of 8 adjacent boxes.

Assignment

Define a class Minesweeper which can be used to represent a field of a game of minesweeper. This class must support the following methods: 

Methods to which a position on the field must be given (isMine, addMine, eraseMine and nearbyMines), must always verify whether this position is situated within the boundaries of the field. If this should not be the case, an AssertionError must be raised with an appropriate message as indicated in the example below.

Example

>>> field = Minesweeper(4, 5, [(0, 0), (1, 2)])
>>> print(field)
*2110
12*10
01110
00000
>>> field.rows()
4
>>> field.columns()
5
>>> field.isMine(0, 0)
True
>>> field.nearbyMines(1, 0)
1
>>> field.nearbyMines(1, 1)
2
>>> field.addMine(3, 3)
>>> print(field)
*2110
12*10
01221
001*1
>>> field.eraseMine(0, 0)
>>> print(field.isMine(0, 0))
False
>>> print(field)
01110
01*10
01221
001*1
>>> field
Minesweeper(4, 5, [(1, 2), (3, 3)])

>>> field.isMine(4, 4)
Traceback (most recent call last):
AssertionError: invalid position (4, 4)
>>> speelveld = Minesweeper(1, 1)
Traceback (most recent call last):
AssertionError: field must contain at least two rows
>>> speelveld = Minesweeper(2, 1)
Traceback (most recent call last):
AssertionError: field must contain at least two columns