Python迷宮生成和迷宮破解算法實(shí)例
迷宮生成
1.隨機(jī)PRIM
思路:先讓迷宮中全都是墻,不斷從列表(最初只含有一個啟始單元格)中選取一個單元格標(biāo)記為通路,將其周圍(上下左右)未訪問過的單元格放入列表并標(biāo)記為已訪問,再隨機(jī)選取該單元格與周圍通路單元格(若有的話)之間的一面墻打通。重復(fù)以上步驟直到列表為空,迷宮生成完畢。這種方式生成的迷宮難度高,岔口多。
效果:

代碼:
import random
import numpy as np
from matplotlib import pyplot as plt
def build_twist(num_rows, num_cols): # 扭曲迷宮
# (行坐標(biāo),列坐標(biāo),四面墻的有無&訪問標(biāo)記)
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 # 標(biāo)記為通路
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 # 標(biāo)記為已訪問
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.深度優(yōu)先
思路:從起點(diǎn)開始隨機(jī)游走并在前進(jìn)方向兩側(cè)建立墻壁,標(biāo)記走過的單元格,當(dāng)無路可走(周圍無未訪問過的單元格)時重復(fù)返回上一個格子直到有新的未訪問單元格可走。最終所有單元格都被訪問過后迷宮生成完畢。這種方式生成的迷宮較為簡單,由一條明顯但是曲折的主路徑和不多的分支路徑組成。
效果:

代碼:
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 # 標(biāo)記為已訪問
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
迷宮破解
效果:


1.填坑法
思路:從起點(diǎn)開始,不斷隨機(jī)選擇沒墻的方向前進(jìn),當(dāng)處于一個坑(除了來時的方向外三面都是墻)中時,退一步并建造一堵墻將坑封上。不斷重復(fù)以上步驟,最終就能抵達(dá)終點(diǎn)。
優(yōu)缺點(diǎn):可以處理含有環(huán)路的迷宮,但是處理時間較長還需要更多的儲存空間。
代碼:
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) # 隨機(jī)選一個方向走
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() # 行動坐標(biāo)記錄的反轉(zhuǎn)
i = 0
while i < len(xy_list)-1: # 去掉重復(fù)的移動步驟
j = (len(xy_list)-1) - r_list.index(xy_list[i])
if i != j: # 說明這兩個坐標(biāo)之間的行動步驟都是多余的,因為一頓移動回到了原坐標(biāo)
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.回溯法
思路:遇到岔口則將岔口坐標(biāo)和所有可行方向壓入棧,從棧中彈出一個坐標(biāo)和方向,前進(jìn)。不斷重復(fù)以上步驟,最終就能抵達(dá)終點(diǎn)。
優(yōu)缺點(diǎn):計算速度快,需要空間小,但無法處理含有環(huán)路的迷宮。
代碼:
def solve_backtrack(num_rows, num_cols, map_arr): # 回溯法
move_list = ['R']
m = 1 # 回溯點(diǎn)組號
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())) # 記錄當(dāng)前坐標(biāo)和可行移動方向
if mark:
r, c, m, go = mark.pop()
del move_list[m:] # 刪除回溯點(diǎn)之后的移動
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迷宮生成和迷宮破解算法實(shí)例就是小編分享給大家的全部內(nèi)容了,希望能給大家一個參考,也希望大家多多支持腳本之家。
- 如何用 Python 制作一個迷宮游戲
- Python 實(shí)現(xiàn)遞歸法解決迷宮問題的示例代碼
- 10分鐘教你用python動畫演示深度優(yōu)先算法搜尋逃出迷宮的路徑
- Python解決走迷宮問題算法示例
- 一道python走迷宮算法題
- Python深度優(yōu)先算法生成迷宮
- Python使用Tkinter實(shí)現(xiàn)機(jī)器人走迷宮
- Python基于分水嶺算法解決走迷宮游戲示例
- Python使用回溯法子集樹模板解決迷宮問題示例
- Python基于遞歸算法實(shí)現(xiàn)的走迷宮問題
- 用Python代碼來解圖片迷宮的方法整理
- python實(shí)現(xiàn)的生成隨機(jī)迷宮算法核心代碼分享(含游戲完整代碼)
- 教你怎么用Python實(shí)現(xiàn)多路徑迷宮
相關(guān)文章
python?selenium.webdriver?爬取政策文件的實(shí)現(xiàn)
本文主要介紹了python?selenium.webdriver?爬取政策文件的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-07-07
python+selenium+autoit實(shí)現(xiàn)文件上傳功能
這篇文章主要介紹了python+selenium+autoit實(shí)現(xiàn)文件上傳功能,需要的朋友可以參考下2017-08-08
Python實(shí)現(xiàn)OpenCV中文路徑圖片讀寫的詳細(xì)指南
在Python中使用OpenCV處理圖片時,涉及讀取和保存圖片的操作,可能會遇到中文路徑的兼容性問題,該指南的目的是展示如何正確處理帶有中文路徑的圖片,并使用OpenCV將圖片保存到指定的中文路徑,需要的朋友可以參考下2025-03-03
python nohup 實(shí)現(xiàn)遠(yuǎn)程運(yùn)行不宕機(jī)操作
這篇文章主要介紹了python nohup 實(shí)現(xiàn)遠(yuǎn)程運(yùn)行不宕機(jī)操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-04-04
4種Python基于字段的不使用元類的ORM實(shí)現(xiàn)方法總結(jié)
在 Python 中,ORM(Object-Relational Mapping)是一種將對象和數(shù)據(jù)庫之間的映射關(guān)系進(jìn)行轉(zhuǎn)換的技術(shù),本文為大家整理了4種不使用元類的簡單ORM實(shí)現(xiàn)方式,需要的可以參考下2023-12-12
jupyter關(guān)于pandas的dataframe行列顯示不全與復(fù)原問題
這篇文章主要介紹了jupyter關(guān)于pandas的dataframe行列顯示不全與復(fù)原問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-02-02

