forked from UNN/2026-rff_mp
88 lines
2.2 KiB
Python
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()
|