Python迷宮生成和迷宮破解算法實(shí)例
迷宮生成
1.隨機(jī)PRIM
思路:先讓迷宮中全都是墻,不斷從列表(最初只含有一個(gè)啟始單元格)中選取一個(gè)單元格標(biāo)記為通路,將其周圍(上下左右)未訪問(wèn)過(guò)的單元格放入列表并標(biāo)記為已訪問(wèn),再隨機(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),四面墻的有無(wú)&訪問(wèn)標(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)記為已訪問(wèn)
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)記走過(guò)的單元格,當(dāng)無(wú)路可走(周圍無(wú)未訪問(wèn)過(guò)的單元格)時(shí)重復(fù)返回上一個(gè)格子直到有新的未訪問(wèn)單元格可走。最終所有單元格都被訪問(wèn)過(guò)后迷宮生成完畢。這種方式生成的迷宮較為簡(jiǎn)單,由一條明顯但是曲折的主路徑和不多的分支路徑組成。
效果:

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

