You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

188 lines
7.4 KiB

import pygame
import random
import sys
pygame.init()
# --- Konstanty okna a rozvržení mřížky ---
SIRKA_OKNA = 600
VYSKA_OKNA = 600
FPS = 30
RADKY = 4
SLOUPCE = 4
KARTICKA_VELIKOST = 100
MEZERA = 20
# Výpočet celkové šířky a výšky mřížky, abychom ji mohli vycentrovat
Mrizka_sirka = (SLOUPCE * KARTICKA_VELIKOST) + ((SLOUPCE - 1) * MEZERA)
Mrizka_vyska = (RADKY * KARTICKA_VELIKOST) + ((RADKY - 1) * MEZERA)
# Odskoky zleva a shora pro vykreslování
Odsazeni_x = (SIRKA_OKNA - Mrizka_sirka) // 2
Odsazeni_y = (VYSKA_OKNA - Mrizka_vyska) // 2
# Barvy (R, G, B)
BILA = (255, 255, 255)
SEDA = (150, 150, 150)
TMAVE_MODRA = (20, 20, 80)
ZELENA_TEXT = (50, 255, 50)
# Potřebujeme 8 barev pro 8 párů = 16 karet
BARVY_PARU = [
(255, 0, 0), # Červená
(0, 255, 0), # Světle Zelená
(0, 0, 255), # Modrá
(255, 255, 0), # Žlutá
(255, 0, 255), # Fialová
(0, 255, 255), # Azurová
(255, 165, 0), # Oranžová
(139, 69, 19) # Hnědá
]
okno = pygame.display.set_mode((SIRKA_OKNA, VYSKA_OKNA))
pygame.display.set_caption("Pexeso (Hledání barevných párů)")
hodiny = pygame.time.Clock()
font = pygame.font.SysFont("arial", 40, bold=True)
font_maly = pygame.font.SysFont("arial", 20)
# --- Třída objektu - objektově orientované programování (OOP) ---
# Použití objektu pro "Kartičku" nám velmi zjednoduší udržování informace
# o tom, jaká barva na kartičce je, a jestli je otočená nebo zakrytá.
class Karticka:
def __init__(self, radek, sloupec, barva_vnitrku):
self.barva = barva_vnitrku
# Stavy kartičky (boolean)
self.odkryta = False # Zda ji hráč právě otočil
self.nalezena = False # Zda už hráč našel její pár (tím ji vyřadil)
# Výpočet její pevné x,y souřadnice na obrazovce podle toho v jakém je sloupci a řádku
self.x = Odsazeni_x + sloupec * (KARTICKA_VELIKOST + MEZERA)
self.y = Odsazeni_y + radek * (KARTICKA_VELIKOST + MEZERA)
# Uložíme si Rect pro zjišťování kolize s myší
self.rect = pygame.Rect(self.x, self.y, KARTICKA_VELIKOST, KARTICKA_VELIKOST)
def vykresli(self):
# Pokud je karta lícem nahoru (odkrytá nebo už nalezena), kreslíme její skrytou barvu
if self.odkryta or self.nalezena:
pygame.draw.rect(okno, self.barva, self.rect)
else:
# Rub karty - šedivá barva
pygame.draw.rect(okno, SEDA, self.rect)
# Obrys kolem kartičky pro lepší vzhled
pygame.draw.rect(okno, BILA, self.rect, 3)
def hlavni_smycka():
# 1. Příprava seznamu barev
# Seznam BARVY_PARU znásobíme 2, abychom od každé barvy měli dvě (pár)
barvy_do_hry = BARVY_PARU * 2
random.shuffle(barvy_do_hry) # Náhodně zamícháme pořadí
# 2. Vytvoření mřížky kartiček (2D pole)
# Vznikne struktura 'seznam v seznamu', ke kartě se přistoupí pomocí karticky[radek][sloupec]
karticky = []
index_barvy = 0
for radek in range(RADKY):
rada = []
for sloupec in range(SLOUPCE):
karta = Karticka(radek, sloupec, barvy_do_hry[index_barvy])
rada.append(karta)
index_barvy += 1
karticky.append(rada)
# Proměnné pro pamatování si, na které karty hráč zrovna kliknul
prvni_vybrana = None
druha_vybrana = None
pocet_pokusu = 0
nalezeno_paru = 0
while True:
# --- Zpracování událostí ---
for udalost in pygame.event.get():
if udalost.type == pygame.QUIT:
pygame.quit()
sys.exit()
# Zjišťování KLIKNUTÍ MYŠÍ
if udalost.type == pygame.MOUSEBUTTONDOWN and udalost.button == 1: # button 1 = levé tlačítko
# Bezpečnostní pojistka - zablokujeme klikání, pokud už máme 2 karty otočené
# a čekáme např. na jejich skrytí v případě, že se neshodují.
if prvni_vybrana is not None and druha_vybrana is not None:
continue
# Kde přesně je myš? Získáme X a Y obrazovky
mys_x, mys_y = pygame.mouse.get_pos()
# Projdeme všechny karty a zjistíme, jestli bod myši je v obdélníku karty
for radek in range(RADKY):
for sloupec in range(SLOUPCE):
karta = karticky[radek][sloupec]
# collidepoint() vrací True, pokud je x,y uvnitř obdélníku karty
if karta.rect.collidepoint(mys_x, mys_y):
# Otočíme kartu, jen když ještě není odkrytá nebo nalezena
if not karta.odkryta and not karta.nalezena:
karta.odkryta = True
# Je to první vybraná karta v tomto tahu?
if prvni_vybrana is None:
prvni_vybrana = karta
else:
# Je to druhá vybraná karta! Tah je dokončen.
druha_vybrana = karta
pocet_pokusu += 1
# --- Vykreslování ---
okno.fill(TMAVE_MODRA)
# Zavoláme metodu vykresli() pro všechny kartičky v tabulce
for radek in range(RADKY):
for sloupec in range(SLOUPCE):
karticky[radek][sloupec].vykresli()
# UI s počtem tahů
text_tahy = font_maly.render(f"Počet pokusů: {pocet_pokusu}", True, BILA)
okno.blit(text_tahy, (10, 10))
# Zpráva o vítězství
if nalezeno_paru == 8: # Maximum možných párů je polovina počtu karet
text_konec = font.render("Vítězství! Skvělá paměť.", True, ZELENA_TEXT)
rect = text_konec.get_rect(center=(SIRKA_OKNA // 2, VYSKA_OKNA - 30))
okno.blit(text_konec, rect)
# Provedeme "vyfocení" na obrazovku ABY BYLA DRUHÁ KARTA VIDĚT PŘED PAUZOU!
pygame.display.flip()
# --- Logika Pexesa (Vyhodnocení po odkrytí druhé karty) ---
if prvni_vybrana is not None and druha_vybrana is not None:
if prvni_vybrana.barva == druha_vybrana.barva:
# Našli jsme PÁR!
prvni_vybrana.nalezena = True
druha_vybrana.nalezena = True
nalezeno_paru += 1
else:
# NENAŠLI. Karty se k sobě nehodí.
# Musíme na 1 vteřinu zastavit program, aby si hráč stihl zapamatovat barvy.
# Použijeme pygame.time.wait(), které "zmrazí" program (hráč nemůže klikat atd.).
# Pro takhle jednoduché výukové pexeso je to naprosto v pořádku.
pygame.time.wait(1000)
# Zase je otočíme rubem vzhůru
prvni_vybrana.odkryta = False
druha_vybrana.odkryta = False
# Vynulujeme výběr pro další tah, ať hráč může volit další karty
prvni_vybrana = None
druha_vybrana = None
# Rychlost smyčky
hodiny.tick(FPS)
if __name__ == "__main__":
# Tady pexeso neběží donekonečna, po vítězství program čeká, dokud jej nezavřeme
hlavni_smycka()