Projekt: Piškvorky
Leden 2026
Zatímco v projektu Knihovna jsem se učil používat třídy a konstruktory, projekt Piškvorky měl jiný cíl: naučit se organizovat kód tak, aby neznečišťoval globální prostor. Hlavním tématem byly Factory Functions a Module Pattern.
Co projekt dělá
Klasická hra pro dva hráče v prohlížeči:
- Hráči (X a O) se střídají v tazích klikáním do mřížky 3x3.
- Hra automaticky detekuje vítězství (řádek, sloupec, diagonála) nebo remízu.
- Zobrazuje, kdo je na řadě.
- Umožňuje restartovat hru bez obnovení stránky.
- Možnost zadat jména hráčů.
Změna myšlení: Moduly vs. Továrny
Nejtěžší částí nebylo naprogramovat logiku hry, ale správně ji rozdělit. Použil jsem dva hlavní koncepty:
- Module Pattern (IIFE): Pro věci, které ve hře existují jen jednou (herní deska, ovládání displeje).
- Factory Function: Pro věci, kterých může být více (hráči).
Herní deska (Gameboard)
Deska je jen jedna, takže jsem použil Modul. Pole board je schované uvnitř funkce a není přístupné přímo z konzole (zapouzdření):
const Gameboard = (() => {
let board = ["", "", "", "", "", "", "", "", ""];
const getBoard = () => board;
const setMark = (index, mark) => {
if (board[index] === "") {
board[index] = mark;
return true;
}
return false;
};
const reset = () => {
board = board.map(() => "");
};
return { getBoard, setMark, reset };
})();
Hráči (Players)
Hráči jsou dva, takže potřebuji továrnu na jejich výrobu:
const Player = (name, mark) => {
return { name, mark };
};
const player1 = Player("Marek", "X");
const player2 = Player("PC", "O");
Logika hry a kontrola výhry
Řízení hry (GameController) je také modul. Drží informaci o tom, kdo je na řadě, a po každém tahu kontroluje výhru.
Výherní kombinace jsem uložil jako pole indexů:
const winningCombinations = [
[0, 1, 2],
[3, 4, 5],
[6, 7, 8], // Řádky
[0, 3, 6],
[1, 4, 7],
[2, 5, 8], // Sloupce
[0, 4, 8],
[2, 4, 6], // Diagonály
];
function checkWin(board) {
return winningCombinations.some((combination) => {
return combination.every((index) => {
return board[index] === currentPlayer.mark;
});
});
}
Použití metod some() a every() udělá kontrolu mnohem elegantnější než hromada if podmínek.
Propojení s HTML (DOM)
Zde jsem se snažil striktně oddělit logiku od vykreslování. Modul DisplayController se stará pouze o DOM.
- Poslouchá kliknutí na buňky.
- Získá index kliknuté buňky (
e.target.dataset.index). - Pošle tento index do GameController.
- Pokud je tah platný, GameController aktualizuje data a řekne DisplayController, ať se překreslí.
GitHub: projekt piškvorky