forked from UNN/2026-rff_mp
[2] feet rewrite some classes and add some coments
This commit is contained in:
parent
dfd34a3974
commit
641e1a8aac
|
|
@ -4,9 +4,8 @@ from collections import deque
|
|||
import heapq
|
||||
import time
|
||||
|
||||
|
||||
# ---------- 1. Модель клетки и лабиринта ----------
|
||||
class Tile:
|
||||
"""Клетка лабиринта."""
|
||||
def __init__(self, x, y):
|
||||
self.x = x
|
||||
self.y = y
|
||||
|
|
@ -19,7 +18,6 @@ class Tile:
|
|||
|
||||
|
||||
class Labyrinth:
|
||||
"""Модель лабиринта."""
|
||||
def __init__(self, width, height):
|
||||
self.width = width
|
||||
self.height = height
|
||||
|
|
@ -64,6 +62,7 @@ class Labyrinth:
|
|||
return result
|
||||
|
||||
|
||||
# ---------- 2. Загрузка лабиринта из файла ----------
|
||||
class LabyrinthLoader:
|
||||
def load(self, filename):
|
||||
raise NotImplementedError
|
||||
|
|
@ -96,6 +95,7 @@ class TextLabyrinthLoader(LabyrinthLoader):
|
|||
return lab
|
||||
|
||||
|
||||
# ---------- 3. Алгоритмы поиска пути (стратегии) ----------
|
||||
class Pathfinder:
|
||||
def find_path(self, lab, start, goal):
|
||||
raise NotImplementedError
|
||||
|
|
@ -186,10 +186,19 @@ class AStar(Pathfinder):
|
|||
return []
|
||||
|
||||
|
||||
# ---------- 4. Оркестратор с поддержкой наблюдателей ----------
|
||||
class LabyrinthSolver:
|
||||
def __init__(self, lab):
|
||||
self.lab = lab
|
||||
self.strategy = None
|
||||
self.observers = []
|
||||
|
||||
def attach(self, obs):
|
||||
self.observers.append(obs)
|
||||
|
||||
def notify(self, event, data):
|
||||
for obs in self.observers:
|
||||
obs.notify(event, data)
|
||||
|
||||
def set_strategy(self, strategy):
|
||||
self.strategy = strategy
|
||||
|
|
@ -200,6 +209,7 @@ class LabyrinthSolver:
|
|||
t0 = time.perf_counter()
|
||||
path = self.strategy.find_path(self.lab, self.lab.start_tile, self.lab.exit_tile)
|
||||
t1 = time.perf_counter()
|
||||
self.notify("path_found", path)
|
||||
return {
|
||||
'time_ms': (t1 - t0) * 1000,
|
||||
'visited': self.strategy.visited_count(),
|
||||
|
|
@ -207,6 +217,7 @@ class LabyrinthSolver:
|
|||
}
|
||||
|
||||
|
||||
# ---------- 5. Визуализация (наблюдатель) ----------
|
||||
class EventListener:
|
||||
def notify(self, event, data):
|
||||
raise NotImplementedError
|
||||
|
|
@ -278,6 +289,7 @@ class ConsoleRenderer(EventListener):
|
|||
print(f"\n Путь найден! Длина = {len(path)}")
|
||||
|
||||
|
||||
# ---------- 6. Игрок и команды с отменой ----------
|
||||
class Walker:
|
||||
def __init__(self, start_tile, lab):
|
||||
self.current = start_tile
|
||||
|
|
@ -331,14 +343,66 @@ class MoveAction(Action):
|
|||
return False
|
||||
|
||||
|
||||
# ---------- 7. Главный интерактивный цикл (коммит №4) ----------
|
||||
if __name__ == "__main__":
|
||||
# Загружаем лабиринт (предполагается, что файл maze/maze1.txt существует)
|
||||
loader = TextLabyrinthLoader()
|
||||
lab = loader.load("maze/maze1.txt")
|
||||
print("Загружен лабиринт, пробуем BFS...")
|
||||
|
||||
player = Walker(lab.start_tile, lab)
|
||||
view = ConsoleRenderer(player)
|
||||
view.notify("maze_loaded", lab)
|
||||
|
||||
solver = LabyrinthSolver(lab)
|
||||
solver.set_strategy(BFS())
|
||||
stats = solver.solve()
|
||||
if stats['length'] > 0:
|
||||
print(f"BFS: время={stats['time_ms']:.3f}мс, посещено={stats['visited']}, длина={stats['length']}")
|
||||
else:
|
||||
print("Путь не найден")
|
||||
solver.attach(view)
|
||||
|
||||
print("\n УПРАВЛЕНИЕ:")
|
||||
print(" H (влево) J (вниз) K (вверх) L (вправо)")
|
||||
print(" U - отменить ход Q - выход")
|
||||
print("\n АВТОПОИСК:")
|
||||
print(" B - BFS D - DFS A - A*")
|
||||
print("\n" + "=" * 50)
|
||||
|
||||
command_stack = []
|
||||
while True:
|
||||
key = input("\n Команда > ").lower()
|
||||
if key == 'q':
|
||||
print("\n До свидания!")
|
||||
break
|
||||
elif key == 'b':
|
||||
solver.set_strategy(BFS())
|
||||
stats = solver.solve()
|
||||
if stats:
|
||||
print(f"\n BFS: время={stats['time_ms']:.3f}мс, посещено={stats['visited']}, длина={stats['length']}")
|
||||
elif key == 'd':
|
||||
solver.set_strategy(DFS())
|
||||
stats = solver.solve()
|
||||
print(f"\n DFS: время={stats['time_ms']:.3f}мс, посещено={stats['visited']}, длина={stats['length']}")
|
||||
elif key == 'a':
|
||||
solver.set_strategy(AStar())
|
||||
stats = solver.solve()
|
||||
print(f"\n A*: время={stats['time_ms']:.3f}мс, посещено={stats['visited']}, длина={stats['length']}")
|
||||
elif key in ['h', 'j', 'k', 'l']:
|
||||
dirs = {'h': (-1,0), 'l': (1,0), 'k': (0,-1), 'j': (0,1)}
|
||||
act = MoveAction(player, dirs[key][0], dirs[key][1], lab)
|
||||
if act.do():
|
||||
command_stack.append(act)
|
||||
view.notify("player_moved", lab)
|
||||
if player.current == lab.exit_tile:
|
||||
print("\n ПОЗДРАВЛЯЮ! ВЫ НАШЛИ ВЫХОД!")
|
||||
print(f" Сделано ходов: {len(command_stack)}")
|
||||
break
|
||||
else:
|
||||
print("\n Туда нельзя – стена!")
|
||||
elif key == 'u':
|
||||
if command_stack:
|
||||
cmd = command_stack.pop()
|
||||
cmd.undo()
|
||||
view.notify("player_moved", lab)
|
||||
print("\n Отмена последнего хода")
|
||||
else:
|
||||
print("\n Нечего отменять")
|
||||
else:
|
||||
print("\n Неизвестная команда. Используйте h,j,k,l, u, b, d, a, q")
|
||||
|
||||
print("\n Игра окончена. Спасибо!")
|
||||
Loading…
Reference in New Issue
Block a user