import fileinput import random from enum import StrEnum ''' This file gives a starting point for the 'spaghetti codenight'. A example that uses the Maze class can be found at the bottom. ''' class Block(StrEnum): """ a Block represents a field in the maze """ Wall = "⬛" # Can't be entered as a player Field = "⬜" # Can be entered as a player FieldKnown = "🟥" # Same as field except that you have already been there Player = "🍝" # You End = "😮" # The end of the maze class Direction(StrEnum): """ Possible directions to move to. """ Up = "⬆️" Right = "➡️" Down = "⬇️" Left = "⬅️" @property def coordinates(self) -> tuple[int, int]: """ The coordinates to add to the current player's position for each possible direction """ coordinates_map = { "⬆️": (-1, 0), "➡️": (0, 1), "⬇️": (1, 0), "⬅️": (0, -1), } return coordinates_map[self.value] class Maze: def __init__(self): self.field: list[list[Block]] # 2D array representing the maze self.player: tuple[int, int] # Position of the player. self.end: tuple[int, int] # Position of the end. self._input = fileinput.input(encoding='utf-8') # Reads the input. You shouldn't access this manually self._get_state() def move(self, dir: Direction) -> bool: """ Move in a given direction Args: mov (Direction): The direction to move in Returns: bool: Returns if the player didn't move """ old_player = self.player print(dir.value, flush=True) # Do move (Flush is necessary!) self._get_state() # Get new maze state return old_player == self.player def get_block(self, dir: Direction) -> Block: """ Get the block in the given direction from the player Args: mov (Direction): The direction Returns: Block: The block """ dy, dx = dir.coordinates py, px = self.player[0] + dy, self.player[1] + dx return self.field[py][px] def _get_state(self): """ Private method. Should not be called manually. Gets the next state from stdin and parses it. """ self.field = [] # Split line by tab and loop over them for i, line in enumerate(self._input.readline().split('\t')): row: list[Block] = [] # Loop over emojis for j, char in enumerate(line): if char in ['\t', '\n']: # Next line continue row.append(Block(char)) # Check for player if char == Block.Player.value: self.player = (i, j) # Check for the end if char == Block.End.value: self.end = (i, j) self.field.append(row) def random_solver(): """ An example of a maze solver using the Maze class. It doesn't guarantee a solution as it will move in a random direction. """ # Get maze maze = Maze() # As long as the maze isn't solved, move in a random direction # The program gets killed when a maze is solved so we don't have to worry about that while True: # Get a random direction dir = random.choice([dir for dir in Direction]) # Move maze.move(dir) if __name__ == '__main__': random_solver()