from collections import deque import heapq from math import inf class PathFindingStrategy: def findPath(self, maze, start, exit): raise NotImplementedError def reconstruct_path(parent, start, goal): if goal not in parent and goal != start: return [] path = [] cur = goal while cur != start: path.append(cur) cur = parent[cur] path.append(start) path.reverse() return path class BFSStrategy(PathFindingStrategy): def findPath(self, maze, start, exit): queue = deque([start]) visited = {start} parent = {} visited_count = 0 while queue: current = queue.popleft() visited_count += 1 if current == exit: path = reconstruct_path(parent, start, exit) return path, visited_count for nxt in maze.getNeighbors(current): if nxt not in visited: visited.add(nxt) parent[nxt] = current queue.append(nxt) return [], visited_count class DFSStrategy(PathFindingStrategy): def findPath(self, maze, start, exit): stack = [start] visited = {start} parent = {} visited_count = 0 while stack: current = stack.pop() visited_count += 1 if current == exit: path = reconstruct_path(parent, start, exit) return path, visited_count for nxt in maze.getNeighbors(current): if nxt not in visited: visited.add(nxt) parent[nxt] = current stack.append(nxt) return [], visited_count class AStarStrategy(PathFindingStrategy): def h(self, a, b): return abs(a.x - b.x) + abs(a.y - b.y) def findPath(self, maze, start, exit): open_heap = [] heapq.heappush(open_heap, (0, 0, start)) parent = {} g = {start: 0} visited = set() visited_count = 0 counter = 1 while open_heap: _, _, current = heapq.heappop(open_heap) if current in visited: continue visited.add(current) visited_count += 1 if current == exit: path = reconstruct_path(parent, start, exit) return path, visited_count for nxt in maze.getNeighbors(current): tentative_g = g[current] + nxt.weight if tentative_g < g.get(nxt, inf): g[nxt] = tentative_g parent[nxt] = current f = tentative_g + self.h(nxt, exit) heapq.heappush(open_heap, (f, counter, nxt)) counter += 1 return [], visited_count