迷宫绘制函数

def draw(num_rows, num_cols, m):image = np.zeros((num_rows * 10, num_cols * 10), dtype=np.uint8)for row in range(0, num_rows):for col in range(0, num_cols):cell_data = m[row, col]for i in range(10 * row + 2, 10 * row + 8):image[i, range(10 * col + 2, 10 * col + 8)] = 255if cell_data[0] == 1:image[range(10 * row + 2, 10 * row + 8), 10 * col] = 255image[range(10 * row + 2, 10 * row + 8), 10 * col + 1] = 255if cell_data[1] == 1:image[10 * row, range(10 * col + 2, 10 * col + 8)] = 255image[10 * row + 1, range(10 * col + 2, 10 * col + 8)] = 255if cell_data[2] == 1:image[range(10 * row + 2, 10 * row + 8), 10 * col + 9] = 255image[range(10 * row + 2, 10 * row + 8), 10 * col + 8] = 255if cell_data[3] == 1:image[10 * row + 9, range(10 * col + 2, 10 * col + 8)] = 255image[10 * row + 8, range(10 * col + 2, 10 * col + 8)] = 255return imagedef draw_path(image, move_list):row, col = (0, 0)image[range(10 * row + 2, 10 * row + 8), 10 * col] = 127image[range(10 * row + 2, 10 * row + 8), 10 * col + 1] = 127for i in range(len(move_list) + 1):for x in range(10 * row + 2, 10 * row + 8):image[x, range(10 * col + 2, 10 * col + 8)] = 127if i > 0:go = move_list[i - 1]if go == 'L':image[range(10 * row + 2, 10 * row + 8), 10 * col + 9] = 127image[range(10 * row + 2, 10 * row + 8), 10 * col + 8] = 127elif go == 'U':image[10 * row + 9, range(10 * col + 2, 10 * col + 8)] = 127image[10 * row + 8, range(10 * col + 2, 10 * col + 8)] = 127elif go == 'R':image[range(10 * row + 2, 10 * row + 8), 10 * col] = 127image[range(10 * row + 2, 10 * row + 8), 10 * col + 1] = 127elif go == 'D':image[10 * row, range(10 * col + 2, 10 * col + 8)] = 127image[10 * row + 1, range(10 * col + 2, 10 * col + 8)] = 127if i >= len(move_list):breakgo = move_list[i]if go == 'L':image[range(10 * row + 2, 10 * row + 8), 10 * col] = 127image[range(10 * row + 2, 10 * row + 8), 10 * col + 1] = 127elif go == 'U':image[10 * row, range(10 * col + 2, 10 * col + 8)] = 127image[10 * row + 1, range(10 * col + 2, 10 * col + 8)] = 127elif go == 'R':image[range(10 * row + 2, 10 * row + 8), 10 * col + 9] = 127image[range(10 * row + 2, 10 * row + 8), 10 * col + 8] = 127elif go == 'D':image[10 * row + 9, range(10 * col + 2, 10 * col + 8)] = 127image[10 * row + 8, range(10 * col + 2, 10 * col + 8)] = 127if go == 'L':col = col - 1elif go == 'U':row = row - 1elif go == 'R':col = col + 1elif go == 'D':row = row + 1image[range(10 * row + 2, 10 * row + 8), 10 * col + 9] = 127image[range(10 * row + 2, 10 * row + 8), 10 * col + 8] = 127return image

迷宫生成

1.随机PRIM

思路:先让迷宫中全都是墙,不断从列表(最初只含有一个启始单元格)中选取一个单元格标记为通路,将其周围(上下左右)未访问过的单元格放入列表并标记为已访问,再随机选取该单元格与周围通路单元格(若有的话)之间的一面墙打通。重复以上步骤直到列表为空,迷宫生成完毕。这种方式生成的迷宫难度高,岔口多。
效果:
代码:

