diff --git a/Finished_Memory_Mouse.py b/Finished_Memory_Mouse.py deleted file mode 100755 index 7a86a54..0000000 --- a/Finished_Memory_Mouse.py +++ /dev/null @@ -1,327 +0,0 @@ -import pygame -import random -import sys -import os - -# ------------------------------- -# Country–Capital Memory Game -# ------------------------------- - -CARD_BACK_COLOR = (100, 100, 200) -CARD_FRONT_COLOR = (230, 230, 250) -MATCH_COLOR = (120, 200, 120) -TEXT_COLOR = (0, 0, 0) -BG_COLOR = (50, 50, 80) -SCREEN_WIDTH, SCREEN_HEIGHT = 800, 600 -FPS = 30 -# Design-Bild (für Kartenrückseite + optionalen Hintergrund) -DESIGN_FILE = "GlobalHintergrund.png" - - - -class MemoryGame: - def __init__(self): - self.deck = [] - self.pair_map = {} - self.matched = [] - self.revealed = [] - self.scores = [0, 0] - self.current_player = 0 - self.font = None - self.card_rects = [] - self.selected = [] - self.found_pairs = 0 - self.total_pairs = 0 - self.running = True - self.awaiting_confirmation = False - self.confirmation_result = None - self.correct_answer_expected = None - self.state = "continent" # continent → americas → difficulty → pairs → game - self.buttons = [] - self.selected_continents = [] - self.level = None - self.pair_count = 6 # Default - - # ------------------------------- - # Card Loading - # ------------------------------- - def load_cards(self, filename): - """Loads pairs from a text file.""" - if not os.path.exists(filename): - print(f"⚠️ File not found: {filename}") - return [] - - pairs = [] - with open(filename, "r", encoding="utf-8") as f: - for line in f: - parts = line.strip().split() - if len(parts) >= 2: - pairs.append((parts[0], parts[1])) - return pairs - - def prepare_deck(self): - """Loads all relevant continent + difficulty files.""" - self.deck = [] - for continent in self.selected_continents: - base = continent - if self.level == "Easy": - self.deck += self.load_cards(base + "-major.txt") - elif self.level == "Normal": - self.deck += self.load_cards(base + "-major.txt") - self.deck += self.load_cards(base + "-Minor.txt") - elif self.level == "Hard": - self.deck += self.load_cards(base + "-major.txt") - self.deck += self.load_cards(base + "-Minor.txt") - self.deck += self.load_cards(base + "-Dependent.txt") - - if not self.deck: - print("⚠️ No cards loaded, check text files.") - sys.exit() - - random.shuffle(self.deck) - # Limit to selected pair count - self.deck = self.deck[:self.pair_count] - - def setup_game(self): - self.cards = [] - self.pair_map = {} - for country, capital in self.deck: - self.cards.append(country) - self.cards.append(capital) - self.pair_map[country] = capital - self.pair_map[capital] = country - random.shuffle(self.cards) - self.matched = [False] * len(self.cards) - self.revealed = [False] * len(self.cards) - self.total_pairs = len(self.deck) - self.card_rects = [] - self.selected = [] - - cols = 4 - rows = (len(self.cards) + cols - 1) // cols - margin = 10 - card_width = (SCREEN_WIDTH - (cols + 1) * margin) // cols - card_height = (SCREEN_HEIGHT - (rows + 1) * margin - 100) // rows - y_offset = 80 - - for i, _ in enumerate(self.cards): - col = i % cols - row = i // cols - x = margin + col * (card_width + margin) - y = y_offset + margin + row * (card_height + margin) - rect = pygame.Rect(x, y, card_width, card_height) - self.card_rects.append(rect) - - # ------------------------------- - # Drawing Menus - # ------------------------------- - def draw_menu(self, screen, title, options): - screen.fill(BG_COLOR) - title_text = self.font.render(title, True, (255, 255, 255)) - screen.blit(title_text, (SCREEN_WIDTH // 2 - title_text.get_width() // 2, 100)) - self.buttons = [] - - for i, option in enumerate(options): - rect = pygame.Rect(SCREEN_WIDTH // 2 - 150, 200 + i * 70, 300, 50) - pygame.draw.rect(screen, (100, 100, 250), rect) - pygame.draw.rect(screen, (255, 255, 255), rect, 2) - text = self.font.render(option, True, (255, 255, 255)) - screen.blit(text, (rect.centerx - text.get_width() // 2, rect.centery - text.get_height() // 2)) - self.buttons.append((rect, option)) - pygame.display.flip() - - def draw_game(self, screen): - screen.fill(BG_COLOR) - title = self.font.render(f"Player {self.current_player + 1}'s turn", True, (255, 255, 255)) - screen.blit(title, (20, 20)) - score_text = self.font.render(f"Scores: P1={self.scores[0]} P2={self.scores[1]}", True, (200, 200, 200)) - screen.blit(score_text, (20, 50)) - - for i, rect in enumerate(self.card_rects): - if self.matched[i]: - color = MATCH_COLOR - elif self.revealed[i]: - color = CARD_FRONT_COLOR - else: - color = CARD_BACK_COLOR - pygame.draw.rect(screen, color, rect) - pygame.draw.rect(screen, (0, 0, 0), rect, 2) - if self.revealed[i] or self.matched[i]: - text = self.font.render(self.cards[i], True, TEXT_COLOR) - text_rect = text.get_rect(center=rect.center) - screen.blit(text, text_rect) - - if self.awaiting_confirmation: - self.draw_confirmation_box(screen) - pygame.display.flip() - - def draw_confirmation_box(self, screen): #y-axis Box - box_rect = pygame.Rect(SCREEN_WIDTH // 2 - 150, SCREEN_HEIGHT // 2 - 320, 300, 160) - pygame.draw.rect(screen, (250, 250, 250), box_rect) - pygame.draw.rect(screen, (0, 0, 0), box_rect, 3) - text = self.font.render("Is that correct?", True, (0, 0, 0)) - screen.blit(text, (box_rect.centerx - text.get_width() // 2, box_rect.y + 20)) - - yes_rect = pygame.Rect(box_rect.x + 50, box_rect.y + 90, 80, 40) - no_rect = pygame.Rect(box_rect.x + 170, box_rect.y + 90, 80, 40) - pygame.draw.rect(screen, (0, 200, 0), yes_rect) - pygame.draw.rect(screen, (200, 0, 0), no_rect) - yes_text = self.font.render("Yes", True, (255, 255, 255)) - no_text = self.font.render("No", True, (255, 255, 255)) - screen.blit(yes_text, (yes_rect.centerx - yes_text.get_width() // 2, yes_rect.centery - yes_text.get_height() // 2)) - screen.blit(no_text, (no_rect.centerx - no_text.get_width() // 2, no_rect.centery - no_text.get_height() // 2)) - self.yes_rect, self.no_rect = yes_rect, no_rect - - # ------------------------------- - # Handling Clicks - # ------------------------------- - def handle_click(self, pos): - if self.state in ["continent", "americas", "difficulty", "pairs"]: - for rect, option in self.buttons: - if rect.collidepoint(pos): - if self.state == "continent": - if option == "Americas": - self.state = "americas" - elif option == "All Continents": - self.selected_continents = ["Europe", "Asia", "Africa", "Oceania", "North-America", "South-America"] - self.state = "difficulty" - else: - self.selected_continents = [option] - self.state = "difficulty" - - elif self.state == "americas": - if option == "North-America": - self.selected_continents = ["North-America"] - elif option == "South-America": - self.selected_continents = ["South-America"] - elif option == "Americas": - self.selected_continents = ["North-America", "South-America"] - self.state = "difficulty" - - elif self.state == "difficulty": - self.level = option - self.state = "pairs" - - elif self.state == "pairs": - self.pair_count = int(option) - self.prepare_deck() - self.setup_game() - self.state = "game" - return - - elif self.state == "game": - if self.awaiting_confirmation: - if self.yes_rect.collidepoint(pos): - self.confirmation_result = "yes" - elif self.no_rect.collidepoint(pos): - self.confirmation_result = "no" - return - - for i, rect in enumerate(self.card_rects): - if rect.collidepoint(pos) and not self.revealed[i] and not self.matched[i]: - self.revealed[i] = True - self.selected.append(i) - return - - # ------------------------------- - # Game Logic Most important - # ------------------------------- - def check_selected(self): - if self.state != "game": - return - - # Wenn zwei Karten ausgewählt wurden → prüfen - if len(self.selected) == 2 and not self.awaiting_confirmation: - a, b = self.selected - is_match = self.pair_map.get(self.cards[a]) == self.cards[b] - self.correct_answer_expected = "yes" if is_match else "no" - self.awaiting_confirmation = True - - # Wenn der Spieler im "Is that correct?"-Dialog geantwortet hat - elif self.awaiting_confirmation and self.confirmation_result: - a, b = self.selected - expected = self.correct_answer_expected - player_correct = self.confirmation_result == expected - - if player_correct: - # Spieler hat korrekt geantwortet - if expected == "yes": - # Richtiges Paar bestätigt - self.matched[a] = self.matched[b] = True - self.scores[self.current_player] += 1 - self.found_pairs += 1 - else: - # "No" richtig bestätigt → kein Paar - self.revealed[a] = self.revealed[b] = False - else: - # Spieler hat sich vertan → Karten umdrehen & Punkt abziehen - self.scores[self.current_player] -= 1 - self.revealed[a] = self.revealed[b] = False - - # Reset für nächsten Zug - self.awaiting_confirmation = False - self.confirmation_result = None - self.selected = [] - self.current_player = 1 - self.current_player - - # ------------------------------- - # Main Game Loop - # ------------------------------- - def run(self): - pygame.init() - screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT)) - pygame.display.set_caption("Country–Capital Memory Game") - clock = pygame.time.Clock() - self.font = pygame.font.SysFont(None, 32) - - while self.running: - for event in pygame.event.get(): - if event.type == pygame.QUIT: - self.running = False - elif event.type == pygame.MOUSEBUTTONDOWN: - self.handle_click(event.pos) - - if self.state == "continent": - self.draw_menu(screen, "Select Continent", ["Europe", "Americas", "Asia", "Africa", "Oceania", "All Continents"]) - elif self.state == "americas": - self.draw_menu(screen, "Select Region", ["North-America", "South-America", "Americas"]) - elif self.state == "difficulty": - self.draw_menu(screen, "Select Difficulty", ["Easy", "Normal", "Hard"]) - elif self.state == "pairs": - self.draw_menu(screen, "Select Number of Pairs", ["4", "6", "8", "10", "12"]) - elif self.state == "game": - self.draw_game(screen) - self.check_selected() - if self.found_pairs == self.total_pairs: - self.display_winner(screen) - pygame.display.flip() - pygame.time.wait(4000) - self.running = False - - clock.tick(FPS) - - pygame.quit() - sys.exit() - - # ------------------------------- - # Winner Display - # ------------------------------- - def display_winner(self, screen): - if self.scores[0] > self.scores[1]: - text = "🏆 Player 1 Wins!" - elif self.scores[1] > self.scores[0]: - text = "🏆 Player 2 Wins!" - else: - text = "🤝 Draw!" - win_text = self.font.render(text, True, (255, 255, 0)) - rect = win_text.get_rect(center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2)) - screen.blit(win_text, rect) - - -# ------------------------------- -# Run the Game -# ------------------------------- -if __name__ == "__main__": - game = MemoryGame() - game.run() - diff --git a/app.py b/app.py new file mode 100644 index 0000000..9aca011 --- /dev/null +++ b/app.py @@ -0,0 +1,34 @@ +from flask import Flask, request, render_template +import subprocess +import sys +import os + +app = Flask(__name__) + + +# Option A: Direkt die Python-Funktion ausführen (wenn dein Spiel in demselben Prozess laufen darf) +# from global_match_memory import run_memory + +@app.get("/") +def home(): + return render_template("index.html") + + +@app.get("/start") +def start_game(): + players = request.args.get("players", "1") + # --- Option A: direkt aufrufen --- + # run_memory(int(players)) + # return "started" + + # --- Option B: separates Fenster/Prozess (robuster) --- + # Startet global_match_memory.py als eigenen Prozess mit Argument "players" + py = sys.executable # aktueller Python-Interpreter + script_path = os.path.join(os.path.dirname(__file__), "global_match_memory.py") + subprocess.Popen([py, script_path, players]) + return "started" + + +if __name__ == "__main__": + # Auf Mac/Windows lokal erreichbar: http://localhost:5000 + app.run(host="127.0.0.1", port=5000, debug=True) diff --git a/global_match_memory.py b/global_match_memory.py index 0c2a2d6..163be1f 100644 --- a/global_match_memory.py +++ b/global_match_memory.py @@ -1,334 +1,345 @@ import pygame -import sys import random +import sys import os -from typing import List, Tuple -# ---------------------------------------------------------- -# Design / Layout -# ---------------------------------------------------------- -WINDOW_W, WINDOW_H = 900, 900 -BG_COLOR = (10, 58, 94) # Global-Match Blau -HUD_BAR_H = 88 -PADDING = 28 -GRID_COLS, GRID_ROWS = 4, 3 # 12 Karten (6 Paare) -GAP = 18 -CARD_RADIUS = 20 -CARD_BORDER = (220, 226, 235) -CARD_FACE = (255, 255, 255) -CARD_TEXT = (22, 44, 66) -BADGE_BG = (18, 122, 138) -BADGE_TEXT = (255, 255, 255) -HIGHLIGHT = (255, 224, 128) +# ------------------------------- +# Country–Capital Memory Game +# ------------------------------- -LOGO_FILE = "LogoSpiel.png" # <— Dein Logo (Rückseite) +CARD_BACK_COLOR = (100, 100, 200) +CARD_FRONT_COLOR = (230, 230, 250) +MATCH_COLOR = (120, 200, 120) +TEXT_COLOR = (0, 0, 0) +BG_COLOR = (50, 50, 80) +SCREEN_WIDTH, SCREEN_HEIGHT = 800, 600 +FPS = 30 +# Design-Bild (für Kartenrückseite + optionalen Hintergrund) +DESIGN_FILE = "GlobalHintergrund.png" -MISMATCH_DELAY_MS = 900 -SINGLEPLAYER_SECONDS = 90 -FPS = 60 -# ---------------------------------------------------------- -# Daten (Deutsch) -# ---------------------------------------------------------- -DATA = { - "Europa": [ - ("Deutschland", "Berlin"), ("Frankreich", "Paris"), ("Italien", "Rom"), - ("Spanien", "Madrid"), ("Portugal", "Lissabon"), ("Niederlande", "Amsterdam"), - ("Belgien", "Brüssel"), ("Österreich", "Wien"), ("Schweiz", "Bern"), - ("Polen", "Warschau"), ("Tschechien", "Prag"), ("Ungarn", "Budapest"), - ("Dänemark", "Kopenhagen"), ("Schweden", "Stockholm"), ("Norwegen", "Oslo") - ], - "Amerika": [ - ("USA", "Washington, D.C."), ("Kanada", "Ottawa"), ("Mexiko", "Mexiko-Stadt"), - ("Brasilien", "Brasília"), ("Argentinien", "Buenos Aires"), ("Chile", "Santiago"), - ("Peru", "Lima"), ("Kolumbien", "Bogotá"), ("Venezuela", "Caracas"), - ("Uruguay", "Montevideo"), ("Bolivien", "Sucre"), ("Ecuador", "Quito") - ], - "Asien": [ - ("China", "Peking"), ("Japan", "Tokio"), ("Südkorea", "Seoul"), - ("Indien", "Neu-Delhi"), ("Pakistan", "Islamabad"), - ("Bangladesch", "Dhaka"), ("Sri Lanka", "Sri Jayewardenepura Kotte"), - ("Nepal", "Kathmandu"), ("Saudi-Arabien", "Riad"), - ("VAE", "Abu Dhabi"), ("Türkei", "Ankara"), ("Indonesien", "Jakarta"), - ("Malaysia", "Kuala Lumpur"), ("Thailand", "Bangkok"), ("Vietnam", "Hanoi") - ], -} -# ---------------------------------------------------------- -# Helpers -# ---------------------------------------------------------- -def load_logo_scaled(size: Tuple[int, int]) -> pygame.Surface: - """Lädt LogoSpiel.png und skaliert mit 10% Rand. Fallback: dunkles GM-Pattern.""" - w, h = size - surf = pygame.Surface((w, h), pygame.SRCALPHA) - # weiße Karte - pygame.draw.rect(surf, CARD_FACE, (0, 0, w, h), border_radius=CARD_RADIUS) - pygame.draw.rect(surf, CARD_BORDER, (0, 0, w, h), width=2, border_radius=CARD_RADIUS) +class MemoryGame: + def __init__(self): + self.deck = [] + self.pair_map = {} + self.matched = [] + self.revealed = [] + self.scores = [0, 0] + self.current_player = 0 + self.font = None + self.card_rects = [] + self.selected = [] + self.found_pairs = 0 + self.total_pairs = 0 + self.running = True + self.awaiting_confirmation = False + self.confirmation_result = None + self.correct_answer_expected = None + self.state = "continent" # continent → americas → difficulty → pairs → game + self.buttons = [] + self.selected_continents = [] + self.level = None + self.pair_count = 6 # Default - inner_pad = int(min(w, h) * 0.12) - logo_rect = pygame.Rect(inner_pad, inner_pad, w - 2*inner_pad, h - 2*inner_pad) + # ------------------------------- + # Card Loading + # ------------------------------- + def load_cards(self, filename): + """Loads pairs from a text file.""" + if not os.path.exists(filename): + print(f"⚠️ File not found: {filename}") + return [] - if os.path.exists(LOGO_FILE): - try: - img = pygame.image.load(LOGO_FILE).convert_alpha() - img = scale_to_fit(img, logo_rect.size) - surf.blit(img, ( - logo_rect.centerx - img.get_width() // 2, - logo_rect.centery - img.get_height() // 2 - )) - return surf - except Exception: - pass + pairs = [] + with open(filename, "r", encoding="utf-8") as f: + for line in f: + parts = line.strip().split() + if len(parts) >= 2: + pairs.append((parts[0], parts[1])) + return pairs - # Fallback: Text "GLOBAL MATCH" - font = pygame.font.SysFont(None, int(h * 0.16), bold=True) - t1 = font.render("GLOBAL", True, (10, 80, 110)) - t2 = font.render("MATCH", True, (240, 180, 60)) - surf.blit(t1, (w//2 - t1.get_width()//2, h//2 - t1.get_height())) - surf.blit(t2, (w//2 - t2.get_width()//2, h//2 + 4)) - return surf + def prepare_deck(self): + """Loads all relevant continent + difficulty files.""" + self.deck = [] + for continent in self.selected_continents: + base = continent + if self.level == "Easy": + self.deck += self.load_cards(base + "-major.txt") + elif self.level == "Normal": + self.deck += self.load_cards(base + "-major.txt") + self.deck += self.load_cards(base + "-Minor.txt") + elif self.level == "Hard": + self.deck += self.load_cards(base + "-major.txt") + self.deck += self.load_cards(base + "-Minor.txt") + self.deck += self.load_cards(base + "-Dependent.txt") -def scale_to_fit(img: pygame.Surface, target_size: Tuple[int, int]) -> pygame.Surface: - tw, th = target_size - iw, ih = img.get_width(), img.get_height() - scale = min(tw / iw, th / ih) - return pygame.transform.smoothscale(img, (int(iw * scale), int(ih * scale))) + if not self.deck: + print("⚠️ No cards loaded, check text files.") + sys.exit() -def wrap_text(text: str, font: pygame.font.Font, max_w: int) -> List[str]: - words = text.split() - lines, line = [], "" - for w in words: - t = (line + " " + w).strip() - if font.size(t)[0] <= max_w: - line = t - else: - if line: - lines.append(line) - line = w - if line: - lines.append(line) - return lines + random.shuffle(self.deck) + # Limit to selected pair count + self.deck = self.deck[:self.pair_count] -def pick_payloads(level: str, n_pairs=6) -> List[dict]: - pool = DATA[level][:] if level in DATA else DATA["Europa"][:] - random.shuffle(pool) - chosen = pool[:n_pairs] - payloads = [] - pid = 0 - for land, cap in chosen: - payloads.append({"pair": pid, "label": land, "kind": "country"}) - payloads.append({"pair": pid, "label": cap, "kind": "capital"}) - pid += 1 - random.shuffle(payloads) - return payloads + def setup_game(self): + self.cards = [] + self.pair_map = {} + for country, capital in self.deck: + self.cards.append(country) + self.cards.append(capital) + self.pair_map[country] = capital + self.pair_map[capital] = country + random.shuffle(self.cards) + self.matched = [False] * len(self.cards) + self.revealed = [False] * len(self.cards) + self.total_pairs = len(self.deck) + self.card_rects = [] + self.selected = [] -# ---------------------------------------------------------- -# Card -# ---------------------------------------------------------- -class Card: - def __init__(self, rect: pygame.Rect, payload: dict, fonts, back_img: pygame.Surface): - self.rect = rect - self.payload = payload - self.font, self.small = fonts - self.back = pygame.transform.smoothscale(back_img, (rect.w, rect.h)) - self.front = pygame.Surface((rect.w, rect.h), pygame.SRCALPHA) - self.is_revealed = False - self.is_matched = False - self._render_front() + cols = 4 + rows = (len(self.cards) + cols - 1) // cols + margin = 10 + card_width = (SCREEN_WIDTH - (cols + 1) * margin) // cols + card_height = (SCREEN_HEIGHT - (rows + 1) * margin - 100) // rows + y_offset = 80 - def _render_front(self): - w, h = self.rect.w, self.rect.h - # weiße Karte + Rand - pygame.draw.rect(self.front, CARD_FACE, (0, 0, w, h), border_radius=CARD_RADIUS) - pygame.draw.rect(self.front, CARD_BORDER, (0, 0, w, h), width=2, border_radius=CARD_RADIUS) + for i, _ in enumerate(self.cards): + col = i % cols + row = i // cols + x = margin + col * (card_width + margin) + y = y_offset + margin + row * (card_height + margin) + rect = pygame.Rect(x, y, card_width, card_height) + self.card_rects.append(rect) - # Badge - badge = "Land" if self.payload["kind"] == "country" else "Hauptstadt" - bsurf = self.small.render(badge, True, BADGE_TEXT) - bw, bh = bsurf.get_size() - badge_bg = pygame.Surface((bw + 18, bh + 8), pygame.SRCALPHA) - pygame.draw.rect(badge_bg, BADGE_BG, badge_bg.get_rect(), border_radius=12) - badge_bg.blit(bsurf, (9, 4)) - self.front.blit(badge_bg, (w - badge_bg.get_width() - 12, 12)) - - # Text - lines = wrap_text(self.payload["label"], self.font, w - 28) - total_h = len(lines) * self.font.get_height() - y = h//2 - total_h//2 - for line in lines: - ts = self.font.render(line, True, CARD_TEXT) - self.front.blit(ts, (w//2 - ts.get_width()//2, y)) - y += self.font.get_height() - - def draw(self, screen: pygame.Surface): - screen.blit(self.front if (self.is_revealed or self.is_matched) else self.back, - (self.rect.x, self.rect.y)) - - def handle_click(self, pos) -> bool: - if self.rect.collidepoint(pos) and not self.is_matched and not self.is_revealed: - self.is_revealed = True - return True - return False - -# ---------------------------------------------------------- -# Main Game -# ---------------------------------------------------------- -def run_memory(level: str = "Europa", mode: str = "single"): - """ - level: 'Europa' | 'Amerika' | 'Asien' - mode : 'single' (Zeit) | 'two' (Punkte, abwechselnd) - """ - pygame.init() - screen = pygame.display.set_mode((WINDOW_W, WINDOW_H)) - pygame.display.set_caption(f"Global Match – {level} ({'1 Spieler' if mode=='single' else '2 Spieler'})") - clock = pygame.time.Clock() - - ui_font = pygame.font.SysFont(None, 32, bold=True) - big_font = pygame.font.SysFont(None, 50, bold=True) - card_font = pygame.font.SysFont(None, 28, bold=True) - small_font = pygame.font.SysFont(None, 20, bold=True) - - # Grid berechnen - grid_w = WINDOW_W - 2 * PADDING - grid_h = WINDOW_H - HUD_BAR_H - 2 * PADDING - cell_w = (grid_w - (GRID_COLS - 1) * GAP) // GRID_COLS - cell_h = (grid_h - (GRID_ROWS - 1) * GAP) // GRID_ROWS - card_size = min(cell_w, cell_h) - start_x = PADDING + (grid_w - (card_size * GRID_COLS + GAP * (GRID_COLS - 1))) // 2 - start_y = HUD_BAR_H + PADDING + (grid_h - (card_size * GRID_ROWS + GAP * (GRID_ROWS - 1))) // 2 - - # Karten erzeugen - back_img = load_logo_scaled((card_size, card_size)) - payloads = pick_payloads(level, n_pairs=6) - - cards: List[Card] = [] - k = 0 - for r in range(GRID_ROWS): - for c in range(GRID_COLS): - if k >= len(payloads): - continue - rect = pygame.Rect(start_x + c * (card_size + GAP), - start_y + r * (card_size + GAP), - card_size, card_size) - cards.append(Card(rect, payloads[k], (card_font, small_font), back_img)) - k += 1 - - # Spielstatus - revealed: List[Card] = [] - lock_until = 0 - total_matches = 0 - need_matches = len(payloads) // 2 - p_turn = 1 - score = {1: 0, 2: 0} - time_left = SINGLEPLAYER_SECONDS * 1000 if mode == "single" else None - end_text = None - - # Loop - while True: - dt = clock.tick(FPS) - now = pygame.time.get_ticks() - - # Events - for e in pygame.event.get(): - if e.type == pygame.QUIT: - pygame.quit() - sys.exit() - if e.type == pygame.KEYDOWN and end_text: - if e.key in (pygame.K_RETURN, pygame.K_SPACE): - pygame.quit() - return - if e.type == pygame.MOUSEBUTTONDOWN and e.button == 1 and not end_text: - if now < lock_until: - continue - for card in cards: - if card.handle_click(e.pos): - revealed.append(card) - if len(revealed) == 2: - a, b = revealed - # Match (gleiches Paar, aber unterschiedliche Art) - if a.payload["pair"] == b.payload["pair"] and a.payload["kind"] != b.payload["kind"]: - a.is_matched = b.is_matched = True - revealed.clear() - total_matches += 1 - if mode == "two": - score[p_turn] += 1 - if total_matches == need_matches: - if mode == "single": - end_text = "Geschafft! Alle 6 Paare." - else: - if score[1] > score[2]: - end_text = f"Spielende – Spieler 1 gewinnt ({score[1]}:{score[2]})" - elif score[2] > score[1]: - end_text = f"Spielende – Spieler 2 gewinnt ({score[2]}:{score[1]})" - else: - end_text = f"Unentschieden ({score[1]}:{score[2]})" - else: - lock_until = now + MISMATCH_DELAY_MS - elif len(revealed) > 2: - # Sicherheitsreset – nur die letzten 2 behalten - for old in revealed[:-2]: - old.is_revealed = False - revealed = revealed[-2:] - - # Timer (Singleplayer) - if not end_text and mode == "single" and time_left is not None: - time_left -= dt - if time_left <= 0: - time_left = 0 - end_text = "Zeit abgelaufen!" - - # Mismatch zurückdrehen + Spielerwechsel - if not end_text and len(revealed) == 2 and lock_until and now >= lock_until: - a, b = revealed - a.is_revealed = False - b.is_revealed = False - revealed.clear() - lock_until = 0 - if mode == "two": - p_turn = 2 if p_turn == 1 else 1 - - # ----------------- Render ----------------- + # ------------------------------- + # Drawing Menus + # ------------------------------- + def draw_menu(self, screen, title, options): screen.fill(BG_COLOR) + title_text = self.font.render(title, True, (255, 255, 255)) + screen.blit(title_text, (SCREEN_WIDTH // 2 - title_text.get_width() // 2, 100)) + self.buttons = [] - # HUD - pygame.draw.rect(screen, (7, 42, 70), (0, 0, WINDOW_W, HUD_BAR_H)) - title = ui_font.render(f"Global Match – {level}", True, (255, 255, 255)) - screen.blit(title, (PADDING, HUD_BAR_H//2 - title.get_height()//2)) - - if mode == "single": - tsec = (time_left // 1000) if time_left is not None else 0 - timer = ui_font.render(f"Zeit: {tsec}s", True, HIGHLIGHT) - screen.blit(timer, (WINDOW_W - PADDING - timer.get_width(), HUD_BAR_H//2 - timer.get_height()//2)) - else: - s = ui_font.render(f"P1: {score[1]} P2: {score[2]} Zug: P{p_turn}", True, HIGHLIGHT) - screen.blit(s, (WINDOW_W - PADDING - s.get_width(), HUD_BAR_H//2 - s.get_height()//2)) - - # Karten - for card in cards: - card.draw(screen) - - # Overlay / Ende - if end_text: - overlay = pygame.Surface((WINDOW_W, WINDOW_H), pygame.SRCALPHA) - overlay.fill((0, 0, 0, 140)) - screen.blit(overlay, (0, 0)) - msg = big_font.render(end_text, True, (255, 255, 255)) - sub = ui_font.render("ENTER/SPACE zum Beenden", True, (240, 240, 240)) - screen.blit(msg, (WINDOW_W//2 - msg.get_width()//2, WINDOW_H//2 - 30)) - screen.blit(sub, (WINDOW_W//2 - sub.get_width()//2, WINDOW_H//2 + 20)) - + for i, option in enumerate(options): + rect = pygame.Rect(SCREEN_WIDTH // 2 - 150, 200 + i * 70, 300, 50) + pygame.draw.rect(screen, (100, 100, 250), rect) + pygame.draw.rect(screen, (255, 255, 255), rect, 2) + text = self.font.render(option, True, (255, 255, 255)) + screen.blit(text, (rect.centerx - text.get_width() // 2, rect.centery - text.get_height() // 2)) + self.buttons.append((rect, option)) pygame.display.flip() -# ---------------------------------------------------------- -# Direktstart (zu Testzwecken) -# ---------------------------------------------------------- + def draw_game(self, screen): + screen.fill(BG_COLOR) + title = self.font.render(f"Player {self.current_player + 1}'s turn", True, (255, 255, 255)) + screen.blit(title, (20, 20)) + score_text = self.font.render(f"Scores: P1={self.scores[0]} P2={self.scores[1]}", True, (200, 200, 200)) + screen.blit(score_text, (20, 50)) + + for i, rect in enumerate(self.card_rects): + if self.matched[i]: + color = MATCH_COLOR + elif self.revealed[i]: + color = CARD_FRONT_COLOR + else: + color = CARD_BACK_COLOR + pygame.draw.rect(screen, color, rect) + pygame.draw.rect(screen, (0, 0, 0), rect, 2) + if self.revealed[i] or self.matched[i]: + text = self.font.render(self.cards[i], True, TEXT_COLOR) + text_rect = text.get_rect(center=rect.center) + screen.blit(text, text_rect) + + if self.awaiting_confirmation: + self.draw_confirmation_box(screen) + pygame.display.flip() + + def draw_confirmation_box(self, screen): #y-axis Box + box_rect = pygame.Rect(SCREEN_WIDTH // 2 - 150, SCREEN_HEIGHT // 2 - 320, 300, 160) + pygame.draw.rect(screen, (250, 250, 250), box_rect) + pygame.draw.rect(screen, (0, 0, 0), box_rect, 3) + text = self.font.render("Is that correct?", True, (0, 0, 0)) + screen.blit(text, (box_rect.centerx - text.get_width() // 2, box_rect.y + 20)) + + yes_rect = pygame.Rect(box_rect.x + 50, box_rect.y + 90, 80, 40) + no_rect = pygame.Rect(box_rect.x + 170, box_rect.y + 90, 80, 40) + pygame.draw.rect(screen, (0, 200, 0), yes_rect) + pygame.draw.rect(screen, (200, 0, 0), no_rect) + yes_text = self.font.render("Yes", True, (255, 255, 255)) + no_text = self.font.render("No", True, (255, 255, 255)) + screen.blit(yes_text, (yes_rect.centerx - yes_text.get_width() // 2, yes_rect.centery - yes_text.get_height() // 2)) + screen.blit(no_text, (no_rect.centerx - no_text.get_width() // 2, no_rect.centery - no_text.get_height() // 2)) + self.yes_rect, self.no_rect = yes_rect, no_rect + + # ------------------------------- + # Handling Clicks + # ------------------------------- + def handle_click(self, pos): + if self.state in ["continent", "americas", "difficulty", "pairs"]: + for rect, option in self.buttons: + if rect.collidepoint(pos): + if self.state == "continent": + if option == "Americas": + self.state = "americas" + elif option == "All Continents": + self.selected_continents = ["Europe", "Asia", "Africa", "Oceania", "North-America", "South-America"] + self.state = "difficulty" + else: + self.selected_continents = [option] + self.state = "difficulty" + + elif self.state == "americas": + if option == "North-America": + self.selected_continents = ["North-America"] + elif option == "South-America": + self.selected_continents = ["South-America"] + elif option == "Americas": + self.selected_continents = ["North-America", "South-America"] + self.state = "difficulty" + + elif self.state == "difficulty": + self.level = option + self.state = "pairs" + + elif self.state == "pairs": + self.pair_count = int(option) + self.prepare_deck() + self.setup_game() + self.state = "game" + return + + elif self.state == "game": + if self.awaiting_confirmation: + if self.yes_rect.collidepoint(pos): + self.confirmation_result = "yes" + elif self.no_rect.collidepoint(pos): + self.confirmation_result = "no" + return + + for i, rect in enumerate(self.card_rects): + if rect.collidepoint(pos) and not self.revealed[i] and not self.matched[i]: + self.revealed[i] = True + self.selected.append(i) + return + + # ------------------------------- + # Game Logic Most important + # ------------------------------- + def check_selected(self): + if self.state != "game": + return + + # Wenn zwei Karten ausgewählt wurden → prüfen + if len(self.selected) == 2 and not self.awaiting_confirmation: + a, b = self.selected + is_match = self.pair_map.get(self.cards[a]) == self.cards[b] + self.correct_answer_expected = "yes" if is_match else "no" + self.awaiting_confirmation = True + + # Wenn der Spieler im "Is that correct?"-Dialog geantwortet hat + elif self.awaiting_confirmation and self.confirmation_result: + a, b = self.selected + expected = self.correct_answer_expected + player_correct = self.confirmation_result == expected + + if player_correct: + # Spieler hat korrekt geantwortet + if expected == "yes": + # Richtiges Paar bestätigt + self.matched[a] = self.matched[b] = True + self.scores[self.current_player] += 1 + self.found_pairs += 1 + else: + # "No" richtig bestätigt → kein Paar + self.revealed[a] = self.revealed[b] = False + else: + # Spieler hat sich vertan → Karten umdrehen & Punkt abziehen + self.scores[self.current_player] -= 1 + self.revealed[a] = self.revealed[b] = False + + # Reset für nächsten Zug + self.awaiting_confirmation = False + self.confirmation_result = None + self.selected = [] + self.current_player = 1 - self.current_player + + # ------------------------------- + # Main Game Loop + # ------------------------------- + def run(self): + pygame.init() + screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT)) + pygame.display.set_caption("Country–Capital Memory Game") + clock = pygame.time.Clock() + self.font = pygame.font.SysFont(None, 32) + + while self.running: + for event in pygame.event.get(): + if event.type == pygame.QUIT: + self.running = False + elif event.type == pygame.MOUSEBUTTONDOWN: + self.handle_click(event.pos) + + if self.state == "continent": + self.draw_menu(screen, "Select Continent", ["Europe", "Americas", "Asia", "Africa", "Oceania", "All Continents"]) + elif self.state == "americas": + self.draw_menu(screen, "Select Region", ["North-America", "South-America", "Americas"]) + elif self.state == "difficulty": + self.draw_menu(screen, "Select Difficulty", ["Easy", "Normal", "Hard"]) + elif self.state == "pairs": + self.draw_menu(screen, "Select Number of Pairs", ["4", "6", "8", "10", "12"]) + elif self.state == "game": + self.draw_game(screen) + self.check_selected() + if self.found_pairs == self.total_pairs: + self.display_winner(screen) + pygame.display.flip() + pygame.time.wait(4000) + self.running = False + + clock.tick(FPS) + + pygame.quit() + sys.exit() + + # ------------------------------- + # Winner Display + # ------------------------------- + def display_winner(self, screen): + if self.scores[0] > self.scores[1]: + text = "🏆 Player 1 Wins!" + elif self.scores[1] > self.scores[0]: + text = "🏆 Player 2 Wins!" + else: + text = "🤝 Draw!" + win_text = self.font.render(text, True, (255, 255, 0)) + rect = win_text.get_rect(center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2)) + screen.blit(win_text, rect) + +def run_memory(players: int = 1): + pygame.init() + screen = pygame.display.set_mode((900, 600)) + pygame.display.set_caption(f"Global Match – {players} Spieler") + clock = pygame.time.Clock() + + running = True + while running: + for event in pygame.event.get(): + if event.type == pygame.QUIT: + running = False + + screen.fill((10, 42, 53)) + # ... dein Memory-Rendering / Logic ... + pygame.display.flip() + clock.tick(60) + + pygame.quit() + +# ------------------------------- +# Run the Game +# ------------------------------- if __name__ == "__main__": - lvl = "Europa" - md = "single" - if len(sys.argv) >= 2: - lvl = sys.argv[1] - if len(sys.argv) >= 3: - md = sys.argv[2] - run_memory(level=lvl, mode=md) - + game = MemoryGame() + game.run() diff --git a/index.html b/templates/index.html similarity index 93% rename from index.html rename to templates/index.html index b34b6c9..09bcd6a 100644 --- a/index.html +++ b/templates/index.html @@ -1,4 +1,4 @@ -from global_match_memory import run_memory + @@ -134,7 +134,7 @@ from global_match_memory import run_memory