2026-rff_mp/pogodinda/lab2/src/commands.py

79 lines
2.1 KiB
Python

from abc import ABC, abstractmethod
from typing import List
from maze import Maze, Cell
class Command(ABC):
"""Интерфейс команды (Command pattern)."""
@abstractmethod
def execute(self) -> bool:
pass
@abstractmethod
def undo(self):
pass
class Player:
"""Игрок, перемещающийся по лабиринту."""
def __init__(self, cell: Cell):
self.current_cell = cell
self._history: List[Cell] = []
def move_to(self, cell: Cell):
self._history.append(self.current_cell)
self.current_cell = cell
def move_back(self):
if self._history:
self.current_cell = self._history.pop()
return self.current_cell
return None
def __repr__(self):
return f"Player({self.current_cell.x}, {self.current_cell.y})"
class MoveCommand(Command):
"""Команда перемещения игрока."""
DIRECTIONS = {
'W': (0, -1),
'S': (0, 1),
'A': (-1, 0),
'D': (1, 0),
}
def __init__(self, player: Player, maze: Maze, direction: str):
self.player = player
self.maze = maze
self.direction = direction.upper()
self._previous_cell = None
self._executed = False
def execute(self) -> bool:
if self.direction not in self.DIRECTIONS:
return False
dx, dy = self.DIRECTIONS[self.direction]
new_x = self.player.current_cell.x + dx
new_y = self.player.current_cell.y + dy
new_cell = self.maze.get_cell(new_x, new_y)
if new_cell and new_cell.is_passable():
self._previous_cell = self.player.current_cell
self.player.move_to(new_cell)
self._executed = True
return True
return False
def undo(self):
if self._executed and self._previous_cell:
self.player.current_cell = self._previous_cell
self._executed = False
self._previous_cell = None