forked from UNN/2026-rff_mp
169 lines
8.2 KiB
Python
169 lines
8.2 KiB
Python
Отчёт ко 2 заданию
|
||
|
||
1. Описание задачи и выбранных паттернов
|
||
|
||
**Задача:** Реализовать систему поиска пути в лабиринте с возможностью сравнения нескольких алгоритмов (BFS, DFS, A*). Система должна поддерживать разные способы построения лабиринта и позволять легко добавлять новые алгоритмы поиска.
|
||
|
||
Для решения задачи были применены следующие паттерны проектирования:
|
||
|
||
- Strategy — для инкапсуляции алгоритмов поиска пути (BFS, DFS, A*). Позволяет динамически менять стратегию поиска.
|
||
- Builder — для построения лабиринта из файла. Отделяет процесс создания лабиринта от его представления.
|
||
|
||
Эти паттерны обеспечивают гибкость и расширяемость системы.
|
||
|
||
Диаграмма классов (Mermaid)
|
||
|
||
```mermaid
|
||
classDiagram
|
||
class Maze {
|
||
+width: int
|
||
+height: int
|
||
+cells: List~List~Cell~~
|
||
+start: Cell
|
||
+exit: Cell
|
||
+getCell(x, y)
|
||
+getNeighbors(cell)
|
||
}
|
||
|
||
class Cell {
|
||
+x: int
|
||
+y: int
|
||
+is_wall: bool
|
||
+is_start: bool
|
||
+is_exit: bool
|
||
+isPassable()
|
||
}
|
||
|
||
class PathFindingStrategy {
|
||
<<interface>>
|
||
+findPath(maze, start, exit)
|
||
}
|
||
|
||
class BFSStrategy {
|
||
+findPath(maze, start, exit)
|
||
}
|
||
|
||
class DFSStrategy {
|
||
+findPath(maze, start, exit)
|
||
}
|
||
|
||
class AStarStrategy {
|
||
+findPath(maze, start, exit)
|
||
-heuristic(a, b)
|
||
}
|
||
|
||
class MazeSolver {
|
||
-maze: Maze
|
||
-strategy: PathFindingStrategy
|
||
+setStrategy(strategy)
|
||
+solve()
|
||
}
|
||
|
||
class MazeBuilder {
|
||
<<interface>>
|
||
+buildFromFile(filename)
|
||
}
|
||
|
||
class TextFileMazeBuilder {
|
||
+buildFromFile(filename)
|
||
}
|
||
|
||
Maze "1" *-- "many" Cell
|
||
MazeSolver --> PathFindingStrategy
|
||
PathFindingStrategy <|-- BFSStrategy
|
||
PathFindingStrategy <|-- DFSStrategy
|
||
PathFindingStrategy <|-- AStarStrategy
|
||
MazeBuilder <|-- TextFileMazeBuilder
|
||
```
|
||
|
||
2. Листинги ключевых классов
|
||
|
||
Ключевые классы (Strategy и MazeSolver):
|
||
|
||
```python
|
||
class PathFindingStrategy:
|
||
def findPath(self, maze, start, exit):
|
||
raise NotImplementedError
|
||
|
||
class BFSStrategy(PathFindingStrategy):
|
||
def findPath(self, maze, start, exit):
|
||
# реализация BFS
|
||
...
|
||
|
||
class DFSStrategy(PathFindingStrategy):
|
||
def findPath(self, maze, start, exit):
|
||
# реализация DFS
|
||
...
|
||
|
||
class AStarStrategy(PathFindingStrategy):
|
||
def findPath(self, maze, start, exit):
|
||
# реализация A*
|
||
...
|
||
```
|
||
|
||
```python
|
||
class MazeSolver:
|
||
def __init__(self, maze=None, strategy=None):
|
||
self.maze = maze
|
||
self.strategy = strategy
|
||
|
||
def setStrategy(self, strategy):
|
||
self.strategy = strategy
|
||
|
||
def solve(self):
|
||
if not self.maze or not self.strategy:
|
||
return None
|
||
# замер времени и вызов стратегии
|
||
...
|
||
```
|
||
|
||
Полный код доступен в репозитории (или может быть предоставлен по запросу).
|
||
|
||
3. Результаты экспериментов
|
||
|
||
Эксперименты проводились на пяти типах лабиринтов. Ниже представлены ключевые результаты.
|
||
|
||
Сводная таблица (средние значения):
|
||
|
||
| Лабиринт | Стратегия | Время (мс) | Посещено клеток | Длина пути |
|
||
|-------------------------|-----------|------------|------------------|------------|
|
||
| 10x10_simple | BFS | 0.07 | 90 | 37 |
|
||
| 10x10_simple | DFS | 0.03 | 67 | 37 |
|
||
| 10x10_simple | A* | 0.09 | 76 | 19 |
|
||
| 50x50_with_deadends | BFS | 1.29 | 1657 | 0 |
|
||
| 50x50_with_deadends | DFS | 0.64 | 993 | 243 |
|
||
| 50x50_with_deadends | A* | 0.56 | 440 | 101 |
|
||
| 100x100_complex | BFS | 4.40 | 5735 | 1 |
|
||
| 100x100_complex | DFS | 4.33 | 5735 | 1 |
|
||
| 100x100_complex | A* | 7.03 | 5735 | 1 |
|
||
| empty | BFS | 0.68 | 900 | 0 |
|
||
| empty | DFS | 0.39 | 900 | 465 |
|
||
| empty | A* | 1.04 | 900 | 59 |
|
||
|
||
Графики (сохранены в папке `results/`):
|
||
- `time_comparison.png` — сравнение времени работы алгоритмов
|
||
- `visited_comparison.png` — сравнение количества посещённых клеток
|
||
|
||
4. Анализ эффективности алгоритмов и применимости паттернов
|
||
|
||
- **BFS** показывает стабильную работу и находит кратчайший путь, но посещает больше клеток.
|
||
- **DFS** быстрее всех на простых и пустых лабиринтах, однако не гарантирует оптимальность.
|
||
- **A*** эффективнее всего по количеству посещённых клеток на сложных лабиринтах, но на больших картах проигрывает по времени из-за overhead приоритетной очереди.
|
||
|
||
Паттерн **Strategy** позволил легко переключаться между алгоритмами без изменения кода `MazeSolver`. Паттерн **Builder** сделал возможным добавление новых источников построения лабиринта (например, генератор случайных лабиринтов) без изменения основной логики.
|
||
|
||
5. Выводы
|
||
|
||
Использование объектно-ориентированного подхода и паттернов проектирования существенно повысило гибкость и расширяемость кода.
|
||
|
||
Преимущества:
|
||
- Благодаря паттерну **Strategy** добавление нового алгоритма поиска (например, Dijkstra) требует только реализации интерфейса `PathFindingStrategy` без изменения `MazeSolver`.
|
||
- Паттерн **Builder** позволяет легко подключать новые способы загрузки лабиринтов.
|
||
- Код стал более читаемым и поддерживаемым.
|
||
|
||
Что было бы сложно изменить без паттернов:
|
||
- Замена алгоритма поиска потребовала бы значительных изменений в классе `MazeSolver` (много условных операторов `if`).
|
||
- Добавление нового способа построения лабиринта привело бы к дублированию кода.
|
||
- Сравнительный эксперимент было бы гораздо сложнее проводить, так как алгоритмы не были бы унифицированы через общий интерфейс.
|
||
|
||
Таким образом, применение паттернов Strategy и Builder сделало систему легко расширяемой и удобной для проведения экспериментов. |