教你怎么用Python实现多路径迷宫


Posted in Python onApril 29, 2021

一、思路介绍

  • 在已有的单路径迷宫基础上打开一块合适的墙就可以构成2路径的迷宫。
  • 打开的墙不能和已有的路径过近。
  • 1。从开始和终点开始进行广度优先搜索,并为迷宫中的每个单元格记录单元格远离开始和终点的步数。
  • 2。通过将距离开头较近的所有单元格放入 start 集合,并将更接近目标的所有单元格放入end集合来将迷宫分成两个部分。
  • 3。 选择分开两个区域的任意一面墙拆开就可以形成2通路的迷宫。
  • 如想生成最短的通路可以选择相邻格子距离差值最大的那面墙拆开,一般情况下这两条路距离也比较远。

二、图示

教你怎么用Python实现多路径迷宫

三、分区域演示代码

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

pygame.init()  # 初始化pygame
size = width, height = 800, 600  # 设置窗口大小
screen = pygame.display.set_mode(size)  # 显示窗口
# 颜色
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),
}
# 格子大小
DIAMOND_LEN = 20
DIAMOND_SIZE = (DIAMOND_LEN, DIAMOND_LEN)
# 蓝格子
DIAMOND=pygame.surface.Surface(DIAMOND_SIZE).convert()
DIAMOND.fill(COLOR[COLOR_BLUE])
# 绿格子 
DIAMOND_GREEN=pygame.surface.Surface(DIAMOND_SIZE).convert()
DIAMOND_GREEN.fill(COLOR[COLOR_GREEN])
# 红格子 
DIAMOND_RED=pygame.surface.Surface(DIAMOND_SIZE).convert()
DIAMOND_RED.fill(COLOR[COLOR_RED])
# 黄格子 
DIAMOND_YELLOW=pygame.surface.Surface(DIAMOND_SIZE).convert()
DIAMOND_YELLOW.fill(COLOR[COLOR_YELLOW])
# 灰的格子 
DIAMOND_GREY=pygame.surface.Surface(DIAMOND_SIZE).convert()
DIAMOND_GREY.fill(COLOR[COLOR_GREY])
# 字体
use_font = pygame.font.Font("FONT.TTF", 16)
use_font12 = pygame.font.Font("FONT.TTF", 12)
# 背景
background=pygame.surface.Surface(size).convert()
background.fill(COLOR[COLOR_BLACK])
# 文字
score_surface = use_font.render("找到终点", True, COLOR[COLOR_BLACK], COLOR[COLOR_GREY])
# 时间
clock = pygame.time.Clock()

##############################################
#   格子访问标记x,y,0,右墙x,y,1,下墙x,y,2
##############################################
#标记 
NOWALL=maze.NOWALL # 无墙
WALL=maze.WALL  # 有墙
WALL2=maze.WALL2  # 有墙

VISIT=maze.VISIT # 到访过
NOVISIT=maze.NOVISIT # 没到过
VERTICAL = maze.VERTICAL # 垂直的
HORIZONTAL = maze.HORIZONTAL# 水平的
INFINITE = maze.INFINITE # 无穷远

INFINITE = maze.INFINITE # 无穷远

