import sys from collections import deque import pygame # ------------------------------------------------------------ # Maus im Käselabyrinth # 2D-Labyrinthspiel / Sammelspiel mit pygame # ------------------------------------------------------------ # Installation, falls pygame noch fehlt: # pip install pygame # # Starten: # python maus_im_kaeselabyrinth.py # ------------------------------------------------------------ pygame.init() # ----------------------------- # Grundeinstellungen # ----------------------------- TILE_SIZE = 32 HUD_HEIGHT = 80 FPS = 60 CAT_MOVE_DELAY = 350 # Millisekunden zwischen Katzenbewegungen # 0 = Weg, 1 = Wand maze = [ [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], [1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1], [1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1], [1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1], [1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1], [1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1], [1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1], [1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1], [1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], [1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1], [1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1], [1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], ] ROWS = len(maze) COLS = len(maze[0]) WIDTH = COLS * TILE_SIZE HEIGHT = ROWS * TILE_SIZE + HUD_HEIGHT screen = pygame.display.set_mode((WIDTH, HEIGHT)) pygame.display.set_caption("Maus im Käselabyrinth") clock = pygame.time.Clock() font_big = pygame.font.SysFont("arial", 38, bold=True) font_medium = pygame.font.SysFont("arial", 24, bold=True) font_small = pygame.font.SysFont("arial", 18) # ----------------------------- # Farben # ----------------------------- BACKGROUND = (247, 239, 210) PATH = (245, 215, 123) WALL = (95, 67, 36) WALL_DARK = (62, 43, 23) GRID_LINE = (220, 185, 85) MOUSE = (185, 185, 185) MOUSE_DARK = (120, 120, 120) CAT = (226, 124, 48) CAT_DARK = (140, 70, 25) CHEESE = (255, 214, 0) CHEESE_DARK = (199, 154, 0) BLACK = (20, 20, 20) WHITE = (255, 255, 255) RED = (190, 40, 40) GREEN = (40, 150, 70) # ----------------------------- # Spielvariablen # ----------------------------- mouse_pos = [1, 1] cat_pos = [20, 13] cheeses = [] score = 0 game_state = "running" # running, won, game_over last_cat_move_time = 0 def reset_game(): """Setzt alle Spielvariablen zurück.""" global mouse_pos, cat_pos, cheeses, score, game_state, last_cat_move_time mouse_pos = [1, 1] cat_pos = [20, 13] # Liste mit genau 10 Käsestücken cheeses = [ [3, 1], [8, 1], [15, 1], [20, 2], [5, 5], [13, 5], [1, 9], [9, 9], [15, 11], [18, 13], ] score = 0 game_state = "running" last_cat_move_time = pygame.time.get_ticks() def is_wall(x, y): """Prüft, ob sich an der Position eine Wand befindet.""" if y < 0 or y >= ROWS or x < 0 or x >= COLS: return True return maze[y][x] == 1 def move_mouse(dx, dy): """Bewegt die Maus, falls keine Wand im Weg ist.""" global mouse_pos if game_state != "running": return new_x = mouse_pos[0] + dx new_y = mouse_pos[1] + dy # Bedingung: Die Maus darf nicht durch Wände laufen. if not is_wall(new_x, new_y): mouse_pos = [new_x, new_y] collect_cheese() check_cat_collision() check_win() def collect_cheese(): """Prüft, ob die Maus Käse eingesammelt hat.""" global score, cheeses if mouse_pos in cheeses: cheeses.remove(mouse_pos.copy()) score += 1 def check_cat_collision(): """Prüft, ob Katze und Maus auf demselben Feld stehen.""" global game_state if mouse_pos == cat_pos: game_state = "game_over" def check_win(): """Prüft, ob alle 10 Käsestücke gesammelt wurden.""" global game_state if score == 10 and game_state == "running": game_state = "won" def get_neighbors(position): """Gibt alle begehbaren Nachbarfelder zurück.""" x, y = position directions = [(0, -1), (0, 1), (-1, 0), (1, 0)] neighbors = [] for dx, dy in directions: next_x = x + dx next_y = y + dy if not is_wall(next_x, next_y): neighbors.append([next_x, next_y]) return neighbors def find_shortest_path(start, goal): """ Sucht mit einer Breitensuche einen Weg von der Katze zur Maus. Dadurch bewegt sich die Katze sinnvoll durch das Labyrinth. """ queue = deque() queue.append((start, [])) visited = {tuple(start)} while queue: current, path = queue.popleft() if current == goal: return path for neighbor in get_neighbors(current): key = tuple(neighbor) if key not in visited: visited.add(key) queue.append((neighbor, path + [neighbor])) return [] def move_cat(): """Bewegt die Katze einen Schritt in Richtung Maus.""" global cat_pos if game_state != "running": return path = find_shortest_path(cat_pos, mouse_pos) if path: cat_pos = path[0] check_cat_collision() def draw_hud(): """Zeichnet Titel, Punkte und Hinweise.""" pygame.draw.rect(screen, BACKGROUND, (0, 0, WIDTH, HUD_HEIGHT)) title = font_medium.render("Maus im Käselabyrinth", True, BLACK) score_text = font_medium.render(f"Punkte: {score} / 10", True, BLACK) if game_state == "running": status = "Status: Spiel läuft" status_color = BLACK elif game_state == "won": status = "Status: Gewonnen!" status_color = GREEN else: status = "Status: Game Over!" status_color = RED status_text = font_medium.render(status, True, status_color) help_text = font_small.render("Steuerung: Pfeiltasten oder W, A, S, D | R = Neustart | ESC = Beenden", True, BLACK) screen.blit(title, (20, 10)) screen.blit(score_text, (20, 42)) screen.blit(status_text, (250, 42)) screen.blit(help_text, (20, 64)) def draw_maze(): """Zeichnet Labyrinth mit Wegen und Wänden.""" for y in range(ROWS): for x in range(COLS): rect = pygame.Rect(x * TILE_SIZE, HUD_HEIGHT + y * TILE_SIZE, TILE_SIZE, TILE_SIZE) if maze[y][x] == 1: pygame.draw.rect(screen, WALL, rect) pygame.draw.rect(screen, WALL_DARK, rect, 2) else: pygame.draw.rect(screen, PATH, rect) pygame.draw.rect(screen, GRID_LINE, rect, 1) def draw_cheese(x, y): """Zeichnet ein Käsestück.""" center_x = x * TILE_SIZE + TILE_SIZE // 2 center_y = HUD_HEIGHT + y * TILE_SIZE + TILE_SIZE // 2 points = [ (center_x - 11, center_y + 10), (center_x + 12, center_y), (center_x - 11, center_y - 10), ] pygame.draw.polygon(screen, CHEESE, points) pygame.draw.polygon(screen, CHEESE_DARK, points, 2) pygame.draw.circle(screen, CHEESE_DARK, (center_x - 3, center_y), 2) pygame.draw.circle(screen, CHEESE_DARK, (center_x + 4, center_y - 3), 2) pygame.draw.circle(screen, CHEESE_DARK, (center_x + 4, center_y + 4), 2) def draw_mouse(): """Zeichnet die Maus.""" x, y = mouse_pos center_x = x * TILE_SIZE + TILE_SIZE // 2 center_y = HUD_HEIGHT + y * TILE_SIZE + TILE_SIZE // 2 # Ohren pygame.draw.circle(screen, MOUSE_DARK, (center_x - 8, center_y - 9), 5) pygame.draw.circle(screen, MOUSE_DARK, (center_x + 8, center_y - 9), 5) # Körper pygame.draw.circle(screen, MOUSE, (center_x, center_y), 11) pygame.draw.circle(screen, BLACK, (center_x, center_y + 2), 2) # Schwanz pygame.draw.line(screen, MOUSE_DARK, (center_x - 10, center_y + 4), (center_x - 17, center_y + 10), 2) def draw_cat(): """Zeichnet die Katze.""" x, y = cat_pos center_x = x * TILE_SIZE + TILE_SIZE // 2 center_y = HUD_HEIGHT + y * TILE_SIZE + TILE_SIZE // 2 # Kopf pygame.draw.circle(screen, CAT, (center_x, center_y), 12) # Ohren left_ear = [(center_x - 10, center_y - 7), (center_x - 4, center_y - 18), (center_x, center_y - 7)] right_ear = [(center_x + 10, center_y - 7), (center_x + 4, center_y - 18), (center_x, center_y - 7)] pygame.draw.polygon(screen, CAT, left_ear) pygame.draw.polygon(screen, CAT, right_ear) pygame.draw.polygon(screen, CAT_DARK, left_ear, 2) pygame.draw.polygon(screen, CAT_DARK, right_ear, 2) # Augen pygame.draw.circle(screen, BLACK, (center_x - 4, center_y - 2), 2) pygame.draw.circle(screen, BLACK, (center_x + 4, center_y - 2), 2) # Nase pygame.draw.circle(screen, CAT_DARK, (center_x, center_y + 4), 2) def draw_end_message(): """Zeichnet Gewinn- oder Game-Over-Meldung.""" if game_state == "running": return box_width = 500 box_height = 160 box_x = WIDTH // 2 - box_width // 2 box_y = HEIGHT // 2 - box_height // 2 pygame.draw.rect(screen, (0, 0, 0), (box_x, box_y, box_width, box_height), border_radius=16) pygame.draw.rect(screen, WHITE, (box_x + 5, box_y + 5, box_width - 10, box_height - 10), border_radius=14) if game_state == "won": title = "GEWONNEN!" subtitle = "Du hast alle 10 Käsestücke gesammelt." color = GREEN else: title = "GAME OVER!" subtitle = "Die Katze hat die Maus gefangen." color = RED title_text = font_big.render(title, True, color) subtitle_text = font_medium.render(subtitle, True, BLACK) restart_text = font_small.render("Drücke R, um neu zu starten.", True, BLACK) screen.blit(title_text, title_text.get_rect(center=(WIDTH // 2, box_y + 48))) screen.blit(subtitle_text, subtitle_text.get_rect(center=(WIDTH // 2, box_y + 92))) screen.blit(restart_text, restart_text.get_rect(center=(WIDTH // 2, box_y + 128))) def draw_game(): """Zeichnet das gesamte Spiel neu.""" screen.fill(BACKGROUND) draw_hud() draw_maze() for cheese in cheeses: draw_cheese(cheese[0], cheese[1]) draw_mouse() draw_cat() draw_end_message() pygame.display.flip() def handle_keydown(key): """Reagiert auf Tastatureingaben.""" if key in (pygame.K_ESCAPE,): pygame.quit() sys.exit() if key == pygame.K_r: reset_game() return if key in (pygame.K_UP, pygame.K_w): move_mouse(0, -1) elif key in (pygame.K_DOWN, pygame.K_s): move_mouse(0, 1) elif key in (pygame.K_LEFT, pygame.K_a): move_mouse(-1, 0) elif key in (pygame.K_RIGHT, pygame.K_d): move_mouse(1, 0) def main(): """Game Loop: Eingaben lesen, Spiel aktualisieren, neu zeichnen.""" global last_cat_move_time reset_game() while True: for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() sys.exit() if event.type == pygame.KEYDOWN: handle_keydown(event.key) current_time = pygame.time.get_ticks() if current_time - last_cat_move_time >= CAT_MOVE_DELAY: move_cat() last_cat_move_time = current_time draw_game() clock.tick(FPS) if __name__ == "__main__": main()