def __generate_maze__(self, size): AbstractGenerator.__generate_maze__(self, size) """implement Prim's Algorithm""" self.mesh = Mesh(size) cell = self.mesh.choose_cell(self.random) self.queue = [cell] while len(self.queue) > 0: n = self.random.randint(0, len(self.queue) - 1) cell = self.queue[n] self.log.debug('looking at ' + str(cell)) wall = self.mesh.choose_wall(cell, self.random) if wall == cell.get_left(): neighbour = self.mesh.get_left_neighbour(cell) elif wall == cell.get_right(): neighbour = self.mesh.get_right_neighbour(cell) elif wall == cell.get_top(): neighbour = self.mesh.get_top_neighbour(cell) elif wall == cell.get_bottom(): neighbour = self.mesh.get_bottom_neighbour(cell) else: self.log.error('Invalid wall: ' + str(wall)) raise Exception('Invalid wall: ' + str(wall)) if cell.get_set() != neighbour.get_set(): self.log.debug('removing wall to ' + str(neighbour)) wall.remove() self.mesh.move_cell(neighbour.get_set(), cell.get_set()) self.queue.append(neighbour) else: self.__create_loops__(cell, neighbour, wall) if not self.mesh.has_neighbour_in_different_set(cell): self.log.debug('removing cell from queue') self.queue.remove(cell) return self.mesh
def test_solve_hard_maze(self): self.log.debug("test_solve_hard_maze") mesh = Mesh(4) # Openings mesh.matrix[0][2].topWall.removed = True mesh.matrix[1][3].rightWall.removed = True mesh.entrance = mesh.matrix[0][2] mesh.exit = mesh.matrix[1][3] # Maze mesh.matrix[0][0].rightWall.removed = True mesh.matrix[0][1].bottomWall.removed = True mesh.matrix[0][1].rightWall.removed = True mesh.matrix[0][3].bottomWall.removed = True mesh.matrix[1][0].bottomWall.removed = True mesh.matrix[1][0].rightWall.removed = True mesh.matrix[1][2].bottomWall.removed = True mesh.matrix[1][2].rightWall.removed = True mesh.matrix[2][0].rightWall.removed = True mesh.matrix[2][1].bottomWall.removed = True mesh.matrix[2][2].rightWall.removed = True mesh.matrix[2][3].bottomWall.removed = True mesh.matrix[3][0].rightWall.removed = True mesh.matrix[3][1].rightWall.removed = True mesh.matrix[3][2].rightWall.removed = True expected_path = [ mesh.matrix[0][2], mesh.matrix[0][1], mesh.matrix[1][1], mesh.matrix[1][0], mesh.matrix[2][0], mesh.matrix[2][1], mesh.matrix[3][1], mesh.matrix[3][2], mesh.matrix[3][3], mesh.matrix[2][3], mesh.matrix[2][2], mesh.matrix[1][2], mesh.matrix[1][3] ] actual_path = self.solver.solve_maze(mesh) tc.assertEqual(actual_path, expected_path)
def __generate_maze__(self, size): AbstractGenerator.__generate_maze__(self, size) """implement Recursive Division Algorithm""" self.mesh = Mesh(size, True) for i in range(0, size): # create boundary walls self.mesh.get_cell(i, 0).create_left() self.mesh.get_cell(i, size - 1).create_right() self.mesh.get_cell(0, i).create_top() self.mesh.get_cell(size - 1, i).create_bottom() self.__divideAndGenerate__(0, size - 1, 0, size - 1) return self.mesh
def __generate_maze__(self, size): AbstractGenerator.__generate_maze__(self, size) """implement Depth-first Search Algorithm""" self.mesh = Mesh(size) cell = self.mesh.choose_cell(self.random) self.stack = [] while self.mesh.has_multiple_sets(): if self.mesh.has_neighbour_in_different_set(cell): wall = self.mesh.choose_wall(cell, self.random) if wall == cell.get_left(): neighbour = self.mesh.get_left_neighbour(cell) if neighbour.get_set() != cell.get_set(): cell.remove_left() self.mesh.move_cell(neighbour.get_set(), cell.get_set()) self.stack.append(cell) cell = neighbour elif wall == cell.get_right(): neighbour = self.mesh.get_right_neighbour(cell) if neighbour.get_set() != cell.get_set(): cell.remove_right() self.mesh.move_cell(neighbour.get_set(), cell.get_set()) self.stack.append(cell) cell = neighbour elif wall == cell.get_top(): neighbour = self.mesh.get_top_neighbour(cell) if neighbour.get_set() != cell.get_set(): cell.remove_top() self.mesh.move_cell(neighbour.get_set(), cell.get_set()) self.stack.append(cell) cell = neighbour elif wall == cell.get_bottom(): neighbour = self.mesh.get_bottom_neighbour(cell) if neighbour.get_set() != cell.get_set(): cell.remove_bottom() self.mesh.move_cell(neighbour.get_set(), cell.get_set()) self.stack.append(cell) cell = neighbour else: self.log.error('Invalid wall') raise Exception('Invalid wall') else: cell = self.__handleDeadEnd__(cell) return self.mesh
def __generate_maze__(self, size): AbstractGenerator.__generate_maze__(self, size) """implement Binary Tree Algorithm""" mesh = Mesh(size) for i in range(1, size): mesh.get_cell(0, i).remove_left() mesh.get_cell(i, 0).remove_top() for i in range(1, size): for j in range(1, size): cell = mesh.get_cell(i, j) if self.random.random() > 0.5: cell.remove_left() else: cell.remove_top() self.__create_loops__(cell, size) return mesh
def __generate_maze__(self, size): AbstractGenerator.__generate_maze__(self, size) """ Kruskal's Algorithm""" mesh = Mesh(size) while mesh.has_multiple_sets(): cell = mesh.choose_cell(self.random) wall = mesh.choose_wall(cell, self.random) if wall == cell.get_left(): neighbour = mesh.get_left_neighbour(cell) elif wall == cell.get_right(): neighbour = mesh.get_right_neighbour(cell) elif wall == cell.get_top(): neighbour = mesh.get_top_neighbour(cell) elif wall == cell.get_bottom(): neighbour = mesh.get_bottom_neighbour(cell) else: self.log.error('Invalid wall') raise Exception('Invalid wall') if neighbour.get_set() != cell.get_set(): wall.remove() mesh.move_cell(neighbour.get_set(), cell.get_set()) else: self.__create_loops__(wall, size) return mesh
class MeshTest(unittest.TestCase): def setUp(self): self.log = logging.getLogger(__name__) self.mesh = Mesh(10) def test_MeshInit(self): self.log.debug("test_MeshInit") mesh = self.mesh self.assertEqual(mesh.size, 10, 'Size is wrong.') self.assertEqual(len(mesh.matrix), mesh.size, 'Length of matrix does not match size.') self.assertEqual(len(mesh.sets), 100, 'Wrong number of Sets found.') self.assertEqual(sum(len(cellSet) for cellSet in mesh.sets), len(set().union(*(set(cellSet) for cellSet in mesh.sets))), 'Not all Sets are distinct.') for i in range(0, mesh.size-1): for j in range(0, mesh.size): self.assertEqual(mesh.matrix[i][j].get_bottom(), mesh.matrix[i + 1][j].get_top(), 'Adjacent cells [' + str(i) + ',' + str(j) + '] and [' + str(i+1) + ',' + str(j) + '] do not share a horizontal wall.') for i in range(0, mesh.size): for j in range(0, mesh.size-1): self.assertEqual(mesh.matrix[i][j].get_right(), mesh.matrix[i][j + 1].get_left(), 'Adjacent cells [' + str(i) + ',' + str(j) + '] and [' + str(i) + ',' + str(j+1) + '] do not share a vertical wall.') for i in range(0, mesh.size): self.assertFalse(mesh.matrix[0][i].get_top().is_removed(), 'Mesh has an entry.') self.assertFalse(mesh.matrix[mesh.size - 1][i].get_bottom().is_removed(), 'Mesh has an entry.') self.assertFalse(mesh.matrix[i][0].get_left().is_removed(), 'Mesh has an entry.') self.assertFalse(mesh.matrix[i][mesh.size - 1].get_right().is_removed(), 'Mesh has an entry.') def test_getSize(self): self.log.debug("test_getSize") self.assertEqual(self.mesh.get_size(), self.mesh.size, 'get_size returns wrong value.') def test_getCell(self): self.log.debug("test_getCell") self.assertEqual(self.mesh.get_cell(3, 7), self.mesh.matrix[3][7], 'get_cell returns wrong value.') def test_getLeftNeighbour(self): self.log.debug("test_getLeftNeighbour") cell = self.mesh.matrix[3][7] self.assertEqual(self.mesh.get_left_neighbour(cell), self.mesh.matrix[cell.get_x()][cell.get_y() - 1], 'get_left_neighbour returns wrong value.') def test_getRightNeighbour(self): self.log.debug("test_getRightNeighbour") cell = self.mesh.matrix[3][7] self.assertEqual(self.mesh.get_right_neighbour(cell), self.mesh.matrix[cell.get_x()][cell.get_y() + 1], 'get_right_neighbour returns wrong value.') def test_getTopNeighbour(self): self.log.debug("test_getTopNeighbour") cell = self.mesh.matrix[3][7] self.assertEqual(self.mesh.get_top_neighbour(cell), self.mesh.matrix[cell.get_x() - 1][cell.get_y()], 'get_top_neighbour returns wrong value.') def test_getBottomNeighbour(self): self.log.debug("test_getBottomNeighbour") cell = self.mesh.matrix[3][7] self.assertEqual(self.mesh.get_bottom_neighbour(cell), self.mesh.matrix[cell.get_x() + 1][cell.get_y()], 'get_bottom_neighbour returns wrong value.') def test_moveCell(self): self.log.debug("test_moveCell") cell1 = self.mesh.matrix[3][7] set1 = cell1.set cell2 = self.mesh.matrix[7][3] set2 = cell2.set self.assertNotEqual(set1, set2, 'Cells have same Set.') self.mesh.move_cell(set1, set2) self.assertEqual(cell1.set, cell2.set, 'Cells do not have same Set.') self.assertEqual(cell1.set, set2, 'Cells were moved into wrong Set.') self.assertIn(cell1, self.mesh.sets[set2], 'Set does not contain Cell.') self.assertIn(cell2, self.mesh.sets[set2], 'Set does not contain Cell.') self.assertNotIn(cell1, self.mesh.sets[set1], 'Set does contain Cell.') self.assertNotIn(cell2, self.mesh.sets[set1], 'Set does contain Cell.') self.assertEqual(len(self.mesh.sets[set1]), 0, 'Set still contains Cells.') def test_checkSets(self): self.log.debug("test_checkSets") self.assertTrue(self.mesh.has_multiple_sets(), 'Mesh has only one non-empty Set.') for i in range(self.mesh.size**2): self.mesh.move_cell(i, 0) self.assertFalse(self.mesh.has_multiple_sets(), 'Not all Cells are in the same Set.') def test_chooseCellSuccess(self): self.log.debug("test_chooseCellSuccess") cell = self.mesh.choose_cell() self.assertTrue(self.mesh.has_neighbour_in_different_set(cell), 'Cell without Wall to a neighbour has been chosen.') def test_chooseCellFail(self): self.log.debug("test_chooseCellFail") for i in range(100): self.mesh.move_cell(i, 0) cell = self.mesh.choose_cell() self.assertIsNone(cell, 'A Cell could be chosen.') def test_isBorder(self): self.log.debug("test_isBorder") cell37 = self.mesh.matrix[3][7] self.assertFalse(self.mesh.is_border(cell37, cell37.topWall), 'Cell is border.') self.assertFalse(self.mesh.is_border(cell37, cell37.leftWall), 'Cell is border.') self.assertFalse(self.mesh.is_border(cell37, cell37.bottomWall), 'Cell is border.') self.assertFalse(self.mesh.is_border(cell37, cell37.rightWall), 'Cell is border.') cell39 = self.mesh.matrix[3][9] self.assertTrue(self.mesh.is_border(cell39, cell39.rightWall), 'Cell is not border.') cell30 = self.mesh.matrix[3][0] self.assertTrue(self.mesh.is_border(cell30, cell30.leftWall), 'Cell is not border.') cell07 = self.mesh.matrix[0][7] self.assertTrue(self.mesh.is_border(cell07, cell07.topWall), 'Cell is not border.') cell97 = self.mesh.matrix[9][7] self.assertTrue(self.mesh.is_border(cell97, cell97.bottomWall), 'Cell is not border.') def test_isLegitNeighbour(self): self.log.debug("test_isLegitNeighbour") self.assertTrue(self.mesh.has_neighbour_in_different_set(self.mesh.matrix[3][7]), 'Cell has no neighbour in different Set.') self.mesh.move_cell(0, 1) self.mesh.move_cell(10, 1) self.assertFalse(self.mesh.has_neighbour_in_different_set(self.mesh.matrix[0][0]), 'Cells has neighbour in different Set.') def test_setCustomOpening(self): self.log.debug("test_setCustomOpening") self.assertRaises(IndexError, self.mesh.set_custom_opening, 10, 9) self.mesh.set_custom_opening(0, 0, True) self.assertTrue(self.mesh.matrix[0][0].get_top().is_removed(), 'Cell (0,0) is not removed.') def test_setRandomTopEntrance(self): self.log.debug("test_setRandomTopEntrance") self.mesh.set_random_top_entrance() found = False for i in range(0, 10): if self.mesh.matrix[0][i].get_top().is_removed(): found = True if not found: self.assertTrue(False, 'No top entrance found') def test_setRandomLeftEntrance(self): self.log.debug("test_setRandomLeftEntrance") self.mesh.set_random_left_entrance() found = False for i in range(0, 10): if self.mesh.matrix[i][0].get_left().is_removed(): found = True if not found: self.assertTrue(False, 'No left entrance found') def test_setRandomBottomExit(self): self.log.debug("test_setRandomBottomExit") self.mesh.set_random_bottom_exit() found = False for i in range(0, 10): if self.mesh.matrix[9][i].get_bottom().is_removed(): found = True if not found: self.assertTrue(False, 'No bottom exit found') def test_setRandomRightExit(self): self.log.debug("test_setRandomRightExit") self.mesh.set_random_right_exit() found = False for i in range(0, 10): if self.mesh.matrix[i][9].get_right().is_removed(): found = True if not found: self.assertTrue(False, 'No right exit found') def test_clearEntrance(self): self.log.debug("test_clearEntrance") self.mesh.set_custom_opening(0, 0) self.mesh.clear_entrance() self.assertFalse(self.mesh.matrix[0][0].get_top().is_removed(), 'Entrance was not cleared') self.assertFalse(self.mesh.matrix[0][0].get_left().is_removed(), 'Entrance was not cleared') def test_clearExit(self): self.log.debug("test_clearExit") self.mesh.set_custom_opening(9, 9) self.mesh.clear_exit() self.assertFalse(self.mesh.matrix[9][9].get_bottom().is_removed(), 'Exit was not cleared') self.assertFalse(self.mesh.matrix[9][9].get_right().is_removed(), 'Exit was not cleared') def test_getEntrance(self): self.log.debug("test_getEntrance") self.mesh.set_custom_opening(0, 0) self.assertEqual(self.mesh.get_entrance(), self.mesh.matrix[0][0], 'get_entrance returned wrong value') def test_getExit(self): self.log.debug("test_getExit") self.mesh.set_custom_opening(9, 9) self.assertEqual(self.mesh.get_exit(), self.mesh.matrix[9][9], 'get_exit returned wrong value') def test_chooseWall(self): self.log.debug("test_chooseWall") cell = self.mesh.matrix[0][5] cell.remove_left() wall = self.mesh.choose_wall(cell) self.assertIsNotNone(wall, 'No wall was chosen') self.assertNotEqual(wall, cell.get_left(), 'A removed wall was chosen') self.assertNotEqual(wall, cell.get_top, 'A border wall was chosen') cell.remove_right() cell.remove_bottom() wall = self.mesh.choose_wall(cell) self.assertIsNone(wall, 'A (removed or border) wall was chosen')
def setUp(self): self.log = logging.getLogger(__name__) self.mesh = Mesh(10)
def test_no_exit(self): self.log.debug("test_no_exit") mesh = Mesh(5) mesh.entrance = mesh.matrix[0][0] with self.assertRaises(Exception): self.solver.solve_maze(mesh)
class RecursiveDivisionGenerator(AbstractGenerator): def __init__(self): AbstractGenerator.__init__(self) self.log = logging.getLogger(__name__) def __generate_maze__(self, size): AbstractGenerator.__generate_maze__(self, size) """implement Recursive Division Algorithm""" self.mesh = Mesh(size, True) for i in range(0, size): # create boundary walls self.mesh.get_cell(i, 0).create_left() self.mesh.get_cell(i, size - 1).create_right() self.mesh.get_cell(0, i).create_top() self.mesh.get_cell(size - 1, i).create_bottom() self.__divideAndGenerate__(0, size - 1, 0, size - 1) return self.mesh def __divideAndGenerate__(self, left_border, right_border, top_border, bottom_border): if (left_border != right_border) and (top_border != bottom_border): column = self.random.randint(left_border + 1, right_border) row = self.random.randint(top_border + 1, bottom_border) for i in range(left_border, right_border + 1): self.mesh.get_cell(row, i).create_top() for i in range(top_border, bottom_border + 1): self.mesh.get_cell(i, column).create_left() left_hole = self.random.randint(left_border, column - 1) right_hole = self.random.randint(column, right_border) top_hole = self.random.randint(top_border, row - 1) bottom_hole = self.random.randint(row, bottom_border) make_hole_list = [ self.__get_make_horizontal_hole__(row, left_hole), self.__get_make_horizontal_hole__(row, right_hole), self.__get_make_vertical_hole__(top_hole, column), self.__get_make_vertical_hole__(bottom_hole, column) ] for i in range(0, 3): choice = self.random.randint(0, len(make_hole_list) - 1) make_hole_list[choice]() make_hole_list.remove(make_hole_list[choice]) self.__create_loops__(make_hole_list) self.__divideAndGenerate__(left_border, column - 1, top_border, row - 1) self.__divideAndGenerate__(column, right_border, top_border, row - 1) self.__divideAndGenerate__(left_border, column - 1, row, bottom_border) self.__divideAndGenerate__(column, right_border, row, bottom_border) def __get_make_vertical_hole__(self, column, row): return self.mesh.get_cell(column, row).remove_left def __get_make_horizontal_hole__(self, column, row): return self.mesh.get_cell(column, row).remove_top def __create_loops__(self, function_list): pass