136 lines
4.2 KiB
Python
136 lines
4.2 KiB
Python
# main.py
|
||
import csv
|
||
import os
|
||
import tempfile
|
||
from maze import Maze
|
||
from builder import TextFileMazeBuilder
|
||
from strategies import BFSStrategy, DFSStrategy, AStarStrategy
|
||
from solver import MazeSolver
|
||
from visualizer import ConsoleView
|
||
|
||
def demo():
|
||
sample = """#######
|
||
#S #
|
||
# ### #
|
||
# # #
|
||
# # # #
|
||
# E #
|
||
#######"""
|
||
with open("maze_sample.txt", "w") as f:
|
||
f.write(sample)
|
||
|
||
builder = TextFileMazeBuilder()
|
||
maze = builder.build_from_file("maze_sample.txt")
|
||
print("Загруженный лабиринт:")
|
||
ConsoleView.render(maze)
|
||
|
||
strategies = {
|
||
"BFS": BFSStrategy(),
|
||
"DFS": DFSStrategy(),
|
||
"A*": AStarStrategy()
|
||
}
|
||
|
||
for name, strat in strategies.items():
|
||
solver = MazeSolver(maze, strat)
|
||
stats = solver.solve()
|
||
print(f"\n{name}: время = {stats.time_ms:.3f} мс, посещено = {stats.visited_cells}, длина пути = {stats.path_length}")
|
||
ConsoleView.render(maze, stats.path)
|
||
|
||
def run_experiments():
|
||
|
||
builder = TextFileMazeBuilder()
|
||
|
||
def make_maze_from_str(s):
|
||
with tempfile.NamedTemporaryFile(mode='w', delete=False, suffix='.txt') as f:
|
||
f.write(s)
|
||
name = f.name
|
||
maze = builder.build_from_file(name)
|
||
os.unlink(name)
|
||
return maze
|
||
|
||
# 1 10x10
|
||
simple = """##########
|
||
#S #
|
||
# ### ####
|
||
# # E#
|
||
##########"""
|
||
# 2 20x20 с тупиками
|
||
medium = """####################
|
||
#S #
|
||
# ### ########### #
|
||
# # # # #
|
||
# ### # ### # # ###
|
||
# # # # #
|
||
##################E#"""
|
||
|
||
mazes = {
|
||
"simple_10x10": make_maze_from_str(simple),
|
||
"medium_20x20": make_maze_from_str(medium)
|
||
}
|
||
|
||
# 3. 50x50
|
||
empty_lines = []
|
||
for y in range(50):
|
||
row = []
|
||
for x in range(50):
|
||
if x == 0 and y == 0:
|
||
row.append('S')
|
||
elif x == 49 and y == 49:
|
||
row.append('E')
|
||
else:
|
||
row.append(' ')
|
||
empty_lines.append(''.join(row))
|
||
empty_str = '\n'.join(empty_lines)
|
||
mazes["empty_50x50"] = make_maze_from_str(empty_str)
|
||
|
||
# 4. Лабиринт без выхода (заменяем 'E' на '#', чтобы выхода не было)
|
||
no_exit_str = empty_str.replace('E', '#')
|
||
with tempfile.NamedTemporaryFile(mode='w', delete=False, suffix='.txt') as f:
|
||
f.write(no_exit_str)
|
||
name = f.name
|
||
# Строим лабиринт без проверки на наличие выхода
|
||
maze_no_exit = builder.build_from_file(name, require_exit=False)
|
||
os.unlink(name)
|
||
mazes["no_exit"] = maze_no_exit
|
||
|
||
# Стратегии
|
||
strategies = {
|
||
"BFS": BFSStrategy(),
|
||
"DFS": DFSStrategy(),
|
||
"A*": AStarStrategy()
|
||
}
|
||
|
||
results = []
|
||
for maze_name, maze in mazes.items():
|
||
for strat_name, strat in strategies.items():
|
||
times = []
|
||
visiteds = []
|
||
lengths = []
|
||
for _ in range(5): # 5 запусков для усреднения
|
||
solver = MazeSolver(maze, strat)
|
||
stats = solver.solve()
|
||
times.append(stats.time_ms)
|
||
visiteds.append(stats.visited_cells)
|
||
lengths.append(stats.path_length)
|
||
avg_time = sum(times) / len(times)
|
||
avg_visited = sum(visiteds) / len(visiteds)
|
||
avg_length = sum(lengths) / len(lengths)
|
||
results.append({
|
||
"maze": maze_name,
|
||
"strategy": strat_name,
|
||
"avg_time_ms": avg_time,
|
||
"avg_visited": avg_visited,
|
||
"avg_path_length": avg_length
|
||
})
|
||
print(f"{maze_name},{strat_name}: time={avg_time:.2f}ms visited={avg_visited:.0f} length={avg_length:.0f}")
|
||
|
||
with open("experiment_results.csv", "w", newline='', encoding='utf-8') as f:
|
||
writer = csv.DictWriter(f, fieldnames=["maze", "strategy", "avg_time_ms", "avg_visited", "avg_path_length"])
|
||
writer.writeheader()
|
||
writer.writerows(results)
|
||
print("\nРезультаты сохранены в experiment_results.csv")
|
||
|
||
if __name__ == "__main__":
|
||
demo()
|
||
print("\n=== ЗАПУСК ЭКСПЕРИМЕНТОВ ===")
|
||
run_experiments() |