迷宫路径规划:Python编程走迷宫的最优
迷宫路径规划:Python编程走迷宫的最优
走迷宫的最优解法,迷宫路径规划:
绿色起点和红色终点
灰色障碍物
黄色表示开放列表中的候选节点
蓝色表示已探索的关闭列表节点
红色线条显示最终路径
通过方向键1调节算法速度按 R 键重新生成迷宫
import pygame
import random
from heapq import heappush, heappop
from collections import deque
class VisualCell:
def __init__(self, x, y, cell_size):
self.rect = pygame.Rect(x * cell_size, y * cell_size, cell_size, cell_size)
self.walls = {'top': True, 'right': True, 'bottom': True, 'left': True}
self.is_obstacle = False
self.came_from = None
self.g_score = float('inf')
self.f_score = float('inf')
class PathFinder:
def __init__(self, cols=25, rows=25, cell_size=30):
self.cell_size = cell_size
self.cols = cols
self.rows = rows
self.grid = [[VisualCell(x, y, cell_size) for x in range(cols)] for y in range(rows)]
# 初始化起点终点
self.start = (0, 0)
self.end = (cols - 1, rows - 1)
self.generate_maze()
self.add_obstacles(0.25)
self.init_algorithm()
def init_algorithm(self):
# 初始化算法数据结构
self.open_set = []
self.closed_set = set()
self.path = deque()
self.found = False
self.done = False
start_cell = self.grid[self.start[1]][self.start[0]]
start_cell.g_score = 0
start_cell.f_score = self.heuristic(self.start, self.end)
heappush(self.open_set, (start_cell.f_score, self.start))
def generate_maze(self):
stack = [self.start]
visited = set(stack)
while stack:
x, y = stack.pop()
current = self.grid[y][x]
neighbors = []
# 获取未访问的邻居
directions = [
('left', x - 1, y),
('right', x + 1, y),
('top', x, y - 1),
('bottom', x, y + 1)
]
for direction in directions:
dir_name, nx, ny = direction
if 0 <= nx < self.cols and 0 <= ny < self.rows:
if (nx, ny) not in visited:
neighbors.append(direction)
if neighbors:
stack.append((x, y))
dir_name, nx, ny = random.choice(neighbors)
next_cell = self.grid[ny][nx]
# 拆除墙壁
if dir_name == 'left':
current.walls['left'] = False
next_cell.walls['right'] = False
elif dir_name == 'right':
current.walls['right'] = False
next_cell.walls['left'] = False
elif dir_name == 'top':
current.walls['top'] = False
next_cell.walls['bottom'] = False
elif dir_name == 'bottom':
current.walls['bottom'] = False
next_cell.walls['top'] = False
visited.add((nx, ny))
stack.append((nx, ny))
def add_obstacles(self, ratio):
candidates = [(x, y) for y in range(self.rows) for x in range(self.cols)
if (x, y) != self.start and (x, y) != self.end]
random.shuffle(candidates)
for x, y in candidates[:int(len(candidates) * ratio)]:
self.grid[y][x].is_obstacle = True
# 确保路径存在
while not self.verify_path():
if not candidates:
break
x, y = candidates.pop()
self.grid[y][x].is_obstacle = False
def verify_path(self):
temp_open = []
heappush(temp_open, (0, self.start))
visited = set()
while temp_open:
current_cost, current = heappop(temp_open)
if current == self.end:
return True
if current in visited:
continue
visited.add(current)
for dx, dy in [(-1, 0), (1, 0), (0, -1), (0, 1)]:
nx, ny = current[0] + dx, current[1] + dy
if 0 <= nx < self.cols and 0 <= ny < self.rows:
if self.grid[ny][nx].is_obstacle:
continue
if not self.can_pass(current, (nx, ny)):
continue
heappush(temp_open, (self.heuristic((nx, ny), self.end), (nx, ny)))
return False
def heuristic(self, a, b):
return abs(a[0] - b[0]) + abs(a[1] - b[1])
def can_pass(self, from_pos, to_pos):
fx, fy = from_pos
tx, ty = to_pos
cell = self.grid[fy][fx]
if tx == fx + 1: return not cell.walls['right']
if tx == fx - 1: return not cell.walls['left']
if ty == fy + 1: return not cell.walls['bottom']
if ty == fy - 1: return not cell.walls['top']
return False
def algorithm_step(self):
if self.done or not self.open_set:
return
current_f, current = heappop(self.open_set)
current_cell = self.grid[current[1]][current[0]]
if current == self.end:
self.reconstruct_path(current_cell)
self.done = True
return
self.closed_set.add(current)
for dx, dy in [(-1, 0), (1, 0), (0, -1), (0, 1)]:
nx, ny = current[0] + dx, current[1] + dy
if 0 <= nx < self.cols and 0 <= ny < self.rows:
neighbor_cell = self.grid[ny][nx]
if neighbor_cell.is_obstacle or (nx, ny) in self.closed_set:
continue
if not self.can_pass(current, (nx, ny)):
continue
tentative_g = current_cell.g_score + 1
if tentative_g < neighbor_cell.g_score:
neighbor_cell.came_from = current_cell
neighbor_cell.g_score = tentative_g
neighbor_cell.f_score = tentative_g + self.heuristic((nx, ny), self.end)
heappush(self.open_set, (neighbor_cell.f_score, (nx, ny)))
def reconstruct_path(self, end_cell):
current = end_cell
while current is not None:
x = current.rect.x // self.cell_size
y = current.rect.y // self.cell_size
self.path.appendleft((x, y))
current = current.came_from
class Visualization:
def __init__(self):
pygame.init()
self.finder = PathFinder()
self.screen = pygame.display.set_mode(
(self.finder.cols * self.finder.cell_size,
self.finder.rows * self.finder.cell_size))
pygame.display.set_caption("Maze Pathfinding Visualization")
self.clock = pygame.time.Clock()
self.speed = 20 # 初始速度:20步/秒
def draw_grid(self):
self.screen.fill((255, 255, 255))
# 绘制所有单元格
for y in range(self.finder.rows):
for x in range(self.finder.cols):
cell = self.finder.grid[y][x]
color = (255, 255, 255)
if cell.is_obstacle:
color = (100, 100, 100)
elif (x, y) == self.finder.start:
color = (0, 255, 0)
elif (x, y) == self.finder.end:
color = (255, 0, 0)
pygame.draw.rect(self.screen, color, cell.rect.inflate(-2, -2))
# 绘制墙壁
if cell.walls['top']:
pygame.draw.line(self.screen, (0, 0, 0),
(cell.rect.left, cell.rect.top),
(cell.rect.right, cell.rect.top), 2)
if cell.walls['right']:
pygame.draw.line(self.screen, (0, 0, 0),
(cell.rect.right, cell.rect.top),
(cell.rect.right, cell.rect.bottom), 2)
if cell.walls['bottom']:
pygame.draw.line(self.screen, (0, 0, 0),
(cell.rect.right, cell.rect.bottom),
(cell.rect.left, cell.rect.bottom), 2)
if cell.walls['left']:
pygame.draw.line(self.screen, (0, 0, 0),
(cell.rect.left, cell.rect.bottom),
(cell.rect.left, cell.rect.top), 2)
# 绘制算法状态
self.draw_algorithm_state()
self.draw_path()
pygame.display.flip()
def draw_algorithm_state(self):
# 开放列表(黄色)
for _, (x, y) in self.finder.open_set:
rect = self.finder.grid[y][x].rect.inflate(-8, -8)
pygame.draw.rect(self.screen, (255, 255, 0), rect)
# 关闭列表(蓝色)
for pos in self.finder.closed_set:
x, y = pos
rect = self.finder.grid[y][x].rect.inflate(-8, -8)
pygame.draw.rect(self.screen, (0, 0, 255), rect)
def draw_path(self):
if self.finder.path:
path = list(self.finder.path)
for i in range(len(path) - 1):
start = (path[i][0] * self.finder.cell_size + self.finder.cell_size // 2,
path[i][1] * self.finder.cell_size + self.finder.cell_size // 2)
end = (path[i + 1][0] * self.finder.cell_size + self.finder.cell_size // 2,
path[i + 1][1] * self.finder.cell_size + self.finder.cell_size // 2)
pygame.draw.line(self.screen, (255, 0, 0), start, end, 4)
def run(self):
last_update = 0
running = True
while running:
current_time = pygame.time.get_ticks()
# 处理事件
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_r: # 重置
self.finder = PathFinder()
elif event.key == pygame.K_UP: # 加速
self.speed = min(100, self.speed + 5)
elif event.key == pygame.K_DOWN: # 减速
self.speed = max(1, self.speed - 5)
# 更新算法
if current_time - last_update > 1000 // self.speed and not self.finder.done:
self.finder.algorithm_step()
last_update = current_time
# 绘制界面
self.draw_grid()
self.clock.tick(60)
pygame.quit()
if __name__ == "__main__":
vis = Visualization()
vis.run()
原文地址:https://blog.csdn.net/2301_76444133/article/details/146440124
免责声明:本站文章内容转载自网络资源,如侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!