class PrimGenerator(MazeGenerator):
    used = []
    walls = [Cell(2, 1), Cell(1, 2)]

    @classmethod
    def get_divided(cls, cell, maze):
        # записывает в divided непосещённые клетки, соседствующие со стеной
        divided = []
        x = cell.x
        y = cell.y
        if cls.used[x + 1][y] == 0 and maze.matrix[x + 1][y] == State.space:
            divided.append(Cell(x + 1, y))
        if cls.used[x][y + 1] == 0 and maze.matrix[x][y + 1] == State.space:
            divided.append(Cell(x, y + 1))
        if cls.used[x - 1][y] == 0 and maze.matrix[x - 1][y] == State.space:
            divided.append(Cell(x - 1, y))
        if cls.used[x][y - 1] == 0 and maze.matrix[x][y - 1] == State.space:
            divided.append(Cell(x, y - 1))
        return divided

    @classmethod
    def add_walls(cls, cell, maze):
        # добавляет в walls внутренние стены лабиринта, соседние с cell
        x = cell.x
        y = cell.y
        if x + 1 < maze.height - 1 and maze.matrix[x + 1][y] == State.wall:
            cls.walls.append(Cell(x + 1, y))
        if y + 1 < maze.width - 1 and maze.matrix[x][y + 1] == State.wall:
            cls.walls.append(Cell(x, y + 1))
        if x - 1 >= 1 and maze.matrix[x - 1][y] == State.wall:
            cls.walls.append(Cell(x - 1, y))
        if y - 1 >= 1 and maze.matrix[x][y - 1] == State.wall:
            cls.walls.append(Cell(x, y - 1))

    @classmethod
    @abstractmethod
    def create(cls, width, height, rand):
        maze = Maze(width, height)
        for i in range(maze.height):
            cls.used.append([0 for i in range(maze.width)])
        cls.used[1][1] = 1

        while len(cls.walls) > 0:
            num = random.randint(0, len(cls.walls) - 1)
            divided = cls.get_divided(cls.walls[num], maze)
            if len(divided) == 1:
                cls.used[divided[0].x][divided[0].y] = 1
                maze.set(cls.walls[num], State.space)
                cls.add_walls(divided[0], maze)
            divided.clear()
            cls.walls.pop(num)

        cls.used = []
        cls.walls = [Cell(2, 1), Cell(1, 2)]
        maze.set_doors(rand)
        return maze
 def add_walls(cls, cell, maze):
     # добавляет в walls внутренние стены лабиринта, соседние с cell
     x = cell.x
     y = cell.y
     if x + 1 < maze.height - 1 and maze.matrix[x + 1][y] == State.wall:
         cls.walls.append(Cell(x + 1, y))
     if y + 1 < maze.width - 1 and maze.matrix[x][y + 1] == State.wall:
         cls.walls.append(Cell(x, y + 1))
     if x - 1 >= 1 and maze.matrix[x - 1][y] == State.wall:
         cls.walls.append(Cell(x - 1, y))
     if y - 1 >= 1 and maze.matrix[x][y - 1] == State.wall:
         cls.walls.append(Cell(x, y - 1))
Example #3
0
def get_next(cell, maze):
    # записывает в next соседние с cell пустые клетки
    next = []
    x = cell.x
    y = cell.y
    if x + 1 < maze.height and maze.matrix[x + 1][y] == State.space:
        next.append(Cell(x + 1, y))
    if y + 1 < maze.width and maze.matrix[x][y + 1] == State.space:
        next.append(Cell(x, y + 1))
    if x - 1 >= 0 and maze.matrix[x - 1][y] == State.space:
        next.append(Cell(x - 1, y))
    if y - 1 >= 0 and maze.matrix[x][y - 1] == State.space:
        next.append(Cell(x, y - 1))
    return next
 def get_divided(cls, cell, maze):
     # записывает в divided непосещённые клетки, соседствующие со стеной
     divided = []
     x = cell.x
     y = cell.y
     if cls.used[x + 1][y] == 0 and maze.matrix[x + 1][y] == State.space:
         divided.append(Cell(x + 1, y))
     if cls.used[x][y + 1] == 0 and maze.matrix[x][y + 1] == State.space:
         divided.append(Cell(x, y + 1))
     if cls.used[x - 1][y] == 0 and maze.matrix[x - 1][y] == State.space:
         divided.append(Cell(x - 1, y))
     if cls.used[x][y - 1] == 0 and maze.matrix[x][y - 1] == State.space:
         divided.append(Cell(x, y - 1))
     return divided
