At an interview, I was asked to build a python program, using TDD, which would output the results of a minesweeper game. Not a fully functional game, just a small program that would take an array of bomb locations and print out a map of the board with all values exposed.
So, if you have a 3×3 board, and there is a bomb in each corner, it would print out something like this:
x 2 x
2 4 2
x 2 x
Or if you have a 3×3 board and there is only a bomb in the upper left corner, it would print out something like this:
x 1 0
1 1 0
0 0 0
I did not complete the task in the allotted time, but it was a fun programming exercise and I hope illuminating to the interviewers. I actually took it home and finished it up. Here’s the full text of the program:
class Board:
def __init__(self, size = 1, bomblocations = []):
self._size = size
self._bomblocations = bomblocations
def size(self):
return self._size
def _bombLocation(self,location):
for onebomblocation in self._bomblocations:
if onebomblocation == location:
return 'x'
def _isOnBoard(self,location):
if location[0] =self._size:
return False
if location[1] >=self._size:
return False
return True
def whatsAt(self,location):
if self._bombLocation(location) == 'x':
return 'x'
if not self._isOnBoard(location):
return None
return self._numberOfBombsAdjacent(location)
def _numberOfBombsAdjacent(self,location):
bombcount = 0
# change x, then y
currx = location[0]
curry = location[1]
for xincrement in [-1,0,1]:
xtotest = currx + xincrement
for yincrement in [-1,0,1]:
ytotest = curry + yincrement
#print 'testing: '+ str(xtotest) + ', '+str(ytotest)+ ', '+str(bombcount)
if not self._isOnBoard([xtotest,ytotest]):
continue
if self._bombLocation([xtotest,ytotest]) == 'x':
bombcount += 1
return bombcount
def printBoard(self):
x = 0
while x < self._size:
y = 0
while y < self._size:
print self.whatsAt([x,y]),
y += 1
x += 1
print
def main():
board = Board(15,[[0,1],[1,2],[2,4],[2,5],[3,5],[5,5]])
board.printBoard()
if __name__ == "__main__":
main()
And the tests:
import unittest
import app
class TestApp(unittest.TestCase):
def setUp(self):
pass
def test_board_creation(self):
newboard = app.Board()
self.assertIsNotNone(newboard)
def test_default_board_size(self):
newboard = app.Board()
self.assertEqual(1, newboard.size())
def test_constructor_board_size(self):
newboard = app.Board(3)
self.assertEqual(3, newboard.size())
def test_board_with_bomb(self):
newboard = app.Board(3,[[0,0]])
self.assertEqual('x', newboard.whatsAt([0,0]))
def test_board_with_n_bombs(self):
newboard = app.Board(4,[[0,0],[3,3]])
self.assertEqual('x', newboard.whatsAt([0,0]))
self.assertEqual('x', newboard.whatsAt([3,3]))
def test_board_with_bomb_check_other_spaces_separated_bombs(self):
newboard = app.Board(4,[[0,0],[3,3]])
self.assertEqual(1, newboard.whatsAt([0,1]))
self.assertEqual(1, newboard.whatsAt([1,0]))
self.assertEqual(1, newboard.whatsAt([1,1]))
self.assertEqual(0, newboard.whatsAt([1,2]))
self.assertEqual(0, newboard.whatsAt([2,1]))
self.assertEqual(1, newboard.whatsAt([3,2]))
self.assertEqual(1, newboard.whatsAt([2,3]))
self.assertEqual(1, newboard.whatsAt([2,2]))
def test_check_other_spaces_contiguous_bombs(self):
newboard = app.Board(4,[[0,1],[0,0]])
self.assertEqual(1, newboard.whatsAt([0,2]))
self.assertEqual(2, newboard.whatsAt([1,0]))
self.assertEqual(0, newboard.whatsAt([2,1]))
def test_off_the_board(self):
newboard = app.Board(3,[[0,0],[1,2]])
self.assertEqual(None, newboard.whatsAt([3,3]))
This was written in python 2.7, and reminded me of the pleasure of small, from the ground up software (as opposed to gluing together libraries to achieve business objectives, which is what I do a lot of nowadays).