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), len(visited) ) for neighbor in maze.getNeighbors(current): if neighbor not in visited: visited.add( neighbor ) parent[ neighbor ] = current queue.append( neighbor ) return [], len(visited) 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), len(visited) ) for neighbor in maze.getNeighbors(current): if neighbor not in visited: visited.add( neighbor ) parent[ neighbor ] = current stack.append( neighbor ) return [], len(visited) 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), len(visited) ) 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 [], len(visited)