|
| 1 | +#33 { Retos para Programadores } RESCATANDO A MICKEY |
| 2 | + |
| 3 | +# Bibliography reference: |
| 4 | +# I use GPT as a reference and sometimes to correct or generate proper comments. |
| 5 | + |
| 6 | +""" |
| 7 | +* EJERCICIO: |
| 8 | + * ¡Disney ha presentado un montón de novedades en su D23! |
| 9 | + * Pero... ¿Dónde está Mickey? |
| 10 | + * Mickey Mouse ha quedado atrapado en un laberinto mágico |
| 11 | + * creado por Maléfica. |
| 12 | + * Desarrolla un programa para ayudarlo a escapar. |
| 13 | + * Requisitos: |
| 14 | + * 1. El laberinto está formado por un cuadrado de 6x6 celdas. |
| 15 | + * 2. Los valores de las celdas serán: |
| 16 | + * - ⬜️ Vacío |
| 17 | + * - ⬛️ Obstáculo |
| 18 | + * - 🐭 Mickey |
| 19 | + * - 🚪 Salida |
| 20 | + * Acciones: |
| 21 | + * 1. Crea una matriz que represente el laberinto (no hace falta |
| 22 | + * que se genere de manera automática). |
| 23 | + * 2. Interactúa con el usuario por consola para preguntarle hacia |
| 24 | + * donde se tiene que desplazar (arriba, abajo, izquierda o derecha). |
| 25 | + * 3. Muestra la actualización del laberinto tras cada desplazamiento. |
| 26 | + * 4. Valida todos los movimientos, teniendo en cuenta los límites |
| 27 | + * del laberinto y los obtáculos. Notifica al usuario. |
| 28 | + * 5. Finaliza el programa cuando Mickey llegue a la salida. |
| 29 | +
|
| 30 | +""" |
| 31 | + |
| 32 | +""" |
| 33 | +Note: If you are using Command Prompt(cmd or Shell in Windows), you may need to change the code page to UTF-8 to properly display emojis. You can do this by running the following command before executing your script: |
| 34 | +
|
| 35 | +chcp 65001 |
| 36 | +
|
| 37 | +Also set the font type to: Segoe UI Emoji or Noto Color Emoji is available. (if this doesn't work you will need to install Windows Terminal to to properly display emojis) |
| 38 | +
|
| 39 | +""" |
| 40 | + |
| 41 | +log = print |
| 42 | + |
| 43 | +import random |
| 44 | + |
| 45 | +# Constants for the maze |
| 46 | +obstacle = '\u2B1B' # ⬛️ Obstacle |
| 47 | +empty_space = '\u2B1C' # ⬜️ Empty space |
| 48 | +mickey = '\U0001F42D' # 🐭 Mickey |
| 49 | +exit = '\U0001F6AA' # 🚪 Exit |
| 50 | + |
| 51 | +# Start position for Mickey |
| 52 | +position = {'x': 0, 'y': 0} |
| 53 | + |
| 54 | +# Function to generate a random maze with obstacles |
| 55 | +def generate_random_maze(size): |
| 56 | + maze = [[obstacle if random.random() < 0.4 else empty_space for _ in range(size)] for _ in range(size)] |
| 57 | + maze[0][0] = mickey # Start position |
| 58 | + maze[size - 1][size - 1] = exit # Exit position |
| 59 | + return maze |
| 60 | + |
| 61 | +# Function to carve a path in the maze using Dijkstra's algorithm |
| 62 | +def dijkstra(maze): |
| 63 | + size = len(maze) |
| 64 | + directions = [(-1, 0), (1, 0), (0, -1), (0, 1)] |
| 65 | + distances = [[float('inf')] * size for _ in range(size)] |
| 66 | + previous = [[None] * size for _ in range(size)] |
| 67 | + distances[0][0] = 0 # Distance from the entrance is 0 |
| 68 | + queue = [(0, 0, 0)] # (x, y, distance) |
| 69 | + |
| 70 | + while queue: |
| 71 | + x, y, distance = queue.pop(0) |
| 72 | + |
| 73 | + if distance > distances[y][x]: |
| 74 | + continue # If the distance is greater than the current distance, do nothing |
| 75 | + |
| 76 | + for dx, dy in directions: |
| 77 | + new_x, new_y = x + dx, y + dy |
| 78 | + |
| 79 | + if 0 <= new_x < size and 0 <= new_y < size: |
| 80 | + new_distance = distance + (10 if maze[new_y][new_x] == obstacle else 1) |
| 81 | + |
| 82 | + if new_distance < distances[new_y][new_x]: |
| 83 | + distances[new_y][new_x] = new_distance |
| 84 | + previous[new_y][new_x] = (x, y) |
| 85 | + queue.append((new_x, new_y, new_distance)) |
| 86 | + |
| 87 | + # Reconstruct the shortest path |
| 88 | + path = [] |
| 89 | + x, y = size - 1, size - 1 |
| 90 | + |
| 91 | + while (x, y) != (0, 0): |
| 92 | + if previous[y][x] is None: |
| 93 | + break # No valid path found |
| 94 | + path.append((x, y)) |
| 95 | + x, y = previous[y][x] |
| 96 | + path.reverse() # Reverse the path to get it from start to exit |
| 97 | + |
| 98 | + # If a path is found, mark it |
| 99 | + if path: |
| 100 | + for x, y in path: |
| 101 | + maze[y][x] = empty_space # Mark the path with an empty space |
| 102 | + |
| 103 | + maze[size - 1][size - 1] = exit # Ensure exit is not overwritten |
| 104 | + return path |
| 105 | + |
| 106 | +# Function to display the maze |
| 107 | +def display_maze(maze): |
| 108 | + print('\nMaze:\n') |
| 109 | + for row in maze: |
| 110 | + print(' '.join(row)) |
| 111 | + print('\n') |
| 112 | + |
| 113 | +# Function to move Mickey |
| 114 | +def move_mickey(direction, maze): |
| 115 | + global position |
| 116 | + new_position = position.copy() |
| 117 | + |
| 118 | + # Update new position based on the direction |
| 119 | + if direction == "w": |
| 120 | + new_position['y'] -= 1 # up |
| 121 | + elif direction == "s": |
| 122 | + new_position['y'] += 1 # down |
| 123 | + elif direction == "a": |
| 124 | + new_position['x'] -= 1 # left |
| 125 | + elif direction == "d": |
| 126 | + new_position['x'] += 1 # right |
| 127 | + |
| 128 | + # Check if the new position is within the bounds of the board |
| 129 | + if (0 <= new_position['x'] < len(maze[0]) and |
| 130 | + 0 <= new_position['y'] < len(maze)): |
| 131 | + # Check if the new position is a wall or path |
| 132 | + if maze[new_position['y']][new_position['x']] == obstacle: |
| 133 | + print("Mickey 🐭 has hit a wall ⬛️, try moving in another direction.") |
| 134 | + return False # Movement failed due to wall |
| 135 | + elif maze[new_position['y']][new_position['x']] == exit: |
| 136 | + print("\nCongratulations! You won! Mickey 🐭 has escaped the maze.") |
| 137 | + maze[position['y']][position['x']] = empty_space # Empty the cell |
| 138 | + position = new_position |
| 139 | + maze[position['y']][position['x']] = mickey # Move |
| 140 | + maze[position['y']][position['x']] = mickey # Move 🐭 Mickey |
| 141 | + return True # Movement successful and game won |
| 142 | + else: |
| 143 | + # Update the position of the player |
| 144 | + maze[position['y']][position['x']] = empty_space # Empty the cell |
| 145 | + position = new_position |
| 146 | + maze[position['y']][position['x']] = mickey # Move 🐭 Mickey |
| 147 | + return True # Movement successful |
| 148 | + else: |
| 149 | + print("Mickey 🐭 cannot move outside the maze, try moving in another direction.") |
| 150 | + return False # Movement failed due to out of bounds |
| 151 | + |
| 152 | +# Main function to start the game |
| 153 | +def main(): |
| 154 | + maze_size = int(input('Enter the size of the maze (between 7 and 15): ')) |
| 155 | + |
| 156 | + # Validate the maze size input |
| 157 | + if maze_size < 7 or maze_size > 15: |
| 158 | + print('Please enter a valid number between 7 and 15.') |
| 159 | + return |
| 160 | + |
| 161 | + # Generate the random maze |
| 162 | + maze = generate_random_maze(maze_size) |
| 163 | + |
| 164 | + # Carve a path in the maze using Dijkstra's algorithm |
| 165 | + dijkstra(maze) |
| 166 | + |
| 167 | + # Display the generated maze |
| 168 | + display_maze(maze) |
| 169 | + |
| 170 | + # Start the game loop |
| 171 | + while True: |
| 172 | + direction = input("Choose a direction to move (up - w, down - s, left - a, right - d): ").lower() |
| 173 | + if move_mickey(direction, maze): |
| 174 | + display_maze(maze) # Display the maze after the move |
| 175 | + if maze[position['y']][position['x']] == exit: |
| 176 | + break # Exit the loop if Mickey has reached the exit |
| 177 | + else: |
| 178 | + display_maze(maze) # Display the maze after an unsuccessful move |
| 179 | + |
| 180 | +if __name__ == "__main__": |
| 181 | + main() # Start the game |
0 commit comments