# 
def FindNext(pathList, walls, grids, rows, cols):
    nextList = [] # 下一步
    for node in pathList:
        r, c = node
        l = grids[r][c]
        nl=l+1
        # 可以到达的位置
        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:
                nextList.append((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:
                nextList.append((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:
                nextList.append((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:
                nextList.append((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]
    # 标记访问过的格子
    screen.blit(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]
    # 标记访问过的格子
    screen.blit(diamod, (px, py))
    distance_surface = use_font.render(string, True, color, color_back)
    screen.blit(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
    # 初始化未访问
    grids=[[ INFINITE for i in range(cols)]for j in range(rows)]
    # 起点
    # 标记迷宫
    r=0
    c=0
    findEndPoint=False
    findPath=False
    # 起点
    startPoint=(r,c)
    # 终点
    stopPoint=(rows-1,cols-1)
    # 
    mainList=[] # 主路径

    beginList=[startPoint]
    endList=[stopPoint]
    grids[r][c]=0 # 标记已经到过格子距离
    grids[stopPoint[0]][stopPoint[1]]=0

    # 没有访问过的格子
    notUseGrids = [] 
    for tr in range(rows):
        for tc in range(cols):
            notUseGrids.append((tr,tc))

    beginMap=beginList
    endMap=endList

    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                return
        if notUseGrids:        
            beginNextList = [] # 下一步
            for node in beginList:
                r, c = node
                l = grids[r][c]
                # 可以到达的位置
                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:
                        beginNextList.append((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:
                        beginNextList.append((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:
                        beginNextList.append((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:
                        beginNextList.append((nr,nc))
                        grids[nr][nc] = l+1
            # 下一圈
            beginList = beginNextList
            beginMap = beginMap + beginNextList
            # end
            endNextList = [] # 下一步
            for node in endList:
                r, c = node
                l = grids[r][c]
                # 可以到达的位置
                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:
                        endNextList.append((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:
                        endNextList.append((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:
                        endNextList.append((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:
                        endNextList.append((nr,nc))
                        grids[nr][nc] = l+1
            # 下一圈
            endList = endNextList
            endMap = endMap + endNextList

        elif findEndPoint and not findPath:
            mainList.append((r,c))
            l = grids[r][c]
            nl=l-1
            # 最近的
            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
                beginNextList.append((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
            # 找到起点
            if 0 == nl:
                mainList.append((nr,nc))
                findPath = True
            r,c=nr,nc

        screen.blit(background, (0, 0))
        # 格子
        for cx in range(cols):
            for ry in range(rows):
                px,py=POSX + 1 + (cx) * DIAMOND_SIZE[0], POSY + 1 + (ry) * DIAMOND_SIZE[1]
                # 标记访问过的格子
                if maze.INFINITE == 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]) 
        # 圈地
        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])
        # 循环外圈
        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])
        # 路径
        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]
            screen.blit(DIAMOND_GREEN, (px, py))
            s = "{}".format(grids[r][c])
            distance_surface = use_font12.render(s, True, COLOR[COLOR_BLACK], COLOR[COLOR_GREEN])
            screen.blit(distance_surface, (px, py))

        # 画外墙
        pygame.draw.rect(screen, COLOR[COLOR_RED], (POSX + 0, POSY + 0, DIAMOND_LEN*cols+1, DIAMOND_LEN*rows+1), 2)
        # 画没打通的墙
        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 maze.WALL == walls[ry][cx][0]:
                    pygame.draw.line(screen, color, (px, py), (px, py+DIAMOND_LEN), 2)
                if maze.WALL == walls[ry][cx][1]:
                    pygame.draw.line(screen, color, (px, py), (px+DIAMOND_LEN, py), 2)
        # 打印文字提示
        if findEndPoint:
            screen.blit(score_surface, (POSX+50, POSY+rows*22))
        # 帧率
        clock.tick(25)

        pygame.display.update()
    return 



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

到此这篇关于教你怎么用Python实现多路径迷宫的文章就介绍到这了,更多相关Python实现多路径迷宫内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
使用Python的Bottle框架写一个简单的服务接口的示例
Aug 25 Python
利用python实现简单的循环购物车功能示例代码
Jul 05 Python
python timestamp和datetime之间转换详解
Dec 11 Python
python opencv实现任意角度的透视变换实例代码
Jan 12 Python
PyQt5主窗口动态加载Widget实例代码
Feb 07 Python
python生成不重复随机数和对list乱序的解决方法
Apr 09 Python
python使用RNN实现文本分类
May 24 Python
django将网络中的图片,保存成model中的ImageField的实例
Aug 07 Python
python使用requests.session模拟登录
Aug 09 Python
详解django实现自定义manage命令的扩展
Aug 13 Python
python字符串替换re.sub()实例解析
Feb 09 Python
python实现每天自动签到领积分的示例代码
Aug 18 Python
python3.9之你应该知道的新特性详解
Apr 29 #Python
Python基础之tkinter图形化界面学习
Apr 29 #Python
Django cookie和session的应用场景及如何使用
Apr 29 #Python
Python使用random模块实现掷骰子游戏的示例代码
Apr 29 #Python
python中requests库+xpath+lxml简单使用
python实现进度条的多种实现
教你如何使用Python下载B站视频的详细教程
You might like
PHP之变量、常量学习笔记
2008/03/27 PHP
php中对xml读取的相关函数的介绍一
2008/06/05 PHP
PHP判断图片格式的七种方法小结
2013/06/03 PHP
PHP实现找出有序数组中绝对值最小的数算法分析
2017/08/07 PHP
laravel-admin自动生成模块,及相关基础配置方法
2019/10/08 PHP
javascript中的注释使用与注意事项小结
2011/09/20 Javascript
nodejs入门详解(多篇文章结合)
2012/03/07 NodeJs
JavaScript 模式之工厂模式(Factory)应用介绍
2012/11/15 Javascript
Js控制弹窗实现在任意分辨率下居中显示
2013/08/01 Javascript
jQuery中iframe的操作(点击按钮新增窗口)
2016/04/20 Javascript
jQuery源码分析之sizzle选择器详解
2017/02/13 Javascript
利用Chrome DevTools直接调试Node.js和JavaScript的方法详解(并行)
2017/02/16 Javascript
JS实现微信里判断页面是否被分享成功的方法
2017/06/06 Javascript
纯JS实现简单的日历
2017/06/26 Javascript
关于element-ui的隐藏组件el-scrollbar的使用
2019/05/29 Javascript
JS原型prototype和__proto__用法实例分析
2020/03/14 Javascript
JavaScript Tab菜单实现过程解析
2020/05/13 Javascript
vue 项目引入echarts 添加点击事件操作
2020/09/09 Javascript
新手该如何学python怎么学好python?
2008/10/07 Python
利用Anaconda完美解决Python 2与python 3的共存问题
2017/05/25 Python
python数字图像处理之高级滤波代码详解
2017/11/23 Python
python requests post多层字典的方法
2018/12/27 Python
Python下简易的单例模式详解
2019/04/08 Python
python实现井字棋小游戏
2020/03/04 Python
埃弗顿足球俱乐部官方网上商店:Everton Direct
2018/01/13 全球购物
日本最大级玩偶手办购物:あみあみ Amiami
2018/04/23 全球购物
Turnbull & Asser官网:英国皇室御用的顶级定制衬衫
2019/01/31 全球购物
建筑学推荐信
2013/11/03 职场文书
运动会广播稿60字
2014/01/15 职场文书
办公室员工岗位工作职责
2014/03/10 职场文书
大学生应聘导游自荐信
2014/06/02 职场文书
先进教师个人事迹材料
2014/12/15 职场文书
小学教师师德师风承诺书
2015/04/28 职场文书
民警忠诚教育心得体会
2016/01/23 职场文书
python b站视频下载的五种版本
2021/05/27 Python
Windows Server 2016服务器用户管理及远程授权图文教程
2022/08/14 Servers