forked from UNN/2026-rff_mp
[2] feat - игрок и система команд с Undo
This commit is contained in:
parent
2e68f1a389
commit
b29a0309a1
|
|
@ -290,8 +290,9 @@ class EventListener:
|
||||||
|
|
||||||
|
|
||||||
class ConsoleDisplay(EventListener):
|
class ConsoleDisplay(EventListener):
|
||||||
def __init__(self):
|
def __init__(self, walker=None):
|
||||||
self._last_path = None
|
self._last_path = None
|
||||||
|
self._walker = walker
|
||||||
|
|
||||||
def update(self, event_type, data):
|
def update(self, event_type, data):
|
||||||
if event_type == "maze_loaded":
|
if event_type == "maze_loaded":
|
||||||
|
|
@ -299,6 +300,8 @@ class ConsoleDisplay(EventListener):
|
||||||
elif event_type == "path_found":
|
elif event_type == "path_found":
|
||||||
self._last_path = data
|
self._last_path = data
|
||||||
self._render_path(data)
|
self._render_path(data)
|
||||||
|
elif event_type == "player_moved":
|
||||||
|
self._render_maze_with_player(data)
|
||||||
|
|
||||||
def _render_maze(self, maze):
|
def _render_maze(self, maze):
|
||||||
os.system('cls' if os.name == 'nt' else 'clear')
|
os.system('cls' if os.name == 'nt' else 'clear')
|
||||||
|
|
@ -322,6 +325,30 @@ class ConsoleDisplay(EventListener):
|
||||||
print("=" * (maze.width * 2 + 4))
|
print("=" * (maze.width * 2 + 4))
|
||||||
print(" S - start E - exit # - wall . - path")
|
print(" S - start E - exit # - wall . - path")
|
||||||
|
|
||||||
|
def _render_maze_with_player(self, maze):
|
||||||
|
os.system('cls' if os.name == 'nt' else 'clear')
|
||||||
|
print("=" * (maze.width * 2 + 4))
|
||||||
|
print(" LABYRINTH (P - player)")
|
||||||
|
print("=" * (maze.width * 2 + 4))
|
||||||
|
|
||||||
|
for y in range(maze.height):
|
||||||
|
print(" ", end='')
|
||||||
|
for x in range(maze.width):
|
||||||
|
cell = maze.cell_at(x, y)
|
||||||
|
if self._walker and cell == self._walker.current:
|
||||||
|
print('P', end=' ')
|
||||||
|
elif cell == maze.start:
|
||||||
|
print('S', end=' ')
|
||||||
|
elif cell == maze.exit:
|
||||||
|
print('E', end=' ')
|
||||||
|
elif cell.is_wall:
|
||||||
|
print('#', end=' ')
|
||||||
|
else:
|
||||||
|
print('.', end=' ')
|
||||||
|
print()
|
||||||
|
print("=" * (maze.width * 2 + 4))
|
||||||
|
print(f" Player position: ({self._walker.current.x}, {self._walker.current.y})")
|
||||||
|
|
||||||
def _render_path(self, path):
|
def _render_path(self, path):
|
||||||
if not path:
|
if not path:
|
||||||
print("\n Path not found!")
|
print("\n Path not found!")
|
||||||
|
|
@ -329,17 +356,76 @@ class ConsoleDisplay(EventListener):
|
||||||
print(f"\n Path found! Length: {len(path)}")
|
print(f"\n Path found! Length: {len(path)}")
|
||||||
|
|
||||||
|
|
||||||
|
# ----------------------------- Игрок и команды -----------------------------
|
||||||
|
class Walker:
|
||||||
|
def __init__(self, start_cell, lab):
|
||||||
|
self._current = start_cell
|
||||||
|
self._previous = None
|
||||||
|
self._labyrinth = lab
|
||||||
|
|
||||||
|
@property
|
||||||
|
def current(self):
|
||||||
|
return self._current
|
||||||
|
|
||||||
|
def move_to(self, cell):
|
||||||
|
if cell and cell.passable():
|
||||||
|
self._previous = self._current
|
||||||
|
self._current = cell
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def undo_move(self):
|
||||||
|
if self._previous:
|
||||||
|
self._current, self._previous = self._previous, None
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
class Action:
|
||||||
|
def execute(self):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def undo(self):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
|
||||||
|
class MoveAction(Action):
|
||||||
|
def __init__(self, walker, direction, lab):
|
||||||
|
self._walker = walker
|
||||||
|
self._dx, self._dy = direction
|
||||||
|
self._lab = lab
|
||||||
|
self._executed = False
|
||||||
|
|
||||||
|
def execute(self):
|
||||||
|
new_x = self._walker.current.x + self._dx
|
||||||
|
new_y = self._walker.current.y + self._dy
|
||||||
|
target = self._lab.cell_at(new_x, new_y)
|
||||||
|
|
||||||
|
if target and target.passable():
|
||||||
|
self._walker.move_to(target)
|
||||||
|
self._executed = True
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def undo(self):
|
||||||
|
if self._executed:
|
||||||
|
self._walker.undo_move()
|
||||||
|
self._executed = False
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
builder = TxtLabyrinthBuilder()
|
builder = TxtLabyrinthBuilder()
|
||||||
maze = builder.build_from_file("maze/level1.txt")
|
maze = builder.build_from_file("maze/level1.txt")
|
||||||
|
|
||||||
view = ConsoleDisplay()
|
walker = Walker(maze.start, maze)
|
||||||
view.update("maze_loaded", maze)
|
view = ConsoleDisplay(walker)
|
||||||
|
view._render_maze_with_player(maze)
|
||||||
|
print("Player created at start position!")
|
||||||
|
|
||||||
pf = Pathfinder(maze)
|
# Test movement
|
||||||
pf.attach(view)
|
test_move = MoveAction(walker, (1, 0), maze)
|
||||||
|
if test_move.execute():
|
||||||
for algo, name in [(BFS(), "BFS"), (DFS(), "DFS"), (AStar(), "A*")]:
|
print("Moved right!")
|
||||||
pf.set_algorithm(algo)
|
view._render_maze_with_player(maze)
|
||||||
stats = pf.solve()
|
|
||||||
print(f"{name}: {stats.time_ms:.3f}ms, visited={stats.visited_cells}, length={stats.path_length}")
|
|
||||||
Loading…
Reference in New Issue
Block a user