from abc import ABC, abstractmethod from collections import deque import heapq class PathFindingStrategy(ABC): @abstractmethod def findPath(self, maze, start, exit_cell): pass def restorePath( self, parent, start, exit_cell ): path = [] current = exit_cell while current != start: path.append(current) current = parent[current] path.append(start) path.reverse() return path class BFSStrategy(PathFindingStrategy): def findPath( self, maze, start, exit_cell ): queue = deque([start]) visited = {start} parent = {} while queue: current = queue.popleft() if current == exit_cell: return self.restorePath( parent, start, exit_cell ) for neighbor in maze.getNeighbors(current): if neighbor not in visited: visited.add( neighbor ) parent[ neighbor ] = current queue.append( neighbor ) return [] class DFSStrategy(PathFindingStrategy): def findPath( self, maze, start, exit_cell ): stack = [start] visited = {start} parent = {} while stack: current = stack.pop() if current == exit_cell: return self.restorePath( parent, start, exit_cell ) for neighbor in maze.getNeighbors(current): if neighbor not in visited: visited.add( neighbor ) parent[ neighbor ] = current stack.append( neighbor ) return [] class AStarStrategy(PathFindingStrategy): def heuristic( self, cell, exit_cell ): return ( abs( cell.x - exit_cell.x ) + abs( cell.y - exit_cell.y ) ) def findPath( self, maze, start, exit_cell ): pq = [] heapq.heappush( pq, ( 0, id(start), start ) ) parent = {} g_score = { start: 0 } visited = set() while pq: _, _, current = ( heapq.heappop( pq ) ) if current in visited: continue visited.add( current ) if current == exit_cell: return self.restorePath( parent, start, exit_cell ) for neighbor in maze.getNeighbors(current): new_cost = ( g_score[current] + 1 ) if ( neighbor not in g_score or new_cost < g_score[neighbor] ): g_score[ neighbor ] = new_cost parent[ neighbor ] = current priority = ( new_cost + self.heuristic( neighbor, exit_cell ) ) heapq.heappush( pq, ( priority, id(neighbor), neighbor ) ) return []