import random
import numpy as np
from matplotlib import pyplot as pltdef build_twist(num_rows, num_cols):  # 扭曲迷宫# (行坐标,列坐标,四面墙的有无&访问标记)m = np.zeros((num_rows, num_cols, 5), dtype=np.uint8)r, c = 0, 0trace = [(r, c)]while trace:r, c = random.choice(trace)m[r, c, 4] = 1    # 标记为通路trace.remove((r, c))check = []if c > 0:if m[r, c - 1, 4] == 1:check.append('L')elif m[r, c - 1, 4] == 0:trace.append((r, c - 1))m[r, c - 1, 4] = 2    # 标记为已访问if r > 0:if m[r - 1, c, 4] == 1:check.append('U')elif m[r - 1, c, 4] == 0:trace.append((r - 1, c))m[r - 1, c, 4] = 2if c < num_cols - 1:if m[r, c + 1, 4] == 1:check.append('R')elif m[r, c + 1, 4] == 0:trace.append((r, c + 1))m[r, c + 1, 4] = 2if r < num_rows - 1:if m[r + 1, c, 4] == 1:check.append('D')elif m[r + 1, c, 4] == 0:trace.append((r + 1, c))m[r + 1, c, 4] = 2if len(check):direction = random.choice(check)if direction == 'L': # 打通一面墙m[r, c, 0] = 1c = c - 1m[r, c, 2] = 1if direction == 'U':m[r, c, 1] = 1r = r - 1m[r, c, 3] = 1if direction == 'R':m[r, c, 2] = 1c = c + 1m[r, c, 0] = 1if direction == 'D':m[r, c, 3] = 1r = r + 1m[r, c, 1] = 1m[0, 0, 0] = 1m[num_rows - 1, num_cols - 1, 2] = 1return m
2.深度优先

思路:从起点开始随机游走并在前进方向两侧建立墙壁,标记走过的单元格,当无路可走(周围无未访问过的单元格)时重复返回上一个格子直到有新的未访问单元格可走。最终所有单元格都被访问过后迷宫生成完毕。这种方式生成的迷宫较为简单,由一条明显但是曲折的主路径和不多的分支路径组成。
效果:代码:

def build_tortuous(num_rows, num_cols):  # 曲折迷宫m = np.zeros((num_rows, num_cols, 5), dtype=np.uint8)r = 0c = 0trace = [(r, c)]while trace:m[r, c, 4] = 1   # 标记为已访问check = []if c > 0 and m[r, c - 1, 4] == 0:check.append('L')if r > 0 and m[r - 1, c, 4] == 0:check.append('U')if c < num_cols - 1 and m[r, c + 1, 4] == 0:check.append('R')if r < num_rows - 1 and m[r + 1, c, 4] == 0:check.append('D')if len(check):trace.append([r, c])direction = random.choice(check)if direction == 'L':m[r, c, 0] = 1c = c - 1m[r, c, 2] = 1if direction == 'U':m[r, c, 1] = 1r = r - 1m[r, c, 3] = 1if direction == 'R':m[r, c, 2] = 1c = c + 1m[r, c, 0] = 1if direction == 'D':m[r, c, 3] = 1r = r + 1m[r, c, 1] = 1else:r, c = trace.pop()m[0, 0, 0] = 1m[num_rows - 1, num_cols - 1, 2] = 1return m

迷宫破解

效果:

1.填坑法

思路:从起点开始,不断随机选择没墙的方向前进,当处于一个坑(除了来时的方向外三面都是墙)中时,退一步并建造一堵墙将坑封上。不断重复以上步骤,最终就能抵达终点。
优缺点:可以处理含有环路的迷宫,但是处理时间较长还需要更多的储存空间。
代码:

def solve_fill(num_rows, num_cols, m):  # 填坑法map_arr = m.copy() # 拷贝一份迷宫来填坑map_arr[0, 0, 0] = 0map_arr[num_rows-1, num_cols-1, 2] = 0move_list = []xy_list = []r, c = (0, 0)while True:if (r == num_rows-1) and (c == num_cols-1):breakxy_list.append((r, c))wall = map_arr[r, c]way = []if wall[0] == 1:way.append('L')if wall[1] == 1:way.append('U')if wall[2] == 1:way.append('R')if wall[3] == 1:way.append('D')if len(way) == 0:return Falseelif len(way) == 1:    # 在坑中go = way[0]move_list.append(go)if go == 'L':  # 填坑map_arr[r, c, 0] = 0c = c - 1map_arr[r, c, 2] = 0elif go == 'U':map_arr[r, c, 1] = 0r = r - 1map_arr[r, c, 3] = 0elif go == 'R':map_arr[r, c, 2] = 0c = c + 1map_arr[r, c, 0] = 0elif go == 'D':map_arr[r, c, 3] = 0r = r + 1map_arr[r, c, 1] = 0else:if len(move_list) != 0:    # 不在坑中come = move_list[len(move_list)-1]if come == 'L':if 'R' in way:way.remove('R')elif come == 'U':if 'D' in way:way.remove('D')elif come == 'R':if 'L' in way:way.remove('L')elif come == 'D':if 'U' in way:way.remove('U')go = random.choice(way) # 随机选一个方向走move_list.append(go)if go == 'L':c = c - 1elif go == 'U':r = r - 1elif go == 'R':c = c + 1elif go == 'D':r = r + 1r_list = xy_list.copy()  r_list.reverse()    # 行动坐标记录的反转i = 0while i < len(xy_list)-1:   # 去掉重复的移动步骤j = (len(xy_list)-1) - r_list.index(xy_list[i])if i != j:  # 说明这两个坐标之间的行动步骤都是多余的,因为一顿移动回到了原坐标del xy_list[i:j]del move_list[i:j]r_list = xy_list.copy()r_list.reverse()i = i + 1return move_list
2.回溯法

