2026-rff_mp/SobolevNS/docs/data/task2_maze/maze_solver/command.py
2026-05-22 13:42:42 +03:00

88 lines
2.2 KiB
Python

"""
maze_solver/command.py - паттерн Command.
Player хранит текущую клетку. MoveCommand двигает игрока в выбранном
направлении и помнит предыдущую позицию для undo. Менеджер CommandHistory
держит стек выполненных команд.
"""
from abc import ABC, abstractmethod
class Player:
"""Игрок в лабиринте."""
def __init__(self, cell):
self.cell = cell
@property
def x(self): return self.cell.x
@property
def y(self): return self.cell.y
class Command(ABC):
@abstractmethod
def execute(self): ...
@abstractmethod
def undo(self): ...
class MoveCommand(Command):
"""Команда перемещения игрока на одну клетку.
direction: одна из 'W','A','S','D' (вверх, влево, вниз, вправо).
"""
DELTAS = {
'W': (0, -1),
'S': (0, 1),
'A': (-1, 0),
'D': (1, 0),
}
def __init__(self, maze, player, direction):
self.maze = maze
self.player = player
self.direction = direction.upper()
self._prev_cell = None
self._executed = False
def execute(self):
if self.direction not in self.DELTAS:
return False
dx, dy = self.DELTAS[self.direction]
target = self.maze.get_cell(self.player.x + dx, self.player.y + dy)
if target is None or not target.is_passable():
return False
self._prev_cell = self.player.cell
self.player.cell = target
self._executed = True
return True
def undo(self):
if not self._executed:
return False
self.player.cell = self._prev_cell
self._executed = False
return True
class CommandHistory:
"""Стек выполненных команд (для общего undo)."""
def __init__(self):
self._stack = []
def do(self, cmd):
if cmd.execute():
self._stack.append(cmd)
return True
return False
def undo(self):
if not self._stack:
return False
return self._stack.pop().undo()