forked from UNN/2026-rff_mp
95 lines
3.4 KiB
Python
95 lines
3.4 KiB
Python
"""
|
|
Реализовать класс ConsoleView, который отображает лабиринт,
|
|
текущее положение игрока (если реализован пошаговый режим) и найденный путь.
|
|
Метод render(maze, player_position, path) рисует карту в консоли."""
|
|
|
|
import os
|
|
|
|
from task2.mazeObjects.cell import Cell
|
|
from task2.mazeObjects.maze import Maze
|
|
from task2.mazeObjects.path import Path
|
|
from task2.observerSubject import MazeEvent, MazeEventType, Observer
|
|
|
|
SBROS = "\033[0m"
|
|
|
|
WALL = "#"
|
|
EXIT = "E"
|
|
START = "S"
|
|
PATH_SYMBOL = "+"
|
|
SPACE_SYMBOL = " "
|
|
|
|
# Я убрал аргументы из render(), чтобы не передавать их при каждом запуске.
|
|
# И работать внутри класса приятнее, чем тянуть эти аргументы туда-сюда
|
|
class ConsoleView(Observer):
|
|
maze:Maze|None
|
|
path:Path|None
|
|
|
|
def __init__(self, maze:Maze|None=None, path:Path|None=None):
|
|
super().__init__()
|
|
self.maze = maze
|
|
self.path = path
|
|
|
|
def _getCellColored(self, cell:Cell) -> str:
|
|
if cell.isWall:
|
|
# Белый
|
|
return self._fmt_str(7, 7, WALL)
|
|
elif cell.isExit:
|
|
# Кислотно-зелёный
|
|
return self._fmt_str(12, 7, EXIT)
|
|
elif cell.isStart:
|
|
# Кислотно-красный
|
|
return self._fmt_str(9, 7, START)
|
|
elif self.path and self.path.array:
|
|
if cell in self.path.array:
|
|
# Градиент
|
|
percent = self.path.array.index(cell) / len(self.path.array)
|
|
n = self._ANSICalculator(*self._getGradient(percent))
|
|
return self._fmt_str(n, 10, PATH_SYMBOL)
|
|
return SPACE_SYMBOL
|
|
|
|
def _fmt_str(self, bg:int, fg:int, symbol:str) -> str:
|
|
return f"\033[48;5;{bg}m\033[38;5;{fg}m{symbol}{SBROS}"
|
|
|
|
def _ANSICalculator(self, r:int, g:int, b:int):
|
|
r = max(0, min(5, r))
|
|
g = max(0, min(5, g))
|
|
b = max(0, min(5, b))
|
|
return 16 + 36*r + 6*g + b
|
|
|
|
def _getGradient(self, percent:float):
|
|
r = 5 * (1-percent)
|
|
g = 0
|
|
b = 5 * percent
|
|
return int(round(r)), int(round(g)), int(round(b))
|
|
|
|
def render(self, player_position=None):
|
|
"""
|
|
Печатем ячейку.
|
|
Цвет зависит от индекса ячейчки в массиве path.
|
|
Если в массиве нет - просто белый.
|
|
"""
|
|
|
|
os.system('cls' if os.name == 'nt' else 'clear')
|
|
|
|
if not self.maze:
|
|
print("Лабиринт ещё не загружен")
|
|
return None
|
|
|
|
output = ""
|
|
for y in range(self.maze.height):
|
|
for x in range(self.maze.width):
|
|
cell = self.maze.getCell(x, y)
|
|
output += self._getCellColored(cell)
|
|
output += "\n"
|
|
print(output)
|
|
|
|
def update(self, event: MazeEvent):
|
|
if event.evtype in (MazeEventType.MAZE_LOADED, MazeEventType.PATH_FOUND, MazeEventType.MOVE):
|
|
if event.evtype == MazeEventType.PATH_FOUND:
|
|
if not event.data: raise ValueError
|
|
self.path = event.data
|
|
if event.evtype == MazeEventType.MAZE_LOADED:
|
|
if not event.data: raise ValueError
|
|
self.maze = self.maze
|
|
self.render()
|