SoFunction
Updated on 2024-10-30

Teach you how to implement a multipath maze with Python

I. Introduction to the idea

  • A 2-path maze can be formed by opening a suitable piece of wall on top of an existing single-path maze.
  • An open wall cannot be too close to an existing path.
  • 1. perform a breadth-first search starting at the start and end points, and for each cell in the maze record the number of steps the cell takes away from the start and end points.
  • 2. Split the maze into two parts by putting all cells closer to the beginning into the start set and all cells closer to the goal into the end set.
  • 3. Choose any wall that separates the two areas and take it apart to create a 2-way maze.
  • If you want to generate the shortest pathway you can choose the wall with the largest difference in distance between neighboring grids to split, and in general these two pathways are also farther apart.

II. Illustrations

在这里插入图片描述

III. Subregional presentation codes

#!/usr/bin/python3.7
# -*- coding: utf-8 -*-
import random
import pygame
#import depth_maze
import maze
#import aldous_broder_maze

()  # Initialize pygame
size = width, height = 800, 600  # Set window size
screen = .set_mode(size)  # Display window
# Color
diamond_color_size = 8
COLOR_RED, COLOR_BLUE, COLOR_GREEN, COLOR_YELLOW, COLOR_BLACK, COLOR_GREY, COLOR_GOLDEN, COLOR_NO_DIAMOND = list(range(
    diamond_color_size))
COLOR = {
    COLOR_RED: (255, 0, 0),
    COLOR_BLUE: (0, 0, 255),
    COLOR_GREEN: (0, 255, 0),
    COLOR_YELLOW: (255, 255, 0),
    COLOR_BLACK: (0, 0, 0),
    COLOR_GREY: (250, 240, 230),
    COLOR_GOLDEN : (255,215,0),
    COLOR_NO_DIAMOND: (100, 100, 100),
}
# Lattice size
DIAMOND_LEN = 20
DIAMOND_SIZE = (DIAMOND_LEN, DIAMOND_LEN)
# Blue plaid
DIAMOND=(DIAMOND_SIZE).convert()
(COLOR[COLOR_BLUE])
# Green plaid
DIAMOND_GREEN=(DIAMOND_SIZE).convert()
DIAMOND_GREEN.fill(COLOR[COLOR_GREEN])
# Red plaid
DIAMOND_RED=(DIAMOND_SIZE).convert()
DIAMOND_RED.fill(COLOR[COLOR_RED])
# Yellow plaid
DIAMOND_YELLOW=(DIAMOND_SIZE).convert()
DIAMOND_YELLOW.fill(COLOR[COLOR_YELLOW])
# The plaid of gray #
DIAMOND_GREY=(DIAMOND_SIZE).convert()
DIAMOND_GREY.fill(COLOR[COLOR_GREY])
# Fonts
use_font = ("", 16)
use_font12 = ("", 12)
# Background
background=(size).convert()
(COLOR[COLOR_BLACK])
# Text
score_surface = use_font.render("Find the end.", True, COLOR[COLOR_BLACK], COLOR[COLOR_GREY])
# Time
clock = ()

##############################################
# Lattice access markers x,y,0, right wall x,y,1, lower wall x,y,2
##############################################
# Marker
NOWALL= # Without walls
WALL=  # With walls
WALL2=maze.WALL2  # With walls

VISIT= # Visited
NOVISIT= # Never been there #
VERTICAL =  # Vertical
HORIZONTAL = # Horizontal
INFINITE =  # Infinity

INFINITE =  # Infinity

# 
def FindNext(pathList, walls, grids, rows, cols):
    nextList = [] # Next
    for node in pathList:
        r, c = node
        l = grids[r][c]
        nl=l+1
        # Accessible locations
        if r>0 and NOWALL == walls[r][c][1] and INFINITE == grids[r-1][c]:
            # move = 'u'
            nr=r-1
            nc=c
            if (nr,nc) not in nextList:
                ((nr,nc))
                grids[nr][nc] = l+1
        if c>0 and NOWALL == walls[r][c][0] and INFINITE == grids[r][c-1]:
            # move = 'l'
            nr=r
            nc=c-1
            if (nr,nc) not in nextList:
                ((nr,nc))
                grids[nr][nc] = l+1
        if c<cols-1 and NOWALL == walls[r][c+1][0] and INFINITE == grids[r][c+1] :
            # move='r'
            nr=r
            nc=c+1
            if (nr,nc) not in nextList:
                ((nr,nc))
                grids[nr][nc] = l+1
        if r<rows-1 and NOWALL == walls[r+1][c][1] and INFINITE == grids[r+1][c] :
            # move='d'
            nr=r+1
            nc=c
            if (nr,nc) not in nextList:
                ((nr,nc))
                grids[nr][nc] = l+1
    return nextList


