我正在尝试使用Eller's algorithm创建一个迷宫。互联网上关于此特定算法的信息不多。所以我在使用该算法时遇到了一些困难,因为有些事情我还不太了解。但是无论如何,这就是我现在拥有的:
class Cell:
def __init__(self, row, col, number, right_wall, bottom_wall):
self.row = row
self.col = col
self.number = number # defines which set this block is in
self.right_wall = right_wall
self.bottom_wall= bottom_wall
# every block includes 5x5 px white space + 1px on it's left and 1px on it's bottom for walls (if the block has ones)
def create_block(row, col, right_wall, bottom_wall):
for i in range(row-2, row+4): # since the path is 5px wide
for j in range(col-2, col+4): # i go to a central pixel of block's white space and make it thick
maze[i, j] = [255, 255, 255] # in other words i draw 2px border around central pixel
if right_wall: # if the block has wall on it's right
create_right_wall(row, col, 1) # draw right wall with a function
if bottom_wall: # if the block has wall on it's bottom
create_bottom_wall(row, col ,1) # draw bottom wall with a function
def create_right_wall(row, col, color):
if color == 0: # if color parameter = 0
for i in range(row-2, row+4):
maze[i, col+3] = [0, 0, 0] # I draw (create) black wall
else:
for i in range(row-2, row+4):
maze[i, col+3] = [255, 255, 255] # I draw white wall (if I need to delete a wall)
def create_bottom_wall(row, col, color):
if color == 0:
for i in range(col-2, col+4):
maze[row+3, i] = [0, 0, 0]
if row + 4 < maze_height and maze[row+4, col-3][0] == 0: # sometimes there's 1px gap between bottom walls
maze[row+3, col-3] = [0, 0, 0] # so I fill it with black pixel
else:
for i in range(col-2, col+4):
maze[row+3, i] = [255, 255, 255] # draws white wall (deleting wall)
def creating():
current_point = [3, 3] # where the top-left block appears ([3,3] is for the block's center)
set_count = 1 # to have unique set numbers, it increases every time after it has been used
for row in range(height): # going from top to bottom
# I print some unnecessary information just to know what's happening
print("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - row", row) # current row being created
if row == 0: # if it's the first row
for col in range(width):
create_block(current_point[0], current_point[1], False, False)
blocks[row].append(Cell(current_point[0], current_point[1], set_count, False, False))
set_count += 1 # since the set number has been used, the next block will have another one
current_point[1] += 6 # the center of the next block is 6px away from the center of the current one
elif row == height - 1: # if it's the last row
for i in range(width):
create_block(current_point[0], current_point[1], False, False)
blocks[row].append(Cell(current_point[0], current_point[1], blocks[row-1][i].number, False, True))
current_point[1] += 6
# I don't know why I do this. Just trying to create the last line correctly
if (not blocks[row-1][i].bottom_wall and not blocks[row-1][i + 1].bottom_wall) and \
(blocks[row-1][i].number == blocks[row-1][i + 1].number):
create_right_wall(blocks[row][i].row, blocks[row][i].col, 0)
break # since it's the last row, don't do anything else
else:
for col in range(width):
create_block(current_point[0], current_point[1], False, False)
print("block on top has set:", blocks[row-1][col].number, end=" ")
if blocks[row-1][col].bottom_wall: # if upper block has bottom wall
blocks[row].append(Cell(current_point[0], current_point[1], set_count, False, False))
print("upper block has a bottom wall, so set for the current block is", set_count)
set_count += 1
else: # if not, the current block's set will be the same as for the upper one
blocks[row].append(Cell(current_point[0], current_point[1],
blocks[row-1][col].number, False, False))
print("current block set", blocks[row-1][col].number)
current_point[1] += 6
# just to show set numbers for current row
for i in blocks[row]:
print(i.number, end=" ")
# putting a wall between blocks of the same set (we don't want to have loops in our maze)
for i in range(len(blocks[row]) - 1):
if blocks[row][i].number == blocks[row][i+1].number:
blocks[row][i].right_wall = True
create_right_wall(blocks[row][i].row, blocks[row][i].col, 0)
print("put a wall between", i+1, "и", i+2, "because", blocks[row][i].number, "=",\
blocks[row][i+1].number)
for i in range(len(blocks[row]) - 1):
if random.choice([0, 1]) == 0 and blocks[row][i].number != blocks[row][i+1].number:
blocks[row][i + 1].number = blocks[row][i].number
print("connect block", i + 1, "and", i + 2)
else:
blocks[row][i].right_wall = True
create_right_wall(blocks[row][i].row, blocks[row][i].col, 0)
# to know what set nu,bers we have in the current row
sets_in_row = []
for i in blocks[row]:
print(i.number, end=" ")
sets_in_row.append(i.number)
sets_in_row = sorted(set(sets_in_row), key=lambda x: sets_in_row.index(x))
print(sets_in_row)
current_bl = 0 # current block in a
for mn in sets_in_row: # for every set number in a row
current_mn_length = sum([p.number == mn for p in blocks[row]]) # how many blocks has this set number
if current_mn_length > 1: # if the current set has more than 1 block
quantity = random.randrange(1, current_mn_length) # random number of bottom walls
# whick blocks in the current set will have a bottom wall
bloxxxx = random.sample(list(range(current_bl, current_bl + current_mn_length)), quantity)
# just to know how it's going
print("\nblock:")
for y in range(current_bl, current_bl + current_mn_length):
print("pos:", y + 1, end=" ")
print(" num:", blocks[row][y].number,)
print("bottom walls for")
for i in bloxxxx:
print(i+1, end=" ")
print()
for b in bloxxxx:
blocks[row][b].bottom_wall = True
create_bottom_wall(blocks[row][b].row, blocks[row][b].col, 0)
current_bl += current_mn_length
else:
print("\n set length of", current_bl + 1, "=", current_mn_length, "so no bottom wall\n")
current_bl += current_mn_length
current_point[0] += 6 # go to the center of the next row block
current_point[1] = 3 # go to the center of the first block of the next row
while True:
width = int(input("Width: "))
height = int(input("height: "))
maze_width = width * 6 + 1
maze_height = height * 6 + 1
maze = np.full((maze_height, maze_width, 3), 0, dtype=np.uint8)
paths = []
all_positions = width * height
break
blocks = [[] for h in range(height)]
creating()
for h in range(maze_height):
maze[h][maze_width-1] = [0, 0, 0]
for w in range(maze_width):
maze[maze_height-1][w] = [0, 0, 0]
img = Image.fromarray(maze, 'RGB')
img.save('maze.png')
img.show()
我试图解释每一行,因此您可以了解我的代码中发生了什么。我知道我有很多不必要的代码。那是因为我尝试了多种方法来生成正确的迷宫。
问题是迷宫不一定总能正确产生。例如,这个有循环。但这不应该。
看看这个 这个有循环和ISOLATED块。那是因为设置了数字。在此迷宫中,第二行具有以下设置:
在我随机连接块之后,2的行已被22隔开。因此第二个块不是集合编号2中唯一的一个。
请帮助我修复代码。如果您对我的代码有任何疑问,我会尽力为您提供更多信息。