rendered paste bodyimport unittestclass MineField(object): def __init__(self, rows): self.mineMap = Grid(rows) self.digMap = Grid.empty(self.mineMap.numRows, self.mineMap.numCols) self.gameOver = False def dig(self, cell): if self._thereIsAMineAt(cell): self._loose() else: self._startDiggingAt(cell) self._win() def _loose(self): self.gameOver = True self.won = False def _startDiggingAt(self, cell): self.digMap.mark(cell) for cell in self._freeNeighborsOf(cell): self._startDiggingIfNotDugAlready(cell) def _freeNeighborsOf(self, cell): for cell in self.mineMap.neighborsOf(cell): if self._isFree(cell): yield cell def _startDiggingIfNotDugAlready(self, cell): if not self.digMap.isMarked(cell): self._startDiggingAt(cell) def _win(self): self.gameOver = True self.won = True def _isFree(self, cell): return not self._thereIsAMineAt(cell) def _thereIsAMineAt(self, cell): return self.mineMap.isMarked(cell) class Grid(object): @classmethod def empty(cls, numRows, numCols): return cls([[False]*numCols for _ in xrange(numRows)]) def __init__(self, rows): self.rows = rows def mark(self, cell): self.rows[cell.row][cell.col] = True def isMarked(self, cell): return self.rows[cell.row][cell.col] def _isCellInside(self, cell): return (cell.row >= 0 and cell.row < self.numRows and cell.col >= 0 and cell.col < self.numCols) @property def numRows(self): return len(self.rows) @property def numCols(self): return len(self.rows[0]) def neighborsOf(self, cell): for neighborCell in cell.iterateNeighbors(): if self._isCellInside(neighborCell): yield neighborCell class Cell(object): def __init__(self, row, col): self.row = row self.col = col def iterateNeighbors(self): yield Cell(self.row-1, self.col) yield Cell(self.row, self.col+1) yield Cell(self.row+1, self.col) yield Cell(self.row, self.col-1)def mineField(*rowsText): return MineField([[char == 'X' for char in rowText] for rowText in rowsText])class Minefield_TestCase(unittest.TestCase): def assertDugCells(self, mineField, *expectedDugCellsText): dugCellsText = [''.join(['O' if dugCell else '.' for dugCell in row]) for row in mineField.digMap.rows] if dugCellsText != list(expectedDugCellsText): self.fail('expected:\n%s\nfound:\n%s' % ('\n'.join(expectedDugCellsText), '\n'.join(dugCellsText))) def test_havingOneCellWithNoMine_Then_Win(self): f = mineField('.') f.dig(Cell(0,0)) self.assertTrue(f.gameOver) self.assertTrue(f.won) def test_havingOneCellWithMine_Then_Loose(self): f = mineField('X') f.dig(Cell(0,0)) self.assertTrue(f.gameOver) self.assertFalse(f.won) def test_havingTwoCellsWithOneMine_Then_Win(self): f = mineField('.X') f.dig(Cell(0,0)) self.assertTrue(f.gameOver) self.assertTrue(f.won) def _test_havingThreeCellsWithOneMine_Then_KeepGoing(self): f = mineField('.X.') f.dig(Cell(0,0)) self.assertFalse(f.gameOver) def test_havingNotDug_Then_NoUncoveredCells(self): f = mineField('.X.') self.assertDugCells(f, '...') def test_havingDugOneCellWithNoMine_Then_CellIsUncovered(self): f = mineField('.X.') f.dig(Cell(0,0)) self.assertDugCells(f, 'O..') def test_havingOneCellOnly_Then_NoNeighbors(self): f = mineField('.') self.assertEquals(len(list(f.mineMap.neighborsOf(Cell(0,0)))), 0) def test_havingTwoCellsHorizontal_Then_OneNeighbor(self): f = mineField('..') self.assertEquals(len(list(f.mineMap.neighborsOf(Cell(0,0)))), 1) def test_havingTwoCellsVertical_Then_OneNeighbor(self): f = mineField('.', '.') self.assertEquals(len(list(f.mineMap.neighborsOf(Cell(0,0)))), 1) def test_having9CellsSquare_Then_4Neighbor(self): f = mineField('...', '...', '...') self.assertEquals(len(list(f.mineMap.neighborsOf(Cell(1,1)))), 4) def test_having9CellsSquareWithMinesInCornerDigCenter_Then_All5CellsDug(self): f = mineField('X.X', '...', 'X.X') f.dig(Cell(1,1)) self.assertDugCells(f, '.O.', 'OOO', '.O.', ) def test_having9CellsSquareAnd1Mine_Then_3FreeNeighbor(self): f = mineField('...', '...', '.X.') self.assertEquals(len(list(f._freeNeighborsOf(Cell(1,1)))), 3) def test_having9CellsSquareAnd2Mines_Then_2FreeNeighbor(self): f = mineField('...', 'X..', '.X.') self.assertEquals(len(list(f._freeNeighborsOf(Cell(1,1)))), 2) def test_having9CellsSquareWithSomeMineDigCenter_Then_SomeCellsDug(self): f = mineField('XX.', '..X', 'X.X') f.dig(Cell(1,1)) self.assertDugCells(f, '...', 'OO.', '.O.', ) def test_having9CellsSquareWithSomeMineDigLeftTop_Then_SomeCellsDug(self): f = mineField('.X.', '.XX', 'X..') f.dig(Cell(0,0)) self.assertDugCells(f, 'O..', 'O..', '...', ) def test_having9CellsSquareWithAPassageDigLeftTop_Then_AllPassageDug(self): f = mineField('.X.', '.XX', '...') f.dig(Cell(0,0)) self.assertDugCells(f, 'O..', 'O..', 'OOO', ) if __name__ == '__main__': unittest.main()