思路:遇到岔口则将岔口坐标和所有可行方向压入栈,从栈中弹出一个坐标和方向,前进。不断重复以上步骤,最终就能抵达终点。
优缺点:计算速度快,需要空间小,但无法处理含有环路的迷宫。
代码:

def solve_backtrack(num_rows, num_cols, map_arr):  # 回溯法move_list = ['R']m = 1   # 回溯点组号mark = []r, c = (0, 0)while True:if (r == num_rows-1) and (c == num_cols-1):breakwall = map_arr[r, c]way = []if wall[0] == 1:way.append('L')if wall[1] == 1:way.append('U')if wall[2] == 1:way.append('R')if wall[3] == 1:way.append('D')come = move_list[len(move_list) - 1]if come == 'L':way.remove('R')elif come == 'U':way.remove('D')elif come == 'R':way.remove('L')elif come == 'D':way.remove('U')while way:mark.append((r, c, m, way.pop()))  # 记录当前坐标和可行移动方向if mark:r, c, m, go = mark.pop()del move_list[m:]   # 删除回溯点之后的移动else:return Falsem = m + 1move_list.append(go)if go == 'L':c = c - 1elif go == 'U':r = r - 1elif go == 'R':c = c + 1elif go == 'D':r = r + 1del move_list[0]return move_list

测试

rows = int(input("Rows: "))
cols = int(input("Columns: "))Map = build_twist(rows, cols)
plt.imshow(draw(rows, cols, Map), cmap='gray')
fig = plt.gcf()
fig.set_size_inches(cols/10/3, rows/10/3)
plt.gca().xaxis.set_major_locator(plt.NullLocator())
plt.gca().yaxis.set_major_locator(plt.NullLocator())
plt.subplots_adjust(top=1, bottom=0, right=1, left=0, hspace=0, wspace=0)
plt.margins(0, 0)
fig.savefig('aaa.png', format='png', transparent=True, dpi=300, pad_inches=0)move = solve_backtrack(rows, cols, Map)
plt.imshow(draw_path(draw(rows, cols, Map), move), cmap='hot')
fig = plt.gcf()
fig.set_size_inches(cols/10/3, rows/10/3)
plt.gca().xaxis.set_major_locator(plt.NullLocator())
plt.gca().yaxis.set_major_locator(plt.NullLocator())
plt.subplots_adjust(top=1, bottom=0, right=1, left=0, hspace=0, wspace=0)
plt.margins(0, 0)
fig.savefig('bbb.png', format='png', transparent=True, dpi=300, pad_inches=0)

