[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 heapq
|
||||||
import time
|
import time
|
||||||
|
|
||||||
|
# ---------- 1. Модель клетки и лабиринта ----------
|
||||||
class Tile:
|
class Tile:
|
||||||
"""Клетка лабиринта."""
|
|
||||||
def __init__(self, x, y):
|
def __init__(self, x, y):
|
||||||
self.x = x
|
self.x = x
|
||||||
self.y = y
|
self.y = y
|
||||||
|
|
@ -19,7 +18,6 @@ class Tile:
|
||||||
|
|
||||||
|
|
||||||
class Labyrinth:
|
class Labyrinth:
|
||||||
"""Модель лабиринта."""
|
|
||||||
def __init__(self, width, height):
|
def __init__(self, width, height):
|
||||||
self.width = width
|
self.width = width
|
||||||
self.height = height
|
self.height = height
|
||||||
|
|
@ -64,6 +62,7 @@ class Labyrinth:
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
# ---------- 2. Загрузка лабиринта из файла ----------
|
||||||
class LabyrinthLoader:
|
class LabyrinthLoader:
|
||||||
def load(self, filename):
|
def load(self, filename):
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
@ -96,6 +95,7 @@ class TextLabyrinthLoader(LabyrinthLoader):
|
||||||
return lab
|
return lab
|
||||||
|
|
||||||
|
|
||||||
|
# ---------- 3. Алгоритмы поиска пути (стратегии) ----------
|
||||||
class Pathfinder:
|
class Pathfinder:
|
||||||
def find_path(self, lab, start, goal):
|
def find_path(self, lab, start, goal):
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
@ -186,10 +186,19 @@ class AStar(Pathfinder):
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
|
||||||
|
# ---------- 4. Оркестратор с поддержкой наблюдателей ----------
|
||||||
class LabyrinthSolver:
|
class LabyrinthSolver:
|
||||||
def __init__(self, lab):
|
def __init__(self, lab):
|
||||||
self.lab = lab
|
self.lab = lab
|
||||||
self.strategy = None
|
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):
|
def set_strategy(self, strategy):
|
||||||
self.strategy = strategy
|
self.strategy = strategy
|
||||||
|
|
@ -200,6 +209,7 @@ class LabyrinthSolver:
|
||||||
t0 = time.perf_counter()
|
t0 = time.perf_counter()
|
||||||
path = self.strategy.find_path(self.lab, self.lab.start_tile, self.lab.exit_tile)
|
path = self.strategy.find_path(self.lab, self.lab.start_tile, self.lab.exit_tile)
|
||||||
t1 = time.perf_counter()
|
t1 = time.perf_counter()
|
||||||
|
self.notify("path_found", path)
|
||||||
return {
|
return {
|
||||||
'time_ms': (t1 - t0) * 1000,
|
'time_ms': (t1 - t0) * 1000,
|
||||||
'visited': self.strategy.visited_count(),
|
'visited': self.strategy.visited_count(),
|
||||||
|
|
@ -207,6 +217,7 @@ class LabyrinthSolver:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# ---------- 5. Визуализация (наблюдатель) ----------
|
||||||
class EventListener:
|
class EventListener:
|
||||||
def notify(self, event, data):
|
def notify(self, event, data):
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
@ -278,6 +289,7 @@ class ConsoleRenderer(EventListener):
|
||||||
print(f"\n Путь найден! Длина = {len(path)}")
|
print(f"\n Путь найден! Длина = {len(path)}")
|
||||||
|
|
||||||
|
|
||||||
|
# ---------- 6. Игрок и команды с отменой ----------
|
||||||
class Walker:
|
class Walker:
|
||||||
def __init__(self, start_tile, lab):
|
def __init__(self, start_tile, lab):
|
||||||
self.current = start_tile
|
self.current = start_tile
|
||||||
|
|
@ -331,14 +343,66 @@ class MoveAction(Action):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
# ---------- 7. Главный интерактивный цикл (коммит №4) ----------
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
# Загружаем лабиринт (предполагается, что файл maze/maze1.txt существует)
|
||||||
loader = TextLabyrinthLoader()
|
loader = TextLabyrinthLoader()
|
||||||
lab = loader.load("maze/maze1.txt")
|
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 = LabyrinthSolver(lab)
|
||||||
solver.set_strategy(BFS())
|
solver.attach(view)
|
||||||
stats = solver.solve()
|
|
||||||
if stats['length'] > 0:
|
print("\n УПРАВЛЕНИЕ:")
|
||||||
print(f"BFS: время={stats['time_ms']:.3f}мс, посещено={stats['visited']}, длина={stats['length']}")
|
print(" H (влево) J (вниз) K (вверх) L (вправо)")
|
||||||
else:
|
print(" U - отменить ход Q - выход")
|
||||||
print("Путь не найден")
|
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