Skip to content

Commit c38e91e

Browse files
authored
Merge pull request #8460 from ignaciovihe/ejercicio-33
#33 - Python
2 parents 93ec70b + 92de31b commit c38e91e

File tree

1 file changed

+231
-0
lines changed

1 file changed

+231
-0
lines changed
Lines changed: 231 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,231 @@
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+
27+
"""
28+
He querido realizar el ejercicio con clases para practicar SOLID. Se podía haber resuelto de forma mucho mas sencilla.
29+
"""
30+
31+
import os
32+
from abc import ABC, abstractmethod
33+
34+
def clear_console():# Sierve para borrar la consola y que el tablero quede siempre en el mismo sitio
35+
os.system('cls' if os.name == 'nt' else 'clear')
36+
37+
38+
maze = [["⬜️","⬛️","🚪","⬜️","⬜️","⬜️","⬛️","⬜️","⬜️","⬜️","⬜️","⬛️"],
39+
["⬜️","⬛️","⬛️","⬛️","⬛️","⬜️","⬜️","⬜️","⬜️","⬜️","⬜️","⬜️"],
40+
["⬛️","⬜️","⬜️","⬜️","⬜️","⬜️","⬛️","⬜️","⬛️","⬜️","⬜️","⬛️"],
41+
["⬜️","⬜️","⬛️","⬜️","⬛️","⬛️","⬜️","⬛️","⬜️","⬛️","⬛️","⬜️"],
42+
["⬜️","⬛️","⬜️","⬜️","⬛️","⬛️","⬜️","⬛️","⬜️","⬜️","⬜️","⬜️"],
43+
["⬜️","⬛️","⬛️","⬛️","⬛️","⬜️","⬜️","⬜️","⬛️","⬜️","⬜️","⬜️"],
44+
["⬜️","⬛️","⬜️","⬛️","⬜️","⬛️","⬛️","⬛️","⬜️","⬛️","⬛️","⬜️"],
45+
["⬜️","⬛️","⬜️","⬛️","⬛️","⬜️","⬜️","⬜️","⬜️","⬜️","⬜️","⬛️"],
46+
["⬜️","⬛️","⬛️","⬛️","⬛️","⬜️","⬛️","⬜️","⬛️","⬛️","⬜️","⬜️"],
47+
["⬜️","⬛️","⬛️","⬜️","⬛️","⬛️","⬛️","⬜️","⬜️","⬜️","⬛️","⬜️"],
48+
["⬜️","⬛️","⬜️","⬛️","⬜️","⬜️","⬜️","⬛️","⬜️","⬜️","⬜️","⬜️"],
49+
["⬛️","🐭","⬜️","⬛️","⬛️","⬛️","⬜️","⬜️","⬜️","⬜️","⬛️","⬜️"],
50+
["⬜️","⬛️","⬜️","⬛️","⬜️","⬜️","⬛️","⬛️","⬛️","⬛️","⬜️","⬜️"],
51+
["⬜️","⬛️","⬜️","⬛️","⬛️","⬜️","⬜️","⬜️","⬜️","⬜️","⬜️","⬜️"]]
52+
53+
class Maze:#Clase que contiene el laberinto y sus proiedades.
54+
def __init__(self, grid):
55+
self.grid = grid
56+
self.obstacles, self.mickey, self.exit = self.update_maze_properties()
57+
58+
def __getitem__(self, index):# Este metodo hace que cuando accedo a la instacia de Maze con indices no tengo que acceder a maze.grid
59+
return self.grid[index]
60+
61+
def __len__(self):
62+
return len(self.grid)# Igualmente dice que cuando acceda a len de la instancia de Maze este accediendo directamente a len de maze.grid
63+
64+
def update_maze_properties(self):
65+
current_obstacles = []
66+
mickey = exit = None #Mejora la seguridad
67+
for i, line in enumerate(self.grid):
68+
for j, column in enumerate(line):
69+
if column != "⬜️":
70+
if column == "⬛️":
71+
current_obstacles.append((i, j))
72+
elif column == "🐭":
73+
mickey = (i, j)
74+
elif column == "🚪":
75+
exit = (i, j)
76+
return current_obstacles, mickey, exit
77+
78+
79+
class MazePrinter:#Esta clase sieve para pintar el laberinto
80+
def __init__(self, maze: Maze):
81+
self.maze = maze
82+
83+
def print_maze(self):
84+
for line in self.maze:
85+
for cell in line:
86+
print(cell, end="")
87+
print()
88+
89+
90+
class CellChecker:# Esta clase se encarga de comprobar las situaciones en el tablero
91+
def __init__(self, maze: Maze):
92+
self.maze = maze
93+
94+
def is_inside_maze(self, i:int, j:int):
95+
return 0<= i < len(self.maze) and 0<= j < len(self.maze[0]) # Puedo acceder directamente a self.maze como si fuera grid por la funcion __getitem__
96+
97+
def is_obstacle(self, i:int, j:int):
98+
return (i, j) in self.maze.obstacles
99+
100+
def is_exit(self, i:int, j: int):
101+
return (i, j) in self.maze.exit
102+
103+
def is_mickey(self, i:int, j: int):
104+
return (i, j) in self.maze.mickey
105+
106+
107+
class GameMessenger:# Esta clase se encarga de imprimir los mensajes de feedback
108+
def invalid_direction(self):
109+
print("Elige una opción válida")
110+
111+
def mickey_blocked(self):
112+
print("Mickey no puede continuar por ahí")
113+
114+
def mickey_wins(self):
115+
print("FELICIDADES! - HAS LIBERADO A MICKEY")
116+
117+
118+
class MoveStrategy(ABC):# Interfaz/Clase abstracta de los posibles movimientos.
119+
@abstractmethod
120+
def matches(self, direction: str) -> bool:
121+
pass
122+
@abstractmethod
123+
def get_movement(self) -> tuple[int, int]:
124+
pass
125+
126+
class MoveLeft(MoveStrategy):#Implementaciones concretas de los posibles movimientos
127+
def matches(self, direction): return direction == "a"
128+
def get_movement(self): return (0, -1)
129+
130+
class MoveUpLeft(MoveStrategy):
131+
def matches(self, direction): return direction == "q"
132+
def get_movement(self): return (-1, -1)
133+
134+
class MoveUp(MoveStrategy):
135+
def matches(self, direction): return direction == "w"
136+
def get_movement(self): return (-1, 0)
137+
138+
class MoveUpRight(MoveStrategy):
139+
def matches(self, direction): return direction == "e"
140+
def get_movement(self): return (-1, 1)
141+
142+
class MoveRight(MoveStrategy):
143+
def matches(self, direction): return direction == "d"
144+
def get_movement(self): return (0, 1)
145+
146+
class MoveDownRight(MoveStrategy):
147+
def matches(self, direction): return direction == "c"
148+
def get_movement(self): return (1, 1)
149+
150+
class MoveDown(MoveStrategy):
151+
def matches(self, direction): return direction == "s"
152+
def get_movement(self): return (1, 0)
153+
154+
class MoveDownLeft(MoveStrategy):
155+
def matches(self, direction): return direction == "z"
156+
def get_movement(self): return (1, -1)
157+
158+
class MovementManager:# Esta clase se encarga de manejar los posibles movimientos
159+
def __init__(self, maze: Maze, cell_checker: CellChecker, strategies):
160+
self.maze = maze
161+
self.cell_checker = cell_checker
162+
self.strategies = strategies
163+
164+
def calculate_movement(self, direction: str):# Obtiene el movimiento segun la opcion elegida
165+
for strategie in self.strategies:
166+
if strategie.matches(direction):
167+
return strategie.get_movement()
168+
return None
169+
170+
def move(self, direction: str):# Realiza el movimiento y devuelve el estado de lo que ha ocurrido. Movimiento normal, bloqueado, final.
171+
movement = self.calculate_movement(direction)
172+
if movement is None:
173+
return "invalid"
174+
175+
new_i = self.maze.mickey[0] + movement[0]
176+
new_j = self.maze.mickey[1] + movement[1]
177+
178+
if self.cell_checker.is_inside_maze(new_i, new_j) and not self.cell_checker.is_obstacle(new_i, new_j):
179+
old_i, old_j = self.maze.mickey
180+
self.maze[old_i][old_j]= "⬜️"
181+
self.maze[new_i][new_j] = "🐭"
182+
self.maze.mickey = (new_i, new_j)
183+
184+
if self.maze.mickey == self.maze.exit:
185+
return "win"
186+
return "moved"
187+
else:
188+
return "blocked"
189+
190+
191+
def main():# Se encarga del flujo del programa
192+
my_maze = Maze(maze)
193+
printer = MazePrinter(my_maze)
194+
cell_checker = CellChecker(my_maze)
195+
movement_strategies = [
196+
MoveLeft(), MoveUpLeft(), MoveUp(), MoveUpRight(), MoveRight(), MoveDownRight(), MoveDown(), MoveDownLeft()
197+
]
198+
movement_manager = MovementManager(my_maze, cell_checker, movement_strategies)
199+
messenger = GameMessenger()
200+
201+
finish = False
202+
print("--Welcome to Mickey Maze--")
203+
printer.print_maze()
204+
205+
while not finish:
206+
print("Movimientos:")
207+
print("a. Izquierda")
208+
print("q. Arriba izquierda")
209+
print("w. Arriba")
210+
print("e. Arriba derecha")
211+
print("d. Derecha")
212+
print("c. Abajo derecha")
213+
print("s. Abajo")
214+
print("z. Abajo izquierda")
215+
216+
option = input("Introduce a donde quieres moverte:")
217+
clear_console()
218+
result = movement_manager.move(option)
219+
220+
printer.print_maze()
221+
222+
match result:
223+
case "invalid":
224+
messenger.invalid_direction()
225+
case "blocked":
226+
messenger.mickey_blocked()
227+
case "win":
228+
messenger.mickey_wins()
229+
finish = True
230+
231+
main()

0 commit comments

Comments
 (0)