Python迷宫生成和迷宫破解算法实例

作者:Eyizoha 时间:2023-12-11 11:46:43 

迷宫生成

1.随机PRIM

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

效果:

Python迷宫生成和迷宫破解算法实例

代码:


import random
import numpy as np
from matplotlib import pyplot as plt

def build_twist(num_rows, num_cols): # 扭曲迷宫
# (行坐标,列坐标,四面墙的有无&访问标记)
m = np.zeros((num_rows, num_cols, 5), dtype=np.uint8)
r, c = 0, 0
trace = [(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] = 2
 if 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] = 2
 if 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] = 2
 if len(check):
  direction = random.choice(check)
  if direction == 'L':# 打通一面墙
   m[r, c, 0] = 1
   c = c - 1
   m[r, c, 2] = 1
  if direction == 'U':
   m[r, c, 1] = 1
   r = r - 1
   m[r, c, 3] = 1
  if direction == 'R':
   m[r, c, 2] = 1
   c = c + 1
   m[r, c, 0] = 1
  if direction == 'D':
   m[r, c, 3] = 1
   r = r + 1
   m[r, c, 1] = 1
m[0, 0, 0] = 1
m[num_rows - 1, num_cols - 1, 2] = 1
return m

2.深度优先

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

效果:

Python迷宫生成和迷宫破解算法实例

代码:


def build_tortuous(num_rows, num_cols): # 曲折迷宫
m = np.zeros((num_rows, num_cols, 5), dtype=np.uint8)
r = 0
c = 0
trace = [(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] = 1
   c = c - 1
   m[r, c, 2] = 1
  if direction == 'U':
   m[r, c, 1] = 1
   r = r - 1
   m[r, c, 3] = 1
  if direction == 'R':
   m[r, c, 2] = 1
   c = c + 1
   m[r, c, 0] = 1
  if direction == 'D':
   m[r, c, 3] = 1
   r = r + 1
   m[r, c, 1] = 1
 else:
  r, c = trace.pop()
m[0, 0, 0] = 1
m[num_rows - 1, num_cols - 1, 2] = 1
return m

迷宫破解

效果:

Python迷宫生成和迷宫破解算法实例

Python迷宫生成和迷宫破解算法实例

1.填坑法

思路:从起点开始,不断随机选择没墙的方向前进,当处于一个坑(除了来时的方向外三面都是墙)中时,退一步并建造一堵墙将坑封上。不断重复以上步骤,最终就能抵达终点。

优缺点:可以处理含有环路的迷宫,但是处理时间较长还需要更多的储存空间。

代码:


def solve_fill(num_rows, num_cols, m): # 填坑法
map_arr = m.copy()# 拷贝一份迷宫来填坑
map_arr[0, 0, 0] = 0
map_arr[num_rows-1, num_cols-1, 2] = 0
move_list = []
xy_list = []
r, c = (0, 0)
while True:
 if (r == num_rows-1) and (c == num_cols-1):
  break
 xy_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 False
 elif len(way) == 1:# 在坑中
  go = way[0]
  move_list.append(go)
  if go == 'L':# 填坑
   map_arr[r, c, 0] = 0
   c = c - 1
   map_arr[r, c, 2] = 0
  elif go == 'U':
   map_arr[r, c, 1] = 0
   r = r - 1
   map_arr[r, c, 3] = 0
  elif go == 'R':
   map_arr[r, c, 2] = 0
   c = c + 1
   map_arr[r, c, 0] = 0
  elif go == 'D':
   map_arr[r, c, 3] = 0
   r = r + 1
   map_arr[r, c, 1] = 0
 else:
  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 - 1
  elif go == 'U':
   r = r - 1
  elif go == 'R':
   c = c + 1
  elif go == 'D':
   r = r + 1
r_list = xy_list.copy()
r_list.reverse()# 行动坐标记录的反转
i = 0
while 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 + 1
return 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):
  break
 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')
 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 False
 m = m + 1
 move_list.append(go)
 if go == 'L':
  c = c - 1
 elif go == 'U':
  r = r - 1
 elif go == 'R':
  c = c + 1
 elif go == 'D':
  r = r + 1
del 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)

来源:https://blog.csdn.net/Eyizoha/article/details/89407054

标签:Python,迷宫,生成,破解
0
投稿

猜你喜欢

  • python实现域名系统(DNS)正向查询的方法

    2021-03-26 17:20:57
  • 用Python实现BP神经网络(附代码)

    2023-11-24 17:20:11
  • python中property属性的介绍及其应用详解

    2022-09-26 03:21:36
  • 简单介绍python封装的基本知识

    2022-04-16 18:51:11
  • vuex mutations的两种调用方法小结

    2024-04-27 16:11:42
  • Python中的条件判断语句基础学习教程

    2021-06-19 11:51:36
  • Python 浪漫烟花实现代码全解

    2023-11-16 01:24:56
  • Python编程使用NLTK进行自然语言处理详解

    2022-07-05 11:47:06
  • Python跳出多重循环的方法示例

    2022-12-18 16:28:26
  • Python利用Seaborn绘制多标签的混淆矩阵

    2022-12-12 17:46:22
  • 基于scrapy的redis安装和配置方法

    2022-07-15 17:26:56
  • JavaScript中的fontsize()方法使用详解

    2024-06-05 09:55:25
  • SQL学习笔记五去重,给新加字段赋值的方法

    2011-09-30 11:53:28
  • DW实现滚动新闻

    2007-12-03 11:35:00
  • Python 列表映射后的平均值

    2021-12-25 19:02:39
  • Keras预训练的ImageNet模型实现分类操作

    2021-12-14 01:33:11
  • 教女朋友学Python3(二)简单的输入输出及内置函数查看 <font color=red>原创</font>

    2022-11-14 08:32:18
  • php使用composer常见问题及解决办法

    2023-07-10 13:54:53
  • 如何利用Pyecharts可视化微信好友

    2022-04-13 07:34:14
  • 如何理解PHP程序执行的过程原理

    2023-10-08 14:45:10
  • asp之家 网络编程 m.aspxhome.com