Portfolio
Projekt: Pokémon Memory Game

Projekt: Pokémon Memory Game

Březen 2026

Po zvládnutí základů Reactu přišla první opravdová výzva z The Odin Project – paměťová hra. Cílem bylo vytvořit aplikaci, která komunikuje s externím API, dynamicky mění UI a hlídá skóre uživatele.

Co projekt dělá

Hra testuje paměť hráče pomocí náhodně generovaných karet Pokémonů:

  • Načtení 12 unikátních Pokémonů z PokeAPI při startu.
  • Míchání pořadí karet po každém kliknutí.
  • Sledování aktuálního skóre (Current Score).
  • Ukládání nejvyššího dosaženého výsledku (Best Score).
  • Reset hry, pokud hráč klikne na stejného Pokémona dvakrát.

Práce s API a useEffect

Karty se načítají asynchronně. Použil jsem useEffect, aby se data stáhla hned při prvním renderu komponenty:

useEffect(() => {
	const getPokemons = async () => {
		const response = await fetch(
			"[https://pokeapi.co/api/v2/pokemon?limit=12](https://pokeapi.co/api/v2/pokemon?limit=12)",
		);
		const data = await response.json();
		// transformace dat a nastavení stavu...
	};
	getPokemons();
}, []);

Nejtěžší bylo zajistit, aby se obrázky načetly dříve, než se karty zobrazí, aby uživatel neviděl prázdná místa.

Logika míchání a stavu

Hlavní logiku hry drží stav cards. Po každém kliknutí se pole s Pokémony zamíchá, což vynutí re-render komponenty a změnu pozic:

const handleCardClick = (id) => {
	if (clickedCards.includes(id)) {
		resetGame();
	} else {
		setClickedCards([...clickedCards, id]);
		setScore(score + 1);
		shuffleArray(cards);
	}
};

Komponentová struktura

Aplikaci jsem rozdělil na několik znovupoužitelných částí:

  • Header: Zobrazuje název a aktuální/nejlepší skóre.
  • CardGrid: Kontejner, který mapuje pole karet.
  • Card: Jednotlivá karta s obrázkem a jménem Pokémona.

Co bylo náročné

  • Asynchronní fetch: Pochopit, jak správně řetězit požadavky na API, abych dostal nejen jména, ale i URL obrázků.
  • Imutabilita stavu: Musel jsem si dávat pozor, abych neměnil původní pole v useState přímo, ale vždy vytvářel kopii.
  • Styling: Zarovnání karet pomocí CSS Gridu tak, aby hra vypadala dobře i na mobilu.

Co jsem se naučil

React Hooks: Práce s useState pro skóre a useEffect pro side-efekty (volání API).

Práce s daty: Mapování polí objektů a jejich transformace pro potřeby UI.

Lifecycle komponenty: Kdy se co vykresluje a proč je důležité čistit side-efekty.

Conditional Rendering: Zobrazení loading spinneru, zatímco se čeká na data z API.

Co dál

Projekt je funkční, ale v budoucnu bych chtěl přidat:

  • Možnost vybrat si generaci Pokémonů.
  • Animace pomocí Framer Motion při míchání karet.
  • Zvukové efekty při kliknutí a prohře.
  • LocalStorage pro trvalé uložení rekordního skóre.

GitHub: Pokemon_memory_game