Example #5
0
 def get_neighbours(cls, cell, width, height):
     # записывает в neighbours непосещённых соседей cell
     neighbours = []
     x = cell.x
     y = cell.y
     if x + 2 < height and cls.used[x + 2][y] == 0:
         neighbours.append(Cell(x + 2, y))
     if y + 2 < width and cls.used[x][y + 2] == 0:
         neighbours.append(Cell(x, y + 2))
     if x - 2 >= 0 and cls.used[x - 2][y] == 0:
         neighbours.append(Cell(x - 2, y))
     if y - 2 >= 0 and cls.used[x][y - 2] == 0:
         neighbours.append(Cell(x, y - 2))
     return neighbours
Example #6
0
def solution(maze: Maze):
    # решение лабиринта методом bfs
    maze1 = copy.deepcopy(maze)
    if maze1.entry == maze1.exit:
        maze1.set(maze.entry, State.way)
        return maze1

    parents = []
    for i in range(maze1.height):
        parents.append([Cell(-2, -2) for i in range(maze1.width)])
    parents[maze1.entry.x][maze1.entry.y] = Cell(-1, -1)

    used = []
    for i in range(maze1.height):
        used.append([0 for i in range(maze1.width)])

    queue = deque()
    queue.appendleft(maze1.entry)
    used[maze.entry.x][maze.entry.y] = 1

    while len(queue) > 0:
        curr = queue.pop()
        if curr == maze1.exit:
            prev = parents[curr.x][curr.y]
            maze1.set(curr, State.way)
            while not prev == maze1.entry:
                maze1.set(prev, State.way)
                curr = prev
                prev = parents[curr.x][curr.y]
            maze1.set(maze1.entry, State.way)
            break

        else:
            next = get_next(curr, maze1)
            for i in next:
                if used[i.x][i.y] == 0 and parents[curr.x][curr.y] != i:
                    parents[i.x][i.y] = curr
                    queue.appendleft(i)
                    used[i.x][i.y] = 1
            next.clear()

    if not maze1.get(maze1.exit) == State.way:
        return False
    return maze1
    def create(cls, width, height, rand):
        maze = Maze(width, height)
        for i in range(maze.height):
            cls.used.append([0 for i in range(maze.width)])
        cls.used[1][1] = 1

        while len(cls.walls) > 0:
            num = random.randint(0, len(cls.walls) - 1)
            divided = cls.get_divided(cls.walls[num], maze)
            if len(divided) == 1:
                cls.used[divided[0].x][divided[0].y] = 1
                maze.set(cls.walls[num], State.space)
                cls.add_walls(divided[0], maze)
            divided.clear()
            cls.walls.pop(num)

        cls.used = []
        cls.walls = [Cell(2, 1), Cell(1, 2)]
        maze.set_doors(rand)
        return maze
Example #8
0
 def create(cls, width, height, rand):
     maze = Maze(width, height)
     stack = [Cell(1, 1)]
     for i in range(maze.height):
         cls.used.append([0 for i in range(maze.width)])
     cls.used[1][1] = 1
     curr = Cell(1, 1)
     while len(stack) > 0:
         neighbours = cls.get_neighbours(curr, maze.width, maze.height)
         if len(neighbours) > 0:
             stack.append(curr)
             k = neighbours[random.randint(0, len(neighbours) - 1)]
             new = Cell((curr.x + k.x) // 2,
                        (curr.y + k.y) // 2)  # стена между двумя клетками
             maze.set(new, State.space)
             cls.used[k.x][k.y] = 1
             curr = k
         else:
             curr = stack.pop()
     maze.set_doors(rand)
     cls.used = []
     return maze