forked from spaghetti/spaghetti-code-3
feat: init
This commit is contained in:
commit
e7cf0747a8
1 changed files with 128 additions and 0 deletions
128
maze.py
Normal file
128
maze.py
Normal file
|
@ -0,0 +1,128 @@
|
|||
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 = {
|
||||
"up": (-1, 0),
|
||||
"right": (0, 1),
|
||||
"down": (1, 0),
|
||||
"left": (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._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 moved
|
||||
"""
|
||||
old_player = self.player
|
||||
|
||||
print(dir.value) # Do move
|
||||
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] + dx, self.player[1] + dy
|
||||
|
||||
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 = []
|
||||
|
||||
lines = fileinput.input()
|
||||
for i, line in enumerate(lines.readline().split('\t')):
|
||||
row: list[Block] = []
|
||||
for j, char in enumerate(line):
|
||||
row.append(Block(char))
|
||||
|
||||
if char == Block.Player.value:
|
||||
self.player = (i, j)
|
||||
|
||||
if char == Block.End.value:
|
||||
self.player = (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()
|
Loading…
Reference in a new issue