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


Posted in Python onDecember 24, 2019

迷宫生成

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)

以上这篇Python迷宫生成和迷宫破解算法实例就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python实现比较文件内容异同
Jun 22 Python
Python判断中文字符串是否相等的实例
Jul 06 Python
使用urllib库的urlretrieve()方法下载网络文件到本地的方法
Dec 19 Python
python获取全国城市pm2.5、臭氧等空气质量过程解析
Oct 12 Python
Pandas聚合运算和分组运算的实现示例
Oct 17 Python
python的pyecharts绘制各种图表详细(附代码)
Nov 11 Python
python3 dict ndarray 存成json,并保留原数据精度的实例
Dec 06 Python
python 实现二维字典的键值合并等函数
Dec 06 Python
TensorFlow固化模型的实现操作
May 26 Python
如何使用Python调整图像大小
Sep 26 Python
Python descriptor(描述符)的实现
Nov 15 Python
Python+Appium实现自动化清理微信僵尸好友的方法
Feb 04 Python
Python3 A*寻路算法实现方式
Dec 24 #Python
python logging添加filter教程
Dec 24 #Python
python打印异常信息的两种实现方式
Dec 24 #Python
numpy实现神经网络反向传播算法的步骤
Dec 24 #Python
python异常处理和日志处理方式
Dec 24 #Python
Python 音频生成器的实现示例
Dec 24 #Python
Python concurrent.futures模块使用实例
Dec 24 #Python
You might like
关于php支持分块与断点续传文件下载功能代码
2014/05/09 PHP
PHP封装的一个支持HTML、JS、PHP重定向的多功能跳转函数
2014/06/19 PHP
php mysql PDO 查询操作的实例详解
2017/09/23 PHP
针对thinkPHP5框架存储过程bug重写的存储过程扩展类完整实例
2018/06/16 PHP
PHPStudy下如何为Apache安装SSL证书的方法步骤
2019/01/23 PHP
DOM相关内容速查手册
2007/02/07 Javascript
JavaScript高级程序设计(第3版)学习笔记9 js函数(下)
2012/10/11 Javascript
js 实现在离开页面时提醒未保存的信息(减少用户重复操作)
2013/01/16 Javascript
JS截取字符串常用方法整理及使用示例
2013/10/18 Javascript
js自动生成对象的属性示例代码
2013/10/28 Javascript
初识Node.js
2014/09/03 Javascript
jquery实现手机号码选号的方法
2015/07/31 Javascript
基于jQuery实现的QQ表情插件
2015/08/25 Javascript
关于javascript事件响应的基础语法总结(必看篇)
2016/12/26 Javascript
VUE element-ui 写个复用Table组件的示例代码
2017/11/18 Javascript
vue2.0使用swiper组件实现轮播的示例代码
2018/03/03 Javascript
关于element-ui的隐藏组件el-scrollbar的使用
2019/05/29 Javascript
vue-cli3添加模式配置多环境变量的方法
2019/06/05 Javascript
electron实现静默打印的示例代码
2019/08/12 Javascript
[01:03:47]VP vs NewBee Supermajor 胜者组 BO3 第一场 6.5
2018/06/06 DOTA
[01:08:32]DOTA2-DPC中国联赛 正赛 DLG vs PHOENIX BO3 第二场 1月18日
2021/03/11 DOTA
Python使用迭代器捕获Generator返回值的方法
2017/04/05 Python
Flask web开发处理POST请求实现(登录案例)
2018/07/26 Python
Pandas中Series和DataFrame的索引实现
2019/06/27 Python
简单了解Python matplotlib线的属性
2019/06/29 Python
python利用xlsxwriter模块 操作 Excel
2020/10/14 Python
css3实现平移效果(transfrom:translate)的示例
2020/11/13 HTML / CSS
GUESS Factory加拿大:牛仔裤、服装及配饰
2019/09/20 全球购物
就业自我评价
2014/02/04 职场文书
趣味运动会策划方案
2014/06/02 职场文书
改革共识倡议书
2014/08/29 职场文书
民主生活会对照检查材料(统计局)
2014/09/21 职场文书
教师个人自我剖析材料
2014/09/29 职场文书
车间主任岗位职责
2015/02/03 职场文书
幼儿园新生开学寄语
2015/05/27 职场文书
革命电影观后感
2015/06/18 职场文书