Пример #1
0
 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
Пример #2
0
 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)
Пример #3
0
 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
Пример #4
0
 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
Пример #5
0
 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
Пример #6
0
 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
Пример #7
0
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')
Пример #8
0
 def setUp(self):
     self.log = logging.getLogger(__name__)
     self.mesh = Mesh(10)
Пример #9
0
 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)
Пример #10
0
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