我们定义一个 Maze 类,用二维数组表示迷宫地图,其中 1 表示墙壁,0 表示路,然后初始化左上角为入口,右下角为出口,最后定义下方向向量。
class Maze:
def init(self, width, height):
self.width = width
self.height = height
self.map = [[0 if x % 2 == 1 and y % 2 == 1 else 1 for x in range(width)] for y in range(height)]
self.map[1][0] = 0 # 入口
self.map[height - 2][width - 1] = 0 # 出口
self.visited = []
right up left down
self.dx = [1, 0, -1, 0]
self.dy = [0, -1, 0, 1]
接下来就是生成迷宫的主函数了。
‘’’
遇到问题没人解答?小编创建了一个Python学习交流QQ群:531509025
寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
‘’’
def generate(self):
start = [1, 1]
self.visited.append(start)
wall_list = self.get_neighbor_wall(start)
while wall_list:
wall_position = random.choice(wall_list)
neighbor_road = self.get_neighbor_road(wall_position)
wall_list.remove(wall_position)
self.deal_with_not_visited(neighbor_road[0], wall_position, wall_list)
self.deal_with_not_visited(neighbor_road[1], wall_position, wall_list)
该函数里面有两个主要函数 get_neighbor_road(point)
和deal_with_not_visited()
,前者会获得传入坐标点 point 的邻路节点,返回值是一个二维数组,后者 deal_with_not_visited()
函数处理步骤 4.1 的逻辑。
由于 Prim 随机算法是随机的从列表中的所有的单元格进行随机选择,新加入的单元格和旧加入的单元格被选中的概率是一样的,因此其分支较多,生成的迷宫较复杂,难度较大,当然看起来也更自然些。生成的迷宫。
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]
[1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1]
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]
[1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1]
[1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1]
[1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1]
[1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1]
[1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1]
[1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0]
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
走出迷宫
得到了迷宫的地图,接下来就按照我们文首的思路来走迷宫即可。主要函数逻辑如下:
def dfs(self, x, y, path, visited=[]):
outOfIndex
if self.is_out_of_index(x, y):
return False
visited or is wall
if [x, y] in visited or self.get_value([x, y]) == 1:
return False
visited.append([x, y])
path.append([x, y])
end…
if x == self.width - 2 and y == self.height - 2:
return True
recursive
for i in range(4):
if 0 < x + self.dx[i] < self.width - 1 and 0 < y + self.dy[i] < self.height - 1 and
self.get_value([x + self.dx[i], y + self.dy[i]]) == 0:
if self.dfs(x + self.dx[i], y + self.dy[i], path, visited):
return True
elif not self.is_out_of_index(x, y) and path[-1] != [x, y]:
path.append([x, y])
很明显,这就是一个典型的递归程序。当该节点坐标越界、该节点被访问过或者该节点是墙壁的时候,直接返回,因为该节点肯定不是我们要找的路径的一部分,否则就将该节点加入被访问过的节点和路径的集合中。
然后如果该节点是出口则表示程序执行结束,找到了通路。不然就遍历四个方向向量,将节点的邻路传入函数 dfs 继续以上步骤,直到找到出路或者程序所有节点都遍历完成。
来看看我们 dfs 得出的路径结果:
[[0, 1], [1, 1], [2, 1], [3, 1], [4, 1], [5, 1], [6, 1], [7, 1], [8, 1], [9, 1], [9, 1], [8, 1], [7, 1], [6, 1], [5, 1], [5, 2], [5, 3], [6, 3], [7, 3], [8, 3], [9, 3], [9, 4], [9, 5], [9, 5], [9, 4], [9, 3], [8, 3], [7, 3], [7, 4], [7, 5], [7, 5], [7, 4], [7, 3], [6, 3], [5, 3], [4, 3], [3, 3], [2, 3], [1, 3], [1, 3], [2, 3], [3, 3], [3, 4], [3, 5], [2, 5], [1, 5], [1, 6], [1, 7], [1, 8], [1, 9], [1, 9], [1, 8], [1, 7], [1, 6], [1, 5], [2, 5], [3, 5], [3, 6], [3, 7], [3, 8], [3, 9], [3, 9], [3, 8], [3, 7], [3, 6], [3, 5], [3, 4], [3, 3], [4, 3], [5, 3], [5, 4], [5, 5], [5, 6], [5, 7], [6, 7], [7, 7], [8, 7], [9, 7], [9, 8], [9, 9], [10, 9]]
可视化
有了迷宫地图和通路路径,剩下的工作就是将这些坐标点渲染出来。今天我们用的可视化库是 pyxel,这是一个用来写像素级游戏的 Python 库,
当然使用前需要先安装下这个库。
Win 用户直接用 pip install -U pyxel
命令安装即可。
Mac 用户使用以下命令安装:
brew install python3 gcc sdl2 sdl2_image gifsicle
pip3 install -U pyxel
先来看个简单的 Demo。
‘’’
遇到问题没人解答?小编创建了一个Python学习交流QQ群:531509025
寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
‘’’
class App:
def init(self):
pyxel.init(160, 120)
self.x = 0
pyxel.run(self.update, self.draw)
def update(self):
self.x = (self.x + 1) % pyxel.width
def draw(self):
pyxel.cls(0)
pyxel.rect(self.x, 0, 8, 8, 9)
App()
类 App 的执行逻辑就是不断的调用 update 函数和 draw 函数,因此可以在 update 函数中更新物体的坐标,然后在 draw 函数中将图像画到屏幕即可。
如此我们就先把迷宫画出来,然后在渲染 dfs 遍历动画。
width, height = 37, 21
my_maze = Maze(width, height)
my_maze.generate()
class App:
def init(self):
pyxel.init(width * pixel, height * pixel)
pyxel.run(self.update, self.draw)
def update(self):
if pyxel.btn(pyxel.KEY_Q):
pyxel.quit()
if pyxel.btn(pyxel.KEY_S):
self.death = False
def draw(self):
draw maze
for x in range(height):
for y in range(width):
color = road_color if my_maze.map[x][y] is 0 else wall_color
pyxel.rect(y * pixel, x * pixel, pixel, pixel, color)
pyxel.rect(0, pixel, pixel, pixel, start_point_color)
pyxel.rect((width - 1) * pixel, (height - 2) * pixel, pixel, pixel, end_point_color)
App()
看起来还可以,这里的宽和高我分别用了 37 和 21 个像素格来生成,所以生成的迷宫不是很复杂,如果像素点很多的话就会错综复杂了。
接下里来我们就需要修改 update 函数和 draw 函数来渲染路径了。为了方便操作,我们在 init 函数中新增几个属性。
self.index = 0
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Python工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Python开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以扫码获取!!!(备注:Python)
链图片转存中…(img-egnkdLfo-1713801411817)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以扫码获取!!!(备注:Python)