forked from UNN/2026-rff_mp
Реализован Этап 5
This commit is contained in:
parent
107d5cbd61
commit
74928a997a
4
MusinAA/task2/mazeObjects/path.py
Normal file
4
MusinAA/task2/mazeObjects/path.py
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
class Path:
|
||||
def __init__(self, array:list[Cell]|None, visited_cells:int):
|
||||
self.array = array
|
||||
self.visited_cells = visited_cells
|
||||
43
MusinAA/task2/mazeSolver.py
Normal file
43
MusinAA/task2/mazeSolver.py
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
from task2.mazeObjects.maze import Maze
|
||||
from task2.mazeObjects.cell import Cell
|
||||
from task2.strategyObjects.pathFindingStrategy import PathFindingStrategy
|
||||
|
||||
import time
|
||||
|
||||
class SearchStats:
|
||||
"""Время выполнения в миллисекундах, количество посещённых клеток, длина найденного пути"""
|
||||
def __init__(self, path: list[Cell]|None, duration:float, visited_cells:int, path_len:int, strategy_name:str):
|
||||
self.duration = duration
|
||||
self.visited_cells = visited_cells
|
||||
self.path_len = path_len
|
||||
self.path = path
|
||||
self.strategy_name = strategy_name
|
||||
|
||||
class MazeSolver:
|
||||
"""
|
||||
MazeSolver содержит поля maze и strategy.
|
||||
Метод setStrategy(strategy) для динамической смены алгоритма.
|
||||
Метод solve() вызывает strategy.findPath(...) и возвращает объект SearchStats (время выполнения в миллисекундах,
|
||||
количество посещённых клеток, длина найденного пути).
|
||||
Для замера времени используйте time.perf_counter() до и после вызова стратегии.
|
||||
"""
|
||||
|
||||
def __init__(self, maze:Maze, strategy:PathFindingStrategy):
|
||||
self.maze = maze
|
||||
self.strategy = strategy
|
||||
|
||||
def setStrategy(self, strategy:PathFindingStrategy):
|
||||
self.strategy = strategy
|
||||
|
||||
def getStrategyName(self):
|
||||
return self.strategy.__class__.__name__
|
||||
|
||||
def solve(self):
|
||||
t_start = time.perf_counter()
|
||||
path = self.strategy.findPath(self.maze, self.maze.startCell, self.maze.endCell)
|
||||
duration = time.perf_counter() - t_start
|
||||
|
||||
path_len = len(path.array) if path.array else 0
|
||||
strategy_name = self.getStrategyName()
|
||||
|
||||
return SearchStats(path.array, duration, path.visited_cells, path_len, strategy_name)
|
||||
|
|
@ -6,13 +6,14 @@ from task2.strategyObjects.util import restorePath
|
|||
|
||||
from task2.mazeObjects.maze import Maze
|
||||
from task2.mazeObjects.cell import Cell
|
||||
from task2.mazeObjects.path import Path
|
||||
|
||||
class AStar(PathFindingStrategy):
|
||||
"""Алгоритм с эвристикой (etc. манхэттенское расстояние) – компромисс между скоростью и оптимальностью."""
|
||||
def heuristic(self, first: Cell, second: Cell) -> int:
|
||||
return abs(first.x - second.x) + abs(first.y - second.y)
|
||||
|
||||
def findPath(self, maze: Maze, start: Cell, exit: Cell):
|
||||
def findPath(self, maze: Maze, start: Cell, exit: Cell) -> Path:
|
||||
tie_breaker = count()
|
||||
start_heuristic = self.heuristic(start, exit)
|
||||
heap: list[tuple[int, int, int, Cell]] = [
|
||||
|
|
@ -29,7 +30,7 @@ class AStar(PathFindingStrategy):
|
|||
visited.add(current)
|
||||
|
||||
if current == exit:
|
||||
return restorePath(parents, exit)
|
||||
return Path(restorePath(parents, exit), len(visited))
|
||||
|
||||
for neighbor in maze.getNeighbors(current):
|
||||
tentative_score = g_score[current]
|
||||
|
|
@ -42,4 +43,4 @@ class AStar(PathFindingStrategy):
|
|||
heap,
|
||||
(priority, heuristic, next(tie_breaker), neighbor),
|
||||
)
|
||||
return []
|
||||
return Path(None, len(visited))
|
||||
|
|
@ -3,13 +3,14 @@ from task2.strategyObjects.util import restorePath
|
|||
|
||||
from task2.mazeObjects.maze import Maze
|
||||
from task2.mazeObjects.cell import Cell
|
||||
from task2.mazeObjects.path import Path
|
||||
|
||||
import queue
|
||||
|
||||
class BFS(PathFindingStrategy):
|
||||
"""Поиск в ширину – гарантирует кратчайший путь по количеству шагов.
|
||||
Возвращает None, если пути нет"""
|
||||
def findPath(self, maze: Maze, start: Cell, exit: Cell):
|
||||
def findPath(self, maze: Maze, start: Cell, exit: Cell) -> Path:
|
||||
visited = dict()
|
||||
parents = dict()
|
||||
q = queue.Queue()
|
||||
|
|
@ -31,4 +32,5 @@ class BFS(PathFindingStrategy):
|
|||
visited[hood] = visited[current] + 1
|
||||
parents[hood] = current
|
||||
q.put(hood)
|
||||
return restorePath(parents, exit)
|
||||
|
||||
return Path(restorePath(parents, exit), len(visited))
|
||||
|
|
@ -3,12 +3,12 @@ from task2.strategyObjects.util import restorePath
|
|||
|
||||
from task2.mazeObjects.maze import Maze
|
||||
from task2.mazeObjects.cell import Cell
|
||||
|
||||
from task2.mazeObjects.path import Path
|
||||
|
||||
class DFS(PathFindingStrategy):
|
||||
"""Поиск в глубину – быстрый, но не обязательно кратчайший.
|
||||
Возвращает None, если пути нет"""
|
||||
def findPath(self, maze: Maze, start: Cell, exit: Cell):
|
||||
def findPath(self, maze: Maze, start: Cell, exit: Cell) -> Path:
|
||||
visited = dict()
|
||||
parents = dict()
|
||||
stack = []
|
||||
|
|
@ -31,4 +31,4 @@ class DFS(PathFindingStrategy):
|
|||
parents[hood] = current
|
||||
stack.append(hood)
|
||||
|
||||
return restorePath(parents, exit)
|
||||
return Path(restorePath(parents, exit), len(visited))
|
||||
|
|
@ -2,12 +2,13 @@ from abc import ABC, abstractmethod
|
|||
|
||||
from task2.mazeObjects.maze import Maze
|
||||
from task2.mazeObjects.cell import Cell
|
||||
from task2.mazeObjects.path import Path
|
||||
|
||||
class PathFindingStrategy(ABC):
|
||||
"""Интерфейс PathFindingStrategy с методом findPath(maze, start, exit),
|
||||
возвращающим список клеток пути (от старта до выхода включительно) или пустой список, если пути нет."""
|
||||
|
||||
@abstractmethod
|
||||
def findPath(self, maze: Maze, start: Cell, exit: Cell):
|
||||
def findPath(self, maze: Maze, start: Cell, exit: Cell) -> Path:
|
||||
"""Возвращает список клеток пути от старта до выхода включительно. Пути нет - пустой список."""
|
||||
raise NotImplementedError
|
||||
Loading…
Reference in New Issue
Block a user