views:

329

answers:

5

What datastructure would you use in Python to represent the internal state of a MineSweeper grid?

Each x,y position will hold a numerical value which represents its current cell state (unexplored, mine, flag, ?).

Should I use nested lists? This seems like the closest thing to a 2D array and it is what I would probably use in any other language (2d array that is).

I'm not that experienced with Python so could someone give me a suggestion?

+6  A: 

you could use a 2 dimensional array, holding objects for the state of each field:

class FieldState(object):
  def __init__(self):
    self.unexplored = True
    self.mine = Random()
    self.flag = Random()
    ...

for x in range(12):
  for y in range(24):
    list[x][y] = FieldState()
zlack
+6  A: 

Use a nested list. It's easy to set up:

field = [([None] * height) for x in range(width)]

field[x][y] = "*"

The clearest thing would probably be a new class:

class MineField(object):
    class _SingleField(object):
        mine = False
        flagged = False
        covered = True

    width = None
    height = None

    def __init__(self, width, height):
        super(MineField, self).__init__()
        self.width = width
        self.height = height
        self._field = [[self._SingleField() for y in range(height)]
                                            for x in range(width)]

        self.init_field(10)

    def init_field(self, minecount):
        pass

    def __getitem__(self, index):
        x, y = index
        return self._field[x][y]

To be used like this:

> m = MineField(10,10)
> m[4,9].mine
False
Georg
Since you are using a class, why not have `__getitem__` take a tuple as the argument. `def __getitem__(self,(x,y)):return self._field[x][y]`. Then you can use `m[4,9]`
gnibbler
@gnibbler: Don't know, somehow I thought it would make it more complex… (even though I've already implemented such a `__getitem__` method some time ago) Thanks.
Georg
+1  A: 

If you use an instance of Board class you can always change the internal representation later.

class Board(object):
    def __init__(self, width, height):
        self.__width, self.__height = width, height
        self._board = [[FieldState() for y in xrange(height)]
                       for x in xrange(width)]
    @property
    def width(self):
        return self.__width

    def mark(self, x, y):
        self._board[x][y].mark()

    def __getitem__(self, coord):
        """
        >>> board = Board(3, 4)
        >>> field = board[1,2] # 2nd column, 3rd row
        """
        x, y = coord
        return self._board[x][y]

    ...

Where FieldState is similar to the one from @zlack's answer.

J.F. Sebastian
+2  A: 

Just to throw another option in the mix, you could use dicts indexed by tuples

board = {}
board[1, 2] = 9
nosklo
+1  A: 

I think there are basically two layers of data: 1) map data: does square have a bomb (e.g represented by -1) or how many bombs are around it, 2) display data, what is shown on the square: bomb count, bomb, flag, question mark, empty, unopened.

So two nested lists (or one nested list of tuples) might be enough.

UncleBens