Skip to content

Commit 3589fa8

Browse files
authored
Merge pull request mouredev#7358 from nlarrea/py33
mouredev#33 - python
2 parents 0548db1 + ee027b0 commit 3589fa8

File tree

1 file changed

+212
-0
lines changed

1 file changed

+212
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
"""
2+
* EJERCICIO:
3+
* ¡Disney ha presentado un montón de novedades en su D23!
4+
* Pero... ¿Dónde está Mickey?
5+
* Mickey Mouse ha quedado atrapado en un laberinto mágico
6+
* creado por Maléfica.
7+
* Desarrolla un programa para ayudarlo a escapar.
8+
* Requisitos:
9+
* 1. El laberinto está formado por un cuadrado de 6x6 celdas.
10+
* 2. Los valores de las celdas serán:
11+
* - "⬜️" Vacío
12+
* - ⬛️ Obstáculo
13+
* - 🐭 Mickey
14+
* - 🚪 Salida
15+
* Acciones:
16+
* 1. Crea una matriz que represente el laberinto (no hace falta
17+
* que se genere de manera automática).
18+
* 2. Interactúa con el usuario por consola para preguntarle hacia
19+
* donde se tiene que desplazar (arriba, abajo, izquierda o derecha).
20+
* 3. Muestra la actualización del laberinto tras cada desplazamiento.
21+
* 4. Valida todos los movimientos, teniendo en cuenta los límites
22+
* del laberinto y los obstáculos. Notifica al usuario.
23+
* 5. Finaliza el programa cuando Mickey llegue a la salida.
24+
"""
25+
26+
from enum import Enum
27+
from typing import Literal
28+
29+
30+
EMPTY = "⬜️"
31+
PLAYER = "🐭"
32+
EXIT = "🚪"
33+
OBSTACLE = "⬛️"
34+
35+
MAZE = [
36+
[PLAYER, OBSTACLE, OBSTACLE, OBSTACLE, OBSTACLE, OBSTACLE],
37+
[EMPTY, OBSTACLE, OBSTACLE, OBSTACLE, EMPTY, OBSTACLE],
38+
[EMPTY, OBSTACLE, OBSTACLE, OBSTACLE, EMPTY, OBSTACLE],
39+
[EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY],
40+
[OBSTACLE, EMPTY, OBSTACLE, EMPTY, OBSTACLE, OBSTACLE],
41+
[OBSTACLE, EMPTY, OBSTACLE, EMPTY, EMPTY, EXIT],
42+
]
43+
44+
45+
class Action(Enum):
46+
UP = "w"
47+
DOWN = "s"
48+
RIGHT = "d"
49+
LEFT = "a"
50+
EXIT = "q"
51+
52+
53+
class Position:
54+
def __init__(self, row: int, col: int, max_row: int, max_col: int):
55+
self.row = row
56+
self.col = col
57+
self._max_row = max_row
58+
self._max_col = max_col
59+
60+
def __eq__(self, value: object):
61+
if isinstance(value, Position):
62+
return value.row == self.row and value.col == self.col
63+
64+
return False
65+
66+
def __hash__(self) -> int:
67+
return hash(self.row, self.col)
68+
69+
def move(self, direction: str):
70+
if direction == Action.UP.value:
71+
self._up()
72+
elif direction == Action.DOWN.value:
73+
self._down()
74+
elif direction == Action.RIGHT.value:
75+
self._right()
76+
elif direction == Action.LEFT.value:
77+
self._left()
78+
else:
79+
print(f"La dirección '{direction}' no es posible.")
80+
81+
def _up(self) -> tuple[int, int]:
82+
if self.row > 0:
83+
self.row -= 1
84+
return (self.row, self.col)
85+
86+
def _down(self) -> tuple[int, int]:
87+
if self.row < self._max_row:
88+
self.row += 1
89+
return (self.row, self.col)
90+
91+
def _left(self) -> tuple[int, int]:
92+
if self.col > 0:
93+
self.col -= 1
94+
return (self.row, self.col)
95+
96+
def _right(self) -> tuple[int, int]:
97+
if self.col < self._max_col:
98+
self.col += 1
99+
return (self.row, self.col)
100+
101+
102+
def select_movement() -> str:
103+
keys = [action.value for action in Action]
104+
while True:
105+
print("Movimientos posibles:")
106+
for action in Action:
107+
print(f" [{action.value.upper()}]: {action.name.capitalize()}")
108+
109+
try:
110+
selection = input("Selecciona qué hacer:\n > ")
111+
assert (
112+
selection.isalpha() and selection.lower() in keys
113+
), f"\nDebes introducir una de las siguientes letras: {', '.join(keys)}"
114+
115+
except AssertionError as error:
116+
print(error)
117+
118+
else:
119+
return selection.lower()
120+
121+
122+
def print_maze(maze: list[list[str]]):
123+
print()
124+
for row in maze:
125+
print("".join(row))
126+
print()
127+
128+
129+
def update_maze(
130+
maze: list[list[str]], new_position: Position
131+
) -> list[list[str]]:
132+
# Get current player's position
133+
old_player_pos = get_position(maze, PLAYER)
134+
135+
# Update player position to be empty from now on
136+
maze[old_player_pos.row][old_player_pos.col] = EMPTY
137+
# Update maze to show player in new position
138+
maze[new_position.row][new_position.col] = PLAYER
139+
140+
return maze
141+
142+
143+
def get_position(maze: list[list[str]], item: Literal["🐭", "🚪"]) -> Position:
144+
for nrow, row in enumerate(maze):
145+
for ncol, col in enumerate(row):
146+
if col == item:
147+
return Position(
148+
row=nrow, col=ncol, max_row=len(maze), max_col=len(row)
149+
)
150+
151+
152+
def actions(maze: list[list[str]], position: Position) -> list[str]:
153+
actions_ = []
154+
155+
# Up
156+
if position.row > 0 and maze[position.row - 1][position.col] in [
157+
EMPTY,
158+
EXIT,
159+
]:
160+
actions_.append(Action.UP.value)
161+
162+
# Down
163+
if position.row < len(maze) - 1 and maze[position.row + 1][
164+
position.col
165+
] in [EMPTY, EXIT]:
166+
actions_.append(Action.DOWN.value)
167+
168+
# Left
169+
if position.col > 0 and maze[position.row][position.col - 1] in [
170+
EMPTY,
171+
EXIT,
172+
]:
173+
actions_.append(Action.LEFT.value)
174+
175+
# Right
176+
if position.col < len(maze) - 1 and maze[position.row][
177+
position.col + 1
178+
] in [EMPTY, EXIT]:
179+
actions_.append(Action.RIGHT.value)
180+
181+
return actions_
182+
183+
184+
def run(maze: list[list[str]]):
185+
EXIT_POS = get_position(maze, EXIT)
186+
player_pos = get_position(maze, PLAYER)
187+
188+
while True:
189+
print_maze(maze)
190+
191+
selected = select_movement()
192+
available_actions = actions(maze, player_pos)
193+
194+
if selected == Action.EXIT.value:
195+
print("\nSaliendo del juego.")
196+
break
197+
198+
elif selected not in available_actions:
199+
print("\nLa opción que has escogido no es posible.")
200+
continue
201+
202+
player_pos.move(selected)
203+
maze = update_maze(maze, player_pos)
204+
205+
if player_pos == EXIT_POS:
206+
print_maze(maze)
207+
print("\n\n¡HAS ENCONTRADO LA SALIDA!")
208+
break
209+
210+
211+
if __name__ == "__main__":
212+
run(MAZE)

0 commit comments

Comments
 (0)