Python——迷宫生成和迷宫破解算法相关推荐

  1. flutter生成源代码_Flutter随机迷宫生成和解迷宫小游戏功能的源码

    此博客旨在帮助大家更好的了解图的遍历算法,通过Flutter移动端平台将图的遍历算法运用在迷宫生成和解迷宫上,让算法变成可视化且可以进行交互,最终做成一个可进行随机迷宫生成和解迷宫的APP小游戏.本人 ...

  2. Flutter-随机迷宫生成和解迷宫小游戏

    此博客旨在帮助大家更好的了解图的遍历算法,通过Flutter移动端平台将图的遍历算法运用在迷宫生成和解迷宫上,让算法变成可视化且可以进行交互,最终做成一个可进行随机迷宫生成和解迷宫的APP小游戏.本人 ...

  3. 迷宫生成与路径规划算法-Python3.8-附Github代码

    MazeProblem 简单介绍一下 该项目不过是一个平平无奇的小作业,基于python3.8开发,目前提供两种迷宫生成算法与三种迷宫求解算法,希望对大家的学习有所帮助. 项目如果有后续的跟进将会声明 ...

  4. js迷宫生成与迷宫求解算法

    迷宫问题是一个很经典的问题,本文记叙迷宫的生成和求解(深度优先),完整dome见文章末尾(包括动画演示) 所涉及迷宫为: 方形规则迷宫 只有一个出口和一个入口 路径连续 只有一个解 先看效果: a.迷 ...

  5. java迷宫队列实现_Creator 迷宫生成: DFS 与 BFS 算法实现

    前言: 我的迷宫代码的实现受到 [liuyubobobo] 的影响. liuyubobobo 迷宫的实现: GUI 部分使用 java Swing,编程语言是 Java. **我的迷宫代码实现: ** ...

  6. 用python 自动生成期权到期日的算法

    在个人量化平台搭建中,上篇( 阿岛格:2022年股市法定交易日期 )介绍了自动生成获取新一年的交易日期数列的简单python方法,本文介绍自动生成期权行权到期日的方法. 到期日是指期权合约到期的日子. ...

  7. HTML+CSS+JavaScript 迷宫生成算法 【建议收藏】

    最近发现很多人都在写算法类的博客,今天就献丑了使用HTML,CSS和JavaScript制作一个简单的迷宫生成小代码.证明了自己对一些简单的小算法还是可以驾驭的,基本功没有荒废. 迷宫生成有很多种算法 ...

  8. 迷宫生成算法---深度优先算法(基于python)

    迷宫生成算法---深度优先算法 总体的目录 版权及协议声明 更加舒服的阅读方式 一. 深度优先算法的原理与思路 二.迷宫的制作 迷宫的总体的创建. 三.代码的实现 总体的目录 版权及协议声明 本文章遵 ...

  9. python实现地牢迷宫生成

    python实现地牢迷宫生成 基本属性 生成房间 生成墙壁 生成门口 生成通道 基本属性 定义当前地牢的等级,地图长宽,房间数量,房间的最小最大长度,如下 class Map:def __init__ ...

最新文章

  1. R语言关系操作符:>、<=、!=、>=、==、
  2. 成功解决sklearn\preprocessing\label.py:151: DeprecationWarning: The truth value of an empty array is amb
  3. sqlite3 select查询一列_Python成为专业人士笔记–Sqlite3 模块
  4. dev-c++官网位置和源码/库位置
  5. 十、Docker快速搭建Elastic Stack(下篇)
  6. 半监督训练-思想与代码实践
  7. V4L2用户空间和kernel层driver的交互过程
  8. STL vector用法介绍
  9. 9277用计算机,【资料】[转]鸿合电子白板学科通用工具使用技巧
  10. as button onitemclicklistener为null_为vue3.0的学习TS解读高级类型
  11. 按钮下载Eclipse Color Theme
  12. 全球最大的免费暗网托管服务商 DH 再度被黑关闭
  13. SonarLint黄线警告python:S125
  14. 《剑指offer》第五十六题(数组中唯一只出现一次的数字)
  15. 优秀的长截图标注工具:iShot for Mac
  16. RK3399平台开发系列讲解(外设篇)3.35、GMAC RGMII Delayline Guide 窗口配置
  17. 网络入门-TRANK
  18. 数据结构 Java数据结构 --- 二叉树
  19. Ubuntu18.04 Ceres Solver
  20. 雷霆战机android代码,雷霆战机代码

热门文章

  1. Python里的%s和%d是什么意思
  2. linux 光功率 模块_光模块及调整光模块输入光功率的方法
  3. pika详解(五)登录认证及connectionParameters
  4. Graphql入门_1
  5. 揪出Android流氓软件
  6. php erp开发文档,API文档
  7. python练习题 21-30
  8. 机器人的弊议论文_关于机器人利弊的议论文
  9. IBM Verse On-Premises 1.0.7发布
  10. 【雷达通信】滤波及数据融合【滤波包括了常增益滤波、卡尔曼(Kalman)滤波和扩展卡尔曼滤波(EKF) 数据融合采用BC和CC两种,基于KF和EKF实现】(Matlab代码实现)