教你怎么用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中使用NLTK库实现对词干的提取的教程
Apr 08 Python
在Python的Bottle框架中使用微信API的示例
Apr 23 Python
python学习教程之Numpy和Pandas的使用
Sep 11 Python
Python Unittest自动化单元测试框架详解
Apr 04 Python
删除DataFrame中值全为NaN或者包含有NaN的列或行方法
Nov 06 Python
python的sorted用法详解
Jun 25 Python
Python 通过截图匹配原图中的位置(opencv)实例
Aug 27 Python
Python爬虫库requests获取响应内容、响应状态码、响应头
Jan 25 Python
python + selenium 刷B站播放量的实例代码
Jun 12 Python
python 代码运行时间获取方式详解
Sep 18 Python
使用Python脚本对GiteePages进行一键部署的使用说明
May 27 Python
python manim实现排序算法动画示例
Aug 14 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 curl_setopt()函数实例代码与参数分析
2011/06/02 PHP
PHP三元运算符的结合性介绍
2012/01/10 PHP
CodeIgniter删除和设置Cookie的方法
2015/04/07 PHP
PHP的压缩函数实现:gzencode、gzdeflate和gzcompress的区别
2016/01/27 PHP
Thinkphp5框架实现获取数据库数据到视图的方法
2019/08/14 PHP
JavaScript面象对象设计
2008/04/28 Javascript
对jQuery的事件绑定的一些思考(补充)
2013/04/20 Javascript
用Jquery选择器计算table中的某一列某一行的合计
2014/08/13 Javascript
jQuery+slidereveal实现的面板滑动侧边展出效果
2015/03/14 Javascript
jquery插件NProgress.js制作网页加载进度条
2015/06/05 Javascript
jQuery鼠标事件汇总
2015/08/30 Javascript
JS实现侧边栏鼠标经过弹出框+缓冲效果
2017/03/29 Javascript
vue2中filter()的实现代码
2017/07/09 Javascript
浅谈Angular4中常用管道
2017/09/27 Javascript
XMLHttpRequest对象_Ajax异步请求重点(推荐)
2017/09/28 Javascript
D3.js实现拓扑图的示例代码
2018/06/30 Javascript
新手入门js闭包学习过程解析
2019/10/08 Javascript
python写入中英文字符串到文件的方法
2015/05/06 Python
Python实现处理管道的方法
2015/06/04 Python
python处理按钮消息的实例详解
2017/07/11 Python
Ubuntu安装Jupyter Notebook教程
2017/10/18 Python
Python通过调用有道翻译api实现翻译功能示例
2018/07/19 Python
DataFrame:通过SparkSql将scala类转为DataFrame的方法
2019/01/29 Python
python的debug实用工具 pdb详解
2019/07/12 Python
基于CSS3的CSS 多栏(Multi-column)实现瀑布流源码分享
2014/06/11 HTML / CSS
记一次高分屏下canvas模糊问题
2020/02/17 HTML / CSS
美国最顶级的精品店之一:Hampden Clothing
2016/12/22 全球购物
意大利奢华内衣制造商:Cosabella
2017/08/29 全球购物
印度尼西亚最大和最全面的网络商城:Blibli.com
2017/10/04 全球购物
承认错误的检讨书
2014/01/30 职场文书
电子装配专业毕业生求职信
2014/04/23 职场文书
公司股份合作协议书
2014/12/07 职场文书
党支部先进事迹材料
2014/12/24 职场文书
个人原因辞职信模板
2015/05/13 职场文书
抖音短视频(douyin)去水印工具的实现代码
2021/03/30 Javascript
Redis做数据持久化的解决方案及底层原理
2021/07/15 Redis