def draw_diamond(r,c, screen, POSX, POSY, diamod):
    px,py=POSX + 1 + (c) * DIAMOND_SIZE[0], POSY + 1 + (r) * DIAMOND_SIZE[1]
    # Marked visited grids
    (diamod, (px, py))
    return 

def draw_diamond_and_str(r,c, screen, POSX, POSY, diamod, use_font, string, color, color_back):
    px,py=POSX + 1 + (c) * DIAMOND_SIZE[0], POSY + 1 + (r) * DIAMOND_SIZE[1]
    # Marked visited grids
    (diamod, (px, py))
    distance_surface = use_font.render(string, True, color, color_back)
    (distance_surface, (px, py))
    return 


# Sample algorithm
def multipath_maze_demo(rows, cols):
    #walls = maze.aldous_broder_maze(rows, cols)
    #walls = maze.depth_maze(rows, cols)
    #walls = maze.kruskal_maze(rows, cols)
    #walls = maze.prim_maze(rows, cols)
    #walls = maze.wilson_maze(rows, cols)
    walls = maze.wilson_maze(rows, cols)
    POSX=40
    POSY=40
    # Initialization not accessed
    grids=[[ INFINITE for i in range(cols)]for j in range(rows)]
    # Starting point
    # Marking the maze
    r=0
    c=0
    findEndPoint=False
    findPath=False
    # Starting point
    startPoint=(r,c)
    # The end point
    stopPoint=(rows-1,cols-1)
    # 
    mainList=[] # Primary path

    beginList=[startPoint]
    endList=[stopPoint]
    grids[r][c]=0 # Marker has traveled the grid distance
    grids[stopPoint[0]][stopPoint[1]]=0

    # Grids not visited
    notUseGrids = [] 
    for tr in range(rows):
        for tc in range(cols):
            ((tr,tc))

    beginMap=beginList
    endMap=endList

    while True:
        for event in ():
            if  == :
                return
        if notUseGrids:        
            beginNextList = [] # Next
            for node in beginList:
                r, c = node
                l = grids[r][c]
                # Accessible locations
                if r>0 and NOWALL == walls[r][c][1] and INFINITE == grids[r-1][c]:
                    # move = 'u'
                    nr=r-1
                    nc=c
                    if (nr,nc) not in beginNextList:
                        ((nr,nc))
                        grids[nr][nc] = l+1
                if c>0 and NOWALL == walls[r][c][0] and INFINITE == grids[r][c-1]:
                    # move = 'l'
                    nr=r
                    nc=c-1
                    if (nr,nc) not in beginNextList:
                        ((nr,nc))
                        grids[nr][nc] = l+1
                if c<cols-1 and NOWALL == walls[r][c+1][0] and INFINITE == grids[r][c+1] :
                    # move='r'
                    nr=r
                    nc=c+1
                    if (nr,nc) not in beginNextList:
                        ((nr,nc))
                        grids[nr][nc] = l+1
                if r<rows-1 and NOWALL == walls[r+1][c][1] and INFINITE == grids[r+1][c] :
                    # move='d'
                    nr=r+1
                    nc=c
                    if (nr,nc) not in beginNextList:
                        ((nr,nc))
                        grids[nr][nc] = l+1
            # Next lap
            beginList = beginNextList
            beginMap = beginMap + beginNextList
            # end
            endNextList = [] # Next
            for node in endList:
                r, c = node
                l = grids[r][c]
                # Accessible locations
                if r>0 and NOWALL == walls[r][c][1] and INFINITE == grids[r-1][c]:
                    # move = 'u'
                    nr=r-1
                    nc=c
                    if (nr,nc) not in endNextList:
                        ((nr,nc))
                        grids[nr][nc] = l+1
                if c>0 and NOWALL == walls[r][c][0] and INFINITE == grids[r][c-1]:
                    # move = 'l'
                    nr=r
                    nc=c-1
                    if (nr,nc) not in endNextList:
                        ((nr,nc))
                        grids[nr][nc] = l+1
                if c<cols-1 and NOWALL == walls[r][c+1][0] and INFINITE == grids[r][c+1] :
                    # move='r'
                    nr=r
                    nc=c+1
                    if (nr,nc) not in endNextList:
                        ((nr,nc))
                        grids[nr][nc] = l+1
                if r<rows-1 and NOWALL == walls[r+1][c][1] and INFINITE == grids[r+1][c] :
                    # move='d'
                    nr=r+1
                    nc=c
                    if (nr,nc) not in endNextList:
                        ((nr,nc))
                        grids[nr][nc] = l+1
            # Next lap
            endList = endNextList
            endMap = endMap + endNextList

        elif findEndPoint and not findPath:
            ((r,c))
            l = grids[r][c]
            nl=l-1
            # Recent
            if r>0 and NOWALL == walls[r][c][1] and nl == grids[r-1][c]:
                # move = 'u'
                nr=r-1
                nc=c
            if c>0 and NOWALL == walls[r][c][0] and nl == grids[r][c-1]:
                # move = 'l'
                nr=r
                nc=c-1
                ((nr,nc))
            if c<cols-1 and NOWALL == walls[r][c+1][0] and nl == grids[r][c+1] :
                # move='r'
                nr=r
                nc=c+1
            if r<rows-1 and NOWALL == walls[r+1][c][1] and nl == grids[r+1][c] :
                # move='d'
                nr=r+1
                nc=c
            # Finding the starting point
            if 0 == nl:
                ((nr,nc))
                findPath = True
            r,c=nr,nc

        (background, (0, 0))
        # Plaid
        for cx in range(cols):
            for ry in range(rows):
                px,py=POSX + 1 + (cx) * DIAMOND_SIZE[0], POSY + 1 + (ry) * DIAMOND_SIZE[1]
                # Marked visited grids
                if  == grids[ry][cx]:
                    draw_diamond(ry, cx, screen, POSX, POSY, DIAMOND)
                else:
                    s = "{}".format(grids[ry][cx])
                    draw_diamond_and_str(ry, cx, screen, POSX,POSY, DIAMOND_GREY, use_font12, s, COLOR[COLOR_BLACK], COLOR[COLOR_GREY]) 
        # Enclave
        for pos in beginMap:
            s = "{}".format(grids[pos[0]][pos[1]])
            draw_diamond_and_str(pos[0], pos[1], screen, POSX,POSY, DIAMOND_GREEN, use_font12, s, COLOR[COLOR_BLACK], COLOR[COLOR_GREEN])
        for pos in endMap:
            s = "{}".format(grids[pos[0]][pos[1]])
            draw_diamond_and_str(pos[0], pos[1], screen, POSX,POSY, DIAMOND_YELLOW, use_font12, s, COLOR[COLOR_BLACK], COLOR[COLOR_YELLOW])
        # Circular outer ring
        if beginList and not mainList:
            for pos in beginList:
                s = "{}".format(grids[pos[0]][pos[1]])
                draw_diamond_and_str(pos[0], pos[1], screen, POSX,POSY, DIAMOND_RED, use_font12, s, COLOR[COLOR_BLACK], COLOR[COLOR_RED])
            for pos in endList:
                s = "{}".format(grids[pos[0]][pos[1]])
                draw_diamond_and_str(pos[0], pos[1], screen, POSX,POSY, DIAMOND_RED, use_font12, s, COLOR[COLOR_BLACK], COLOR[COLOR_RED])
        # Path
        if mainList:
            for pos in mainList:
                s = "{}".format(grids[pos[0]][pos[1]])
                draw_diamond_and_str(pos[0], pos[1], screen, POSX,POSY, DIAMOND_YELLOW, use_font12, s, COLOR[COLOR_BLACK], COLOR[COLOR_YELLOW])
            # r,c
            px,py=POSX + 1 + (c) * DIAMOND_SIZE[0], POSY + 1 + (r) * DIAMOND_SIZE[1]
            (DIAMOND_GREEN, (px, py))
            s = "{}".format(grids[r][c])
            distance_surface = use_font12.render(s, True, COLOR[COLOR_BLACK], COLOR[COLOR_GREEN])
            (distance_surface, (px, py))

        # Painted facades
        (screen, COLOR[COLOR_RED], (POSX + 0, POSY + 0, DIAMOND_LEN*cols+1, DIAMOND_LEN*rows+1), 2)
        # Drawing walls that aren't open
        for cx in range( cols):
            for ry in range(rows):
                px,py=POSX + 1 + (cx) * DIAMOND_SIZE[0], POSY + 1 + (ry) * DIAMOND_SIZE[1]
                color = COLOR[COLOR_BLACK]
                if  == walls[ry][cx][0]:
                    (screen, color, (px, py), (px, py+DIAMOND_LEN), 2)
                if  == walls[ry][cx][1]:
                    (screen, color, (px, py), (px+DIAMOND_LEN, py), 2)
        # Print text alerts
        if findEndPoint:
            (score_surface, (POSX+50, POSY+rows*22))
        # Frame rate
        (25)

        ()
    return 



# main
if __name__ == "__main__":
    '''main'''
    multipath_maze_demo(20, 30)

To this article on how to teach you to use Python to achieve multi-path maze is introduced to this article, more related Python to achieve multi-path maze content, please search for my previous posts or continue to browse the following related articles I hope you will support me in the future!