forked from UNN/2026-rff_mp
134 lines
4.9 KiB
Markdown
134 lines
4.9 KiB
Markdown
# Отчёт по лабораторной работе №2
|
||
## Поиск выхода из лабиринта
|
||
## Цель работы
|
||
Разработать гибкую, расширяемую программу для загрузки лабиринта из файла, поиска пути от старта до выхода с возможностью выбора алгоритма, визуализации процесса и экспериментального сравнения алгоритмов с применением паттернов проектирования GoF.
|
||
|
||
```python
|
||
import sys
|
||
sys.path.append('.')
|
||
|
||
from builders import TextFileMazeBuilder
|
||
from strategies import BFSStrategy, DFSStrategy, AStarStrategy
|
||
from solver import MazeSolver
|
||
from observers import ConsoleView
|
||
import time
|
||
import pandas as pd
|
||
import matplotlib.pyplot as plt
|
||
builder = TextFileMazeBuilder()
|
||
maze = builder.build_from_file("mazes/small.txt")
|
||
print(f"Размер лабиринта: {maze.width}×{maze.height}")
|
||
print(maze)
|
||
## Паттерн Builder (Строитель)
|
||
|
||
```python
|
||
class TextFileMazeBuilder(MazeBuilder):
|
||
WALL_CHAR = '#'
|
||
START_CHAR = 'S'
|
||
EXIT_CHAR = 'E'
|
||
|
||
def build_from_file(self, filename: str) -> Maze:
|
||
with open(filename, 'r') as f:
|
||
lines = f.readlines()
|
||
# парсинг и создание лабиринта
|
||
return maze
|
||
|
||
**Ячейка 6 (паттерн Strategy):**
|
||
```markdown
|
||
## Паттерн Strategy (Стратегия)
|
||
|
||
Реализованы три алгоритма поиска пути:
|
||
- **BFS** - поиск в ширину (гарантирует кратчайший путь)
|
||
- **DFS** - поиск в глубину (быстрый, но не оптимальный)
|
||
- **A*** - с эвристикой (манхэттенское расстояние)
|
||
strategies = {
|
||
"BFS": BFSStrategy(),
|
||
"DFS": DFSStrategy(),
|
||
"A*": AStarStrategy()
|
||
}
|
||
|
||
results = []
|
||
|
||
for name, strategy in strategies.items():
|
||
solver = MazeSolver(maze, strategy)
|
||
start_time = time.perf_counter()
|
||
path, stats = solver.solve()
|
||
end_time = time.perf_counter()
|
||
|
||
results.append({
|
||
"Алгоритм": name,
|
||
"Время (мс)": stats.time_ms,
|
||
"Длина пути": stats.path_length,
|
||
"Посещено клеток": stats.visited_cells
|
||
})
|
||
|
||
print(f"{name}: {stats}")
|
||
|
||
df = pd.DataFrame(results)
|
||
df
|
||
## Паттерн Observer (Наблюдатель)
|
||
|
||
```python
|
||
class ConsoleView(Observer):
|
||
def render(self, maze, path=None):
|
||
path_set = set(path) if path else set()
|
||
print("\n+" + "-" * maze.width + "+")
|
||
for y in range(maze.height):
|
||
row = []
|
||
for x in range(maze.width):
|
||
cell = maze.get_cell(x, y)
|
||
if cell.is_start:
|
||
row.append('S')
|
||
elif cell.is_exit:
|
||
row.append('E')
|
||
elif cell in path_set:
|
||
row.append('*')
|
||
elif cell.is_wall:
|
||
row.append('#')
|
||
else:
|
||
row.append(' ')
|
||
print("|" + ''.join(row) + "|")
|
||
print("+" + "-" * maze.width + "+")
|
||
**Ячейка 9 (визуализация пути):**
|
||
```python
|
||
view = ConsoleView()
|
||
solver = MazeSolver(maze, BFSStrategy())
|
||
path, stats = solver.solve()
|
||
view.render(maze, path=path)
|
||
print(f"Найден путь длиной {len(path)} клеток")
|
||
data = pd.read_csv("experiment_results.csv")
|
||
data
|
||
fig, axes = plt.subplots(1, 2, figsize=(12, 5))
|
||
|
||
algorithms = data['strategy'].unique()
|
||
mazes = data['maze_file'].unique()
|
||
|
||
for algo in algorithms:
|
||
algo_data = data[data['strategy'] == algo]
|
||
axes[0].plot(algo_data['maze_file'], algo_data['time_mean'], marker='o', label=algo)
|
||
axes[1].plot(algo_data['maze_file'], algo_data['path_length_mean'], marker='o', label=algo)
|
||
|
||
axes[0].set_title('Время выполнения (мс)')
|
||
axes[0].legend()
|
||
axes[1].set_title('Длина пути')
|
||
axes[1].legend()
|
||
plt.xticks(rotation=45)
|
||
plt.tight_layout()
|
||
plt.savefig('report_graphs.png')
|
||
plt.show()
|
||
## Выводы
|
||
|
||
В ходе лабораторной работы были реализованы паттерны:
|
||
|
||
| Паттерн | Где используется | Преимущество |
|
||
|---------|-----------------|--------------|
|
||
| **Builder** | `TextFileMazeBuilder` | Сокрытие сложности создания лабиринта |
|
||
| **Strategy** | `BFS/DFS/A*` | Легкая смена алгоритмов |
|
||
| **Observer** | `ConsoleView` | Отделение визуализации от логики |
|
||
| **Command** | `MoveCommand` | Поддержка отмены действий |
|
||
|
||
### Сравнение алгоритмов
|
||
|
||
- **BFS** - оптимальный по длине пути, стабильное время
|
||
- **DFS** - самый быстрый, но путь длиннее
|
||
- **A*** - баланс скорости и оптимальности
|