Python 与Eller的问题';s算法-迷宫生成

Python 与Eller的问题';s算法-迷宫生成,python,python-3.x,maze,Python,Python 3.x,Maze,我正在尝试使用创建一个迷宫。互联网上没有太多关于这种特殊算法的信息。所以我对这个算法有一些困难,因为有些事情我不完全理解。但无论如何,这就是我现在所拥有的: class Cell: def __init__(self, row, col, number, right_wall, bottom_wall): self.row = row self.col = col self.number = number # defines whic

我正在尝试使用创建一个迷宫。互联网上没有太多关于这种特殊算法的信息。所以我对这个算法有一些困难,因为有些事情我不完全理解。但无论如何,这就是我现在所拥有的:

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()
类单元格:
定义初始(自身、行、列、编号、右墙、下墙):
self.row=行
self.col=col
self.number=number#定义此块所在的集合
self.right\u wall=right\u wall
self.bottom\u wall=bottom\u wall
#每个区块包括5x5像素的空白空间+1px(位于其左侧)和1px(位于其底部)的墙壁(如果区块有)
def创建块(行、列、右墙、下墙):
对于范围内的i(第2行,第4行):#因为路径是5px宽
对于范围内的j(col-2,col+4):#我转到块的空白区域的中心像素并使其变厚
迷宫[i,j]=[255,255,255]#换句话说,我在中心像素周围画了2px的边框
如果右边有墙:#如果街区有墙,它就在右边
创建右墙(行、列、1)#使用函数绘制右墙
if bottom_wall:#如果块的底部有墙
创建底墙(行、列、1)#使用函数绘制底墙
def创建右墙(行、列、颜色):
如果颜色=0:#如果颜色参数=0
对于范围内的i(第2行,第+4行):
迷宫[i,col+3]=[0,0,0]#我画(创建)黑墙
其他:
对于范围内的i(第2行,第+4行):
迷宫[i,col+3]=[255,255,255]#我画白墙(如果我需要删除墙)
def创建底部墙(行、列、颜色):
如果颜色==0:
对于范围内的i(第2列,第4列):
迷宫[行+3,i]=[0,0,0]
如果第4行<迷宫高度且迷宫[第4行,第3列][0]==0:#有时底墙之间有1px的间隙
迷宫[row+3,col-3]=[0,0,0]#所以我用黑色像素填充它
其他:
对于范围内的i(第2列,第4列):
迷宫[行+3,i]=[255,255,255]#绘制白色墙(删除墙)
def creating():
当前_点=[3,3]#左上块出现的位置([3,3]表示块的中心)
set_count=1#要拥有唯一的集合编号,它在使用后每次都会增加
对于范围内的行(高度):#从上到下
#我打印一些不必要的信息只是为了知道发生了什么
打印(“--------------------------行”,行)#正在创建的当前行
如果行==0:#如果是第一行
对于范围内的列(宽度):
创建_块(当前_点[0],当前_点[1],假,假)
块[row]。追加(单元格(当前_点[0],当前_点[1],设置_计数,False,False))
set_count+=1#由于已使用设置的编号,下一个块将有另一个
当前_点[1]+=6#下一个块的中心距当前块的中心6px
elif row==高度-1:#如果是最后一行
对于范围内的i(宽度):
创建_块(当前_点[0],当前_点[1],假,假)
块[row]。追加(单元格(当前_点[0],当前_点[1],块[row-1][i]。数字,假,真))
当前_点[1]+=6
#我不知道我为什么这么做。只是尝试正确地创建最后一行
如果(不是块[row-1][i]。底部墙,而不是块[row-1][i+1]。底部墙)和\
(区块[第1行][i]。编号==区块[第1行][i+1]。编号):
创建右墙(块[行][i]。行,块[行][i]。列,0)
休息,因为这是最后一排,所以不要做其他事情
其他:
对于范围内的列(宽度):
创建_块(当前_点[0],当前_点[1],假,假)
打印(“顶部的块已设置:”,块[row-1][col]。编号,end=”“)
如果块[row-1][col]。底部#墙:#如果上部块有底部墙
块[row]。追加(单元格(当前_点[0],当前_点[1],设置_计数,False,False))
打印(“上部块有底壁,因此当前块的设置为”,设置计数)
设置_计数+=1
否则:#如果不是,则当前块的设置将与上一个块的设置相同
块[行]。追加(单元格(当前_点[0],当前_点[1],
块[row-1][col]。编号,False,False)
打印(“当前块集”,块[row-1][col]。编号)
当前_点[1]+=6
#仅显示当前行的设置编号
对于块[行]中的i:
打印(i.number,end=“”)
#在同一组块之间放置一面墙(我们不希望迷宫中有回路)
对于范围内的i(len(块[行])-1):
如果块[row][i]。编号==块[row][i+1]。编号:
块[行][i]。右墙=真
创建右墙(块[行][i]。行,块[行][i]。列,0)
打印(“在“、i+1”和“、i+2”之间放置一堵墙,因为“、块[行][i]。数字,”=“\
块[行][i+1]。编号)
对于范围内的i(len(块[行])-1):
if random.choice([0,1])==0并阻止[row][i]。number!=块[行][i+1]。编号:
块[行][i+1]。编号=块[行][i]。编号
打印(“连接块”、“i+1”和“i+2”)
其他:
块[行][i]。右墙=真
创建右墙(块[行][i]。行,块[行][i]。列,0)
#要知道当前行中的设置nu,BER
设置_行中的_=[]
对于块[行]中的i:
打印(i.number,end=“”)
设置行中的行。追加(i.number)
集合行中的集合=已排序(集合(集合行中的集合),键=λx:集合i