a star dijkstra dfs可视化规划,通过pygame 在界面设定起止点和障碍物,趣味性强,适合新手学习。 路径规划 , pygame , 自动驾驶 有详细使用说明
今天咱们来搞点好玩的——用pygame做个能自由设置障碍物的路径规划可视化工具!不需要高深的算法基础,只要会点Python就能玩转。这个工具支持A*、Dijkstra和DFS三种算法实时演示,还能用鼠标画迷宫,特别适合刚入门的同学理解算法差异。
先看效果:深灰色是墙,亮色是探索过的区域,彩色路径会像贪吃蛇一样慢慢爬出来。按空格可以随时切换算法,亲眼看看不同算法探索路径的差异(比如DFS跑出来的路径可能扭成麻花~)
![可视化效果截图]
整个项目就一个py文件,核心代码不到200行。咱们先来看怎么用pygame画网格:
class Grid:
def __init__(self, rows, cols, size):
self.rows = rows
self.cols = cols
self.size = size
self.grid = [[Node(i, j) for j in range(cols)] for i in range(rows)]
def draw(self, screen):
for i in range(self.rows):
for j in range(self.cols):
color = self.grid[i][j].get_color()
pygame.draw.rect(screen, color,
(j*self.size, i*self.size,
self.size-1, self.size-1))
每个网格节点用Node对象存储状态(是否起点/终点/障碍物/已访问等)。这里有个小技巧:size-1让网格线自然显现,省去单独画线的麻烦。
事件处理是项目的灵魂部分。看这段鼠标交互逻辑:
if event.type == pygame.MOUSEBUTTONDOWN:
x, y = pygame.mouse.get_pos()
row, col = y // NODE_SIZE, x // NODE_SIZE
if event.button == 1: # 左键设起点
start = (row, col)
elif event.button == 3: # 右键设终点
end = (row, col)
elif event.button == 2: # 中键画墙
grid[row][col].toggle_wall()
重点说下A*算法的实现。和Dijkstra不同之处在于加入了启发式函数(这里用曼哈顿距离):
def heuristic(a, b):
return abs(a[0]-b[0]) + abs(a[1]-b[1])
open_set = PriorityQueue()
open_set.put((0, start))
came_from = {}
g_score = {node: float('inf') for row in grid for node in row}
g_score[start] = 0
while not open_set.empty():
current = open_set.get()[1]
if current == end:
break
for neighbor in get_neighbors(current):
tentative_g = g_score[current] + 1
if tentative_g < g_score[neighbor]:
came_from[neighbor] = current
g_score[neighbor] = tentative_g
f_score = tentative_g + heuristic(neighbor, end)
open_set.put((f_score, neighbor))
Dijkstra其实就是把启发函数设为零的A*,而DFS把优先队列换成栈就行。三个算法共用一套可视化逻辑,运行时切换算法变量即可。
使用说明(记得先pip install pygame):
- 左键单击设起点(绿色)
- 右键单击设终点(红色)
- 中键拖动画障碍(灰色)
- 空格键开始寻路,R键重置地图
- 数字键1/2/3切换算法(A*/Dijkstra/DFS)
- 按C键清空已探索区域
遇到死胡同时会弹窗提示,这时候可以随意修改地图再重新运行。建议故意画个U型墙,对比三种算法的探索过程——你会发现A*的探索区域最集中,DFS到处乱撞,而Dijkstra像水波扩散。
完整代码已打包在GitHub(地址见文末),包含自动寻路延迟效果、路径回溯等细节。这个项目稍加改造就能用在自动驾驶仿真中,比如把网格地图换成真实道路数据,把鼠标画墙改成导入高精地图的障碍物数据。
最后留个思考题:如果要让算法支持对角线移动,哪些地方需要修改?(提示:修改get_neighbors函数和启发函数)


被折叠的 条评论
为什么被折叠?



