rendered paste bodyimport unittestclass MineField(object): @classmethod def fromString(cls, *rows): return cls([[ch != '.' for ch in row] for row in rows]) def __init__(self, rows): self.minesGrid = Grid(rows) self.dugGrid = Grid([[False] * len(row) for row in rows]) self.win = False self.gameOver = False def dig(self, row, col): cell = Coordinate(row, col) if self._thereIsAMineAt(cell): self._looseGame() else: self._uncoverCellAndFreeNeighbors(cell) if self._allCoveredCellsHideMines(): self._winGame() def _uncoverCellAndFreeNeighbors(self, cell): if not self._cellIsAlreadyDug(cell): self.dugGrid.mark(cell) for neighbor in self.dugGrid.iterNeighborsOf(cell): if not self._thereIsAMineAt(neighbor): self._uncoverCellAndFreeNeighbors(neighbor) def _cellIsAlreadyDug(self, cell): return self.dugGrid.isMarked(cell) def _thereIsAMineAt(self, cell): return self.minesGrid.isMarked(cell) def _looseGame(self): self.win = False self.gameOver = True def _winGame(self): self.win = True self.gameOver = True def _allCoveredCellsHideMines(self): for cell in self.dugGrid.iterAllCoveredCells(): if not self._thereIsAMineAt(cell): return False return True class Grid(object): def __init__(self, rows): self.rows = rows def iterAllCoveredCells(self): for cell in self._iterAllCells(): if not self.isMarked(cell): yield cell def _iterAllCells(self): for row in xrange(0, len(self.rows)): for col in xrange(0, len(self.rows[row])): yield Coordinate(row, col) def isMarked(self, coordinate): return bool(self.getValueAt(coordinate)) def getValueAt(self, coordinate): return self.rows[coordinate.row][coordinate.col] def mark(self, coordinate): self.rows[coordinate.row][coordinate.col] = True def toStrings(self): return [''.join(['O' if cell else '.' for cell in row]) for row in self.rows] def neighborsOf(self, row, col): center = Coordinate(row, col) return [self.getValueAt(coordinate) for coordinate in self.iterNeighborsOf(center)] def iterNeighborsOf(self, center): for cell in center._iterSquareAround(): if self._isInsideGrid(cell): if not cell.sameAs(center): yield cell def _isInsideGrid(self, cell): return (0 <= cell.row and cell.row < self.numRows and 0 <= cell.col and cell.col < self.numCols) @property def numRows(self): return len(self.rows) @property def numCols(self): return len(self.rows[0]) class Coordinate(object): def __init__(self, row, col): self.row = row self.col = col def _iterSquareAround(self): for rowIdx in xrange(-1, 2): for colIdx in xrange(-1, 2): yield Coordinate(self.row+rowIdx, self.col+colIdx) def sameAs(self, oth): return self.row == oth.row and self.col == oth.colclass Test_MineField(unittest.TestCase): def test_one_cell_with_no_mine_dig_and_win(self): m = MineField.fromString('.') m.dig(0,0) self.assertTrue(m.gameOver) self.assertTrue(m.win) def test_one_cell_with_one_mine_dig_and_loose(self): m = MineField.fromString('X') m.dig(0,0) self.assertTrue(m.gameOver) self.assertFalse(m.win) def test_4_cells_with_only_one_free_dig_and_find_only_one_dug(self): m = MineField.fromString('.X', 'XX') m.dig(0,0) self.assertEquals(m.dugGrid.toStrings(), ['O.', '..']) def test_4_cells_with_2_free_dig_one_and_find_both_dug(self): m = MineField.fromString('.X', '.X') m.dig(0,0) self.assertEquals(m.dugGrid.toStrings(), ['O.', 'O.']) def test_9_cells_with_vertical_tunnel_dig_first_and_find_others_dug(self): m = MineField.fromString('.X.', '.X.', '.X.') m.dig(0,0) self.assertEquals(m.dugGrid.toStrings(), ['O..', 'O..', 'O..']) def test_9_cells_with_circular_tunnel_dig_first_and_find_others_dug(self): m = MineField.fromString('.X.', '.X.', '...') m.dig(0,0) self.assertEquals(m.dugGrid.toStrings(), ['O.O', 'O.O', 'OOO']) class Test_Grid(unittest.TestCase): def test_grid_with_1_cell_neighbors_are_none(self): g = Grid([['a']]) self.assertEquals(g.neighborsOf(0,0), []) def test_grid_with_2_cells_neighbor_of_former_is_latter(self): g = Grid([['a', 'b']]) self.assertEquals(g.neighborsOf(0,0), ['b']) def test_grid_with_4_cells_neighbors_of_first_are_the_others(self): g = Grid([['a', 'b'], ['c', 'd']]) self.assertEquals(g.neighborsOf(0,0), list('bcd')) def test_grid_with_9_cells_neighbors_of_central_are_the_others(self): g = Grid([['a', 'b', 'c'], ['d', 'e', 'f'], ['g', 'h', 'i']]) self.assertEquals(g.neighborsOf(1,1), list('abcdfghi')) def test_grid_with_9_cells_neighbors_of_lower_right_are_the_others_3(self): g = Grid([['a', 'b', 'c'], ['d', 'e', 'f'], ['g', 'h', 'i']]) self.assertEquals(g.neighborsOf(2,2), list('efh')) if __name__ == "__main__": unittest.main()