← Lekcje
JavaScript · lekcja 28

Gra 3/5:
budujemy planszę 3×3

Plan tematu (5 godzin):

  1. Godzina 1: zdarzenie, addEventListener, obiekt zdarzenia
  2. Godzina 2: nie tylko klik - inne zdarzenia (keydown, submit)
  3. Godzina 3 (dziś): budujemy planszę 3×3 (kółko i krzyżyk)
  4. Godzina 4: kliknięcie pola zapisuje ruch
  5. Godzina 5: kto wygrał - sprawdzamy planszę
Rozgrzewka · 3 minuty

Rozgrzewka: inne zdarzenia niż klik

  1. Jaka metoda podłącza funkcję do zdarzenia (np. submit) na wybranym elemencie?
  2. Co robi e.preventDefault() wywołane w funkcji obsługującej zdarzenie submit?
  3. Jakie zdarzenie zdarza się, gdy użytkownik wciska klawisz na klawiaturze?
Część 1 · Siatka na stronie

Plansza jako siatka 9 przycisków

Planszę 3×3 budujecie z dziewięciu zwykłych przycisków w jednym kontenerze <div id="board">. Żeby ustawiły się w trzech rzędach po trzy, kontener dostaje display: grid - znany z CSS sposób układania elementów w rzędach i kolumnach.

#board {
  display: grid;
  grid-template-columns: repeat(3, 100px);
  gap: 4px;
}
<div id="board"> <button></button> <button></button> <button></button> … (razem 9) </div> display: grid trzy rzędy po trzy pola
MDN, Learn_web_development/Core/CSS_layout/Grids: „CSS grid layout is a two-dimensional layout system for the web. It lets you organize content into rows and columns and offers many features to simplify the creation of complex layouts.” - „Siatka CSS to dwuwymiarowy system układania treści na stronie. Pozwala organizować zawartość w rzędy i kolumny i oferuje wiele funkcji ułatwiających tworzenie złożonych układów.” (tłum. własne)
Część 2 · Stan planszy

Tablica stanu planszy

Same przyciski to tylko obrazek. Żeby gra wiedziała, co jest gdzie wpisane, potrzebuje osobnego miejsca w pamięci - tablicy board z dziewięcioma polami, po jednym na każdy przycisk. Na start każde pole jest puste - pusty tekst "".

let board = Array(9).fill("");
0 1 2 3 4 5 6 7 8 "" "" "" "" "" "" "" "" "" board = ["", "", "", "", "", "", "", "", ""]
Część 3 · Klik i indeks

Mapowanie: klik na pole → indeks w tablicy

Żeby wiedzieć, które pole tablicy board odpowiada klikniętemu przyciskowi, każdy przycisk dostaje klasę cell i atrybut data-index z numerem swojego pola (0-8). document.getElementsByClassName("cell") (lekcja 21) zwraca kolekcję wszystkich dziewięciu przycisków naraz, a pętla for przechodzi po niej i każdemu po kolei ustawia numer pola.

const cells = document.getElementsByClassName("cell");
for (let i = 0; i < cells.length; i++) {
  cells[i].setAttribute("data-index", i);
}
przycisk data-index="4" klik → e.target 0 1 2 3 4 5 board[4]
MDN, Web/API/Document/getElementsByClassName, jak w lekcji 51 (deck 51_js_dom_2_slajdy.html)
Egzamin EE.09

Tak pytają na egzaminie o tablice i siatki

Ten temat to projekt własny, nie ma w bankach CKE osobnego pytania o „planszę do gry”. Pytania o tworzenie tablic (Array, indeksy, dostęp przez klucz) już wykorzystaliście w temacie „Tablice w JavaScript” (lekcje 11-13) - tam poznaliście m.in. zapis Array(...) i pytania z banku o tworzenie tablic.

Tworzenie siatki 3×3 i mapowanie klik→indeks wraca za to w części praktycznej egzaminu - i w kolejnych dwóch godzinach tego projektu, gdzie plansza staje się w pełni grywalną grą.

Ćwiczenie przy komputerze · 30 minut

Ćwiczenie: plansza 3×3 i tablica stanu

  1. Utwórz nowy plik tic-tac-toe.html: kontener <div id="board"> z dziewięcioma pustymi przyciskami <button type="button" class="cell"></button> w środku, w <style> ustaw #board { display: grid; grid-template-columns: repeat(3, 100px); gap: 4px; }.
  2. Utwórz plik tic-tac-toe.js i podepnij go na końcu <body> przez <script src="tic-tac-toe.js"></script>.
  3. W tic-tac-toe.js zapisz let board = Array(9).fill(""); - tablicę dziewięciu pustych pól.
  4. Pętlą for przejdź po document.getElementsByClassName("cell") i każdemu przyciskowi ustaw setAttribute("data-index", i) z jego numerem 0-8.
  5. Sprawdź w przeglądarce: otwórz tic-tac-toe.html - plansza ma wyglądać jak siatka 3×3. W konsoli (F12) sprawdź, że każdy przycisk ma atrybut data-index.
  6. Dla chętnych: zapisz zmiany w swoim repozytorium - commit „Buduje plansze 3x3 kolko i krzyzyk”.
Cały plik: tic-tac-toe.html i tic-tac-toe.js
<!-- tic-tac-toe.html -->
<!DOCTYPE html><html lang="pl"><head>
<meta charset="utf-8"><title>Kółko i krzyżyk</title>
<style>#board{display:grid;grid-template-columns:repeat(3,100px);gap:4px}
#board button{height:100px;font-size:2rem}</style>
</head><body>
<div id="board">
<button type="button" class="cell"></button> <button type="button" class="cell"></button> <button type="button" class="cell"></button>
<button type="button" class="cell"></button> <button type="button" class="cell"></button> <button type="button" class="cell"></button>
<button type="button" class="cell"></button> <button type="button" class="cell"></button> <button type="button" class="cell"></button>
</div>
<script src="tic-tac-toe.js"></script></body></html>
// tic-tac-toe.js
let board = Array(9).fill("");

const cells = document.getElementsByClassName("cell");
for (let i = 0; i < cells.length; i++) {
  cells[i].setAttribute("data-index", i);
}
Na koniec

Sprawdź się

  1. Ile elementów ma tablica board na starcie gry?
  2. Jaka wartość znajduje się na starcie w każdym elemencie tablicy board?
  3. Do czego służy atrybut data-index na każdym przycisku planszy?

To tyle na dziś - kolejny temat: kliknięcie pola zapisuje ruch.

Poza szkołą

A jak to wygląda w produkcji?

Na lekcjiW produkcjiStatus
display: grid ze stałą liczbą kolumn (3)CSS Grid ma ok. 97% globalnego wsparcia przeglądarek (caniuse.com, sprawdzone 05.09.2026); używany też do układów responsywnych (auto-fit, minmax), nie tylko stałej siatkinadal w użyciu
9 przycisków wpisanych ręcznie w HTMLSiatka renderowana pętlą z danych (np. array.map() w React, v-for w Vue) zamiast ręcznego wpisywania każdego elementuzastępowane
Stan gry w zwykłej zmiennej let boardStan aplikacji w bibliotekach do zarządzania stanem (Redux, Pinia) albo w stanie komponentu (useState) - ten sam pomysł: dane osobno, widok tylko je pokazujenadal w użyciu (inna forma)
wsparcie CSS Grid - caniuse.com/css-grid