Przejdź do głównej treści
INF.03-07-26.06-SGCzerwiec 2026 · 39 kroków · ok. 66 min · 34 kryteria z klucza

Rozwiązanie krok po kroku: Plansza kółko i krzyżyk (Nowoczesny kod (grid, data-*))

To drugi sposób rozwiązania tego samego arkusza. Wynik jest ten sam - baza gryTowarzyskie z czterema zapytaniami i strona gra.html z planszą 3 × 3, na której kółko i krzyżyk grają na zmianę - i tak samo spełnia każde kryterium klucza. Inna jest droga:

  • siatka CSS: trzy sekcje w grid-template-columns: 20% 60% 20% zamiast display: flex z szerokościami bloków,
  • stan gry w jednym miejscu: skrypt zapisuje, kto gra, w atrybucie data-player bloku głównego, a to, która sekcja jest widoczna, wynika z reguł CSS - skrypt nie ustawia stylów,
  • skrypt w osobnym pliku gra.js z atrybutem defer: querySelectorAll i addEventListener zamiast dziewięciu atrybutów onclick, zajęte pole kończy funkcję od razu (return), nazwa obrazu powstaje z gracza, a tekst alternatywny mówi, co stoi w polu.

Na końcu krótkie porównanie z wersją podstawową (zakładka obok). Baza i obrazy pochodzą z prawdziwego archiwum pliki8, zapytania zostały wykonane na tej bazie w MariaDB, a plansza sprawdzona w prawdziwej przeglądarce: przebieg z ilustracji 4 i klik w zajęte pole. Plansza w podglądzie działa - od kroków ze skryptem można w nią klikać.

Jak liczą się punkty. Klucz ma 34 kryteria (R.1.1 - R.5.7), każde za 1 punkt. Próg zdania to 75%, czyli 26 punktów. Przy każdym kroku jest napisane, które kryteria spełnia.

  1. Etap 1: Baza danych

    Kroki 1-7 · po tym etapie masz 6 z 34 kryteriów (pkt)

    Krok 1: Baza danych gryTowarzyskie

    ok. 2 min
    Polecenie z arkusza

    Utwórz bazę danych o nazwie gryTowarzyskie, z zestawem polskich znaków (np. utf8_polish_ci).

    Archiwum pliki8.7z rozpakuj hasłem KoLko+KrzyZyk (wielkość liter ma znaczenie). W phpMyAdmin Nowa → gryTowarzyskie, porównywanie utf8_polish_ci:

    CREATE DATABASE gryTowarzyskie CHARACTER SET utf8 COLLATE utf8_polish_ci;
    

    MariaDB na Windows pokaże nazwę małymi literami (grytowarzyskie) - to ustawienie serwera, nie błąd.

  2. Krok 2: Import tabeli z pliku

    ok. 2 min
    Polecenie z arkusza

    Do utworzonej bazy zaimportuj tabelę z pliku gryTowarzyskie.sql.

    Import → plik z archiwum (w archiwum nazwa jest małymi literami: grytowarzyskie.sql). Jedna tabela z 12 grami.

  3. Krok 3: Zrzut ekranu import.png

    Kryteria:

    R.1.1 Wykonany import tabel do bazy danych gryTowarzyskie - plik import.png

    ok. 2 min
    Polecenie z arkusza

    Wykonaj zrzut ekranu po imporcie. Zapisz zrzut w formacie PNG pod nazwą import. Nie kadruj zrzutu. Powinien on obejmować cały ekran monitora, z widocznym paskiem zadań. Na zrzucie powinny być widoczne elementy wskazujące na poprawnie wykonany import tabel.

    Cały ekran z paskiem zadań, zapis jako import.png.

    Typowe błędy

    Wykadrowany zrzut nie jest oceniany.

  4. Krok 4: Zapytanie 1: gry dla więcej niż 4 graczy

    Kryteria: ,

    R.1.2 W pliku kwerendy.txt zapisane co najmniej jedno zapytanie SQL, wynikające z treści zadania

    R.1.3 Wykonane zapytanie 1 wybierające jedynie nazwy i potrzebne materiały do gier przeznaczonych dla więcej niż 4 graczy. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT nazwa, potrzebne FROM grytowarzyskie WHERE liczbaGraczy > 4; oraz na zrzucie są dokładnie 2 rekordy z nazwami: Państwa - miasta i Kalambury

    ok. 2 min
    Polecenie z arkusza

    Zapytanie 1: wybierające jedynie nazwy i potrzebne materiały do gier przeznaczonych dla więcej niż 4 graczy.

    „Więcej niż 4” to ostro > 4. Każda klauzula w osobnej linii. Wynik: Państwa - miasta i Kalambury. Zapytanie do kwerendy.txt, zrzut kw1.png.

    Typowe błędy

    >= 4 dokłada trzy gry dla czterech osób.

    kwerendy.txt Tekst nowy plik
    -- Zapytanie 1
    SELECT nazwa, potrzebne
    FROM grytowarzyskie
    WHERE liczbaGraczy > 4;
    Podgląd strony po tym kroku
    Podgląd strony po kroku 4
  5. Krok 5: Zapytanie 2: średni czas gier dla dwóch osób

    Kryteria:

    R.1.4 Wykonane zapytanie 2 liczące średnią arytmetyczną czasu trwania gier, które są przeznaczone jedynie dla dwóch graczy, nazwa kolumny (alias) „średnia w minutach”. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT AVG(czasRozgrywki) AS "średnia w minutach" FROM grytowarzyskie WHERE liczbaGraczy = 2; oraz na zrzucie jest widoczna wartość 12.7500 z dowolnym zaokrągleniem

    ok. 2 min
    Polecenie z arkusza

    Zapytanie 2: liczące średnią arytmetyczną czasu trwania gier, które są przeznaczone jedynie dla dwóch graczy, nazwa kolumny (alias) „średnia w minutach”.

    AVG(czasRozgrywki) z aliasem w odwrotnych apostrofach - to w MySQL i MariaDB właściwy znak dla nazw (kolumn, tabel, aliasów); cudzysłów "..." też tu zadziała, ale w trybie ANSI oznacza co innego niż napis w apostrofach, a odwrotne apostrofy zawsze znaczą nazwę. Spacje w aliasie wymagają jednego z tych zapisów. Wynik: (10 + 1 + 20 + 20) / 4 = 12.7500. Zrzut kw2.png.

    Typowe błędy

    Alias ze spacją bez cudzysłowu ani odwrotnych apostrofów kończy się błędem składni.

    kwerendy.txt Tekst zmienione: 5 linii
    -- Zapytanie 1
    SELECT nazwa, potrzebne
    FROM grytowarzyskie
    WHERE liczbaGraczy > 4;
    
    -- Zapytanie 2
    SELECT AVG(czasRozgrywki) AS `średnia w minutach`
    FROM grytowarzyskie
    WHERE liczbaGraczy = 2;
    Podgląd strony po tym kroku
    Podgląd strony po kroku 5
  6. Krok 6: Zapytanie 3: gry o najdłuższym czasie rozgrywki

    Kryteria:

    R.1.5 Wykonane zapytanie 3 wybierające jedynie nazwy gier o najdłuższym czasie rozgrywki. Należy posłużyć się kwerendą zagnieżdżoną. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT nazwa FROM grytowarzyskie WHERE czasRozgrywki = (SELECT MAX(czasRozgrywki) FROM grytowarzyskie); (sortowanie i LIMIT 1 jest błędem) oraz na zrzucie są dokładnie 2 rekordy: Państwa - miasta i Kalambury

    ok. 3 min
    Polecenie z arkusza

    Zapytanie 3: wybierające jedynie nazwy gier o najdłuższym czasie rozgrywki. Jeśli kilka gier ma ten sam, najdłuższy czas rozgrywki to wszystkie ich nazwy powinny być wybrane. Należy posłużyć się kwerendą zagnieżdżoną.

    Zapytanie wewnętrzne we wcięciu, w osobnych liniach - od razu widać, że zwraca jedną liczbę (najdłuższy czas, 30 minut), a zewnętrzne wybiera wszystkie gry z tym czasem. Wynik: Państwa - miasta i Kalambury. Zrzut kw3.png.

    Typowe błędy

    ORDER BY czasRozgrywki DESC LIMIT 1 zwraca jedną grę - klucz wprost uznaje to za błąd.

    kwerendy.txt Tekst zmienione: 8 linii
    -- Zapytanie 1
    SELECT nazwa, potrzebne
    FROM grytowarzyskie
    WHERE liczbaGraczy > 4;
    
    -- Zapytanie 2
    SELECT AVG(czasRozgrywki) AS `średnia w minutach`
    FROM grytowarzyskie
    WHERE liczbaGraczy = 2;
    
    -- Zapytanie 3
    SELECT nazwa
    FROM grytowarzyskie
    WHERE czasRozgrywki = (
        SELECT MAX(czasRozgrywki)
        FROM grytowarzyskie
    );
    Podgląd strony po tym kroku
    Podgląd strony po kroku 6
  7. Krok 7: Zapytanie 4: gry karciane dla mniej niż 4 graczy

    Kryteria:

    R.1.6 Wykonane zapytanie 4 wybierające jedynie nazwy gier karcianych (pole potrzebne zawiera cząstkę „karty”) przeznaczonych dla mniej niż 4 graczy. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT nazwa FROM grytowarzyskie WHERE potrzebne LIKE "%karty%" AND liczbaGraczy < 4; lub "karty%" oraz na zrzucie są dokładnie 3 rekordy: Piotruś Pan, Pasjans, Tysiąc

    ok. 2 min
    Polecenie z arkusza

    Zapytanie 4: wybierające jedynie nazwy gier karcianych (pole potrzebne zawiera cząstkę „karty”) przeznaczonych dla mniej niż 4 graczy.

    LIKE '%karty%' - % z obu stron szuka cząstki w dowolnym miejscu; porównywanie _ci nie rozróżnia wielkości liter, więc znajduje też „Karty”. Wynik: Piotruś Pan, Pasjans, Tysiąc. Zrzut kw4.png.

    kwerendy.txt Tekst zmienione: 6 linii
    -- Zapytanie 1
    SELECT nazwa, potrzebne
    FROM grytowarzyskie
    WHERE liczbaGraczy > 4;
    
    -- Zapytanie 2
    SELECT AVG(czasRozgrywki) AS `średnia w minutach`
    FROM grytowarzyskie
    WHERE liczbaGraczy = 2;
    
    -- Zapytanie 3
    SELECT nazwa
    FROM grytowarzyskie
    WHERE czasRozgrywki = (
        SELECT MAX(czasRozgrywki)
        FROM grytowarzyskie
    );
    
    -- Zapytanie 4
    SELECT nazwa
    FROM grytowarzyskie
    WHERE potrzebne LIKE '%karty%'
      AND liczbaGraczy < 4;
    Podgląd strony po tym kroku
    Podgląd strony po kroku 7
  8. Etap 2: Strona HTML

    Kroki 8-20 · po tym etapie masz 15 z 34 kryteriów (pkt)

    Krok 8: Plik gra.html w HTML5

    ok. 1 min
    Polecenie z arkusza

    Nazwa pliku gra.html. Zapisana w języku HTML5.

    <!DOCTYPE html> i szkielet. Plik gra.html w folderze zdającego, obok trzech obrazów z archiwum.

    gra.html HTML nowy plik
    <!DOCTYPE html>
    <html>
    <head>
    </head>
    <body>
    </body>
    </html>
    Podgląd strony po tym kroku (gra.html)
  9. Krok 9: Język strony

    Kryteria:

    R.2.1 W pliku gra.html znajduje się deklaracja HTML5 <!DOCTYPE HTML> i deklaracja języka zawartości: polski np. <html lang="pl">

    ok. 1 min
    Polecenie z arkusza

    Zadeklarowany polski język zawartości witryny.

    lang="pl" w <html>.

    gra.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
    </head>
    <body>
    </body>
    </html>
    Podgląd strony po tym kroku (gra.html)
  10. Krok 10: Kodowanie polskich znaków

    ok. 1 min
    Polecenie z arkusza

    Jawnie zastosowany właściwy standard kodowania polskich znaków.

    <meta charset="UTF-8"> jako pierwszy element <head>.

    gra.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
    </head>
    <body>
    </body>
    </html>
    Podgląd strony po tym kroku (gra.html)
  11. Krok 11: Tytuł strony

    Kryteria:

    R.2.2 W sekcji head znajduje się jawnie podany standard kodowania polskich znaków i tytuł strony "Gra"

    ok. 1 min
    Polecenie z arkusza

    Tytuł strony „Gra”.

    <title> w <head>; obok <meta name="viewport"> dla telefonów - arkusz tego nie wymaga.

    gra.html HTML zmienione: 2 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Gra</title>
    </head>
    <body>
    </body>
    </html>
    Podgląd strony po tym kroku (gra.html)
  12. Krok 12: Podpięcie arkusza stylów

    Kryteria:

    R.3.2 Strona zawiera działające połączenie z zewnętrznym arkuszem stylów o nazwie styl.css formatowanie CSS pochodzi jedynie z tego arkusza

    ok. 1 min
    Polecenie z arkusza

    Arkusz stylów w pliku o nazwie styl.css prawidłowo połączony z kodem strony.

    <link rel="stylesheet" href="styl.css">. W tej wersji także zmiany widoczności sekcji opisuje CSS - skrypt nie ustawia żadnego stylu.

    gra.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Gra</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
    </body>
    </html>
    Podgląd strony po tym kroku (gra.html)
  13. Krok 13: Bloki: nagłówek, blok główny z trzema sekcjami, stopka

    Kryteria:

    R.2.3 W sekcji body zdefiniowany jest podział na bloki za pomocą semantycznych znaczników HTML5: header, main -> section + section + section, footer (dopuszcza się stosowanie bloków pomocniczych)

    ok. 2 min
    Polecenie z arkusza

    Podział strony na bloki: nagłówkowy, główny, stopka. Blok główny zawiera trzy bloki sekcji. Podział zrealizowany za pomocą semantycznych znaczników języka HTML5 tak, aby po uruchomieniu w przeglądarce układ bloków był zgodny z ilustracją 3.

    header, main z trzema section, footer (R.2.3). Identyfikatory po angielsku: left, middle, right.

    gra.html HTML zmienione: 12 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Gra</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
        </header>
        <main>
            <section id="left">
            </section>
            <section id="middle">
            </section>
            <section id="right">
            </section>
        </main>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (gra.html)
  14. Krok 14: Nagłówek strony

    ok. 1 min
    Polecenie z arkusza

    Zawartość bloku nagłówkowego: Nagłówek pierwszego stopnia o treści: „Zagraj w kółko i krzyżyk”.

    <h1> w <header>.

    gra.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Gra</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Zagraj w kółko i krzyżyk</h1>
        </header>
        <main>
            <section id="left">
            </section>
            <section id="middle">
            </section>
            <section id="right">
            </section>
        </main>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (gra.html)
  15. Krok 15: Sekcja lewa: „Gra kółko”

    ok. 1 min
    Polecenie z arkusza

    Zawartość bloku sekcji lewej: Nagłówek drugiego stopnia o treści: „Gra kółko”.

    <h2> w lewej sekcji - widocznej, gdy ruch należy do kółka.

    gra.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Gra</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Zagraj w kółko i krzyżyk</h1>
        </header>
        <main>
            <section id="left">
                <h2>Gra kółko</h2>
            </section>
            <section id="middle">
            </section>
            <section id="right">
            </section>
        </main>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (gra.html)
  16. Krok 16: Tabela 3 × 3

    Kryteria:

    R.2.5 W bloku sekcji środkowej znajduje się tabela o trzech kolumnach i trzech wierszach (znaczniki <table>, <tr>, <td>)

    ok. 2 min
    Polecenie z arkusza

    Zawartość bloku sekcji środkowej: Tabela o trzech wierszach i trzech kolumnach.

    <table> z trzema <tr> po trzy <td> - dziewięć pól planszy (R.2.5).

    gra.html HTML zmienione: 17 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Gra</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Zagraj w kółko i krzyżyk</h1>
        </header>
        <main>
            <section id="left">
                <h2>Gra kółko</h2>
            </section>
            <section id="middle">
                <table>
                    <tr>
                        <td></td>
                        <td></td>
                        <td></td>
                    </tr>
                    <tr>
                        <td></td>
                        <td></td>
                        <td></td>
                    </tr>
                    <tr>
                        <td></td>
                        <td></td>
                        <td></td>
                    </tr>
                </table>
            </section>
            <section id="right">
            </section>
        </main>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (gra.html)
  17. Krok 17: Obraz nic.png w każdej komórce

    Kryteria: ,

    R.2.6 Na stronie znajduje się przynajmniej jeden obraz nic.png

    R.2.7 Wszystkie komórki tabeli są wypełnione obrazami

    ok. 2 min
    Polecenie z arkusza

    Każda komórka tabeli jest wypełniona obrazem nic.png.

    W każdej komórce <img src="nic.png" alt="puste pole"> - bez onclick: obsługę kliknięć przypnie skrypt jednym poleceniem dla wszystkich dziewięciu obrazów.

    Typowe błędy

    Obraz tylko w części komórek kosztuje R.2.7.

    gra.html HTML zmienione: 9 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Gra</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Zagraj w kółko i krzyżyk</h1>
        </header>
        <main>
            <section id="left">
                <h2>Gra kółko</h2>
            </section>
            <section id="middle">
                <table>
                    <tr>
                        <td><img src="nic.png" alt="puste pole"></td>
                        <td><img src="nic.png" alt="puste pole"></td>
                        <td><img src="nic.png" alt="puste pole"></td>
                    </tr>
                    <tr>
                        <td><img src="nic.png" alt="puste pole"></td>
                        <td><img src="nic.png" alt="puste pole"></td>
                        <td><img src="nic.png" alt="puste pole"></td>
                    </tr>
                    <tr>
                        <td><img src="nic.png" alt="puste pole"></td>
                        <td><img src="nic.png" alt="puste pole"></td>
                        <td><img src="nic.png" alt="puste pole"></td>
                    </tr>
                </table>
            </section>
            <section id="right">
            </section>
        </main>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (gra.html)
  18. Krok 18: Sekcja prawa: „Gra krzyżyk”

    ok. 1 min
    Polecenie z arkusza

    Zawartość bloku sekcji prawej: Nagłówek drugiego stopnia o treści: „Gra krzyżyk”.

    Drugi <h2>, w prawej sekcji - CSS ją ukryje na start.

    gra.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Gra</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Zagraj w kółko i krzyżyk</h1>
        </header>
        <main>
            <section id="left">
                <h2>Gra kółko</h2>
            </section>
            <section id="middle">
                <table>
                    <tr>
                        <td><img src="nic.png" alt="puste pole"></td>
                        <td><img src="nic.png" alt="puste pole"></td>
                        <td><img src="nic.png" alt="puste pole"></td>
                    </tr>
                    <tr>
                        <td><img src="nic.png" alt="puste pole"></td>
                        <td><img src="nic.png" alt="puste pole"></td>
                        <td><img src="nic.png" alt="puste pole"></td>
                    </tr>
                    <tr>
                        <td><img src="nic.png" alt="puste pole"></td>
                        <td><img src="nic.png" alt="puste pole"></td>
                        <td><img src="nic.png" alt="puste pole"></td>
                    </tr>
                </table>
            </section>
            <section id="right">
                <h2>Gra krzyżyk</h2>
            </section>
        </main>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (gra.html)
  19. Krok 19: Odnośnik „Zagraj w statki” w nowym oknie

    Kryteria:

    R.3.3 Kliknięcie odnośnika „Zagraj w statki” powoduje otwarcie strony https://pl.battleship-game.org/ w nowym oknie przeglądarki

    ok. 1 min
    Polecenie z arkusza

    Zawartość bloku stopki: Odnośnik do strony https://pl.battleship-game.org/ o treści „Zagraj w statki”. Odnośnik otwiera się w nowym oknie.

    target="_blank" otwiera stronę w nowej karcie. rel="noopener" odcina nowej karcie dostęp do tej strony przez window.opener - zwyczaj przy odnośnikach do obcych serwisów (współczesne przeglądarki robią to już same).

    gra.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Gra</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Zagraj w kółko i krzyżyk</h1>
        </header>
        <main>
            <section id="left">
                <h2>Gra kółko</h2>
            </section>
            <section id="middle">
                <table>
                    <tr>
                        <td><img src="nic.png" alt="puste pole"></td>
                        <td><img src="nic.png" alt="puste pole"></td>
                        <td><img src="nic.png" alt="puste pole"></td>
                    </tr>
                    <tr>
                        <td><img src="nic.png" alt="puste pole"></td>
                        <td><img src="nic.png" alt="puste pole"></td>
                        <td><img src="nic.png" alt="puste pole"></td>
                    </tr>
                    <tr>
                        <td><img src="nic.png" alt="puste pole"></td>
                        <td><img src="nic.png" alt="puste pole"></td>
                        <td><img src="nic.png" alt="puste pole"></td>
                    </tr>
                </table>
            </section>
            <section id="right">
                <h2>Gra krzyżyk</h2>
            </section>
        </main>
        <footer>
            <a href="https://pl.battleship-game.org/" target="_blank" rel="noopener">Zagraj w statki</a>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (gra.html)
  20. Krok 20: Stopka: autor gry

    Kryteria:

    R.2.4 W bloku nagłówkowym znajduje się <h1>: "Zagraj w kółko i krzyżyk", w bloku sekcji lewej <h2>: "Gra kółko", prawej <h2>: "Gra krzyżyk" (może być ukryty ), w stopce <p> z numerem zdającego

    ok. 1 min
    Polecenie z arkusza

    Paragraf o treści „Grę opracował: ”, dalej wstawiony numer zdającego.

    Na egzaminie wpisujesz swój numer zdającego (PESEL) - tutaj stoi imię i nazwisko autora rozwiązania. Zamyka komplet R.2.4.

    gra.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Gra</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h1>Zagraj w kółko i krzyżyk</h1>
        </header>
        <main>
            <section id="left">
                <h2>Gra kółko</h2>
            </section>
            <section id="middle">
                <table>
                    <tr>
                        <td><img src="nic.png" alt="puste pole"></td>
                        <td><img src="nic.png" alt="puste pole"></td>
                        <td><img src="nic.png" alt="puste pole"></td>
                    </tr>
                    <tr>
                        <td><img src="nic.png" alt="puste pole"></td>
                        <td><img src="nic.png" alt="puste pole"></td>
                        <td><img src="nic.png" alt="puste pole"></td>
                    </tr>
                    <tr>
                        <td><img src="nic.png" alt="puste pole"></td>
                        <td><img src="nic.png" alt="puste pole"></td>
                        <td><img src="nic.png" alt="puste pole"></td>
                    </tr>
                </table>
            </section>
            <section id="right">
                <h2>Gra krzyżyk</h2>
            </section>
        </main>
        <footer>
            <a href="https://pl.battleship-game.org/" target="_blank" rel="noopener">Zagraj w statki</a>
            <p>Grę opracował: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (gra.html)
  21. Etap 3: Styl CSS

    Kroki 21-31 · po tym etapie masz 26 z 34 kryteriów (pkt)

    Krok 21: Zmienna z kolorem i krój czcionki

    Kryteria:

    R.4.1 domyślne formatowanie selektorów (*): krój czcionki "Lucida Console" - jako pierwszy, monospace - jako ostatni

    ok. 2 min
    Polecenie z arkusza

    Domyślnie, dla wszystkich selektorów: krój czcionki Lucida Console, w przypadku braku monospace.

    SeaGreen występuje w arkuszu dwa razy (ramki komórek i tło klikniętej komórki) - trafia do zmiennej CSS --green. Potem * z krojem i rodziną zapasową monospace (R.4.1).

    styl.css CSS nowy plik
    :root {
        --green: SeaGreen;
    }
    
    * {
        font-family: "Lucida Console", monospace;
    }
    Podgląd strony po tym kroku (gra.html)
  22. Krok 22: Ciało strony: tło i wyśrodkowanie

    Kryteria:

    R.4.5 wyrównanie tekstu: ciało strony - do środka

    ok. 1 min
    Polecenie z arkusza

    Dla ciała strony: kolor tła HoneyDew, tekst wyrównany do środka.

    text-align: center dziedziczą wszystkie bloki (R.4.5).

    styl.css CSS zmienione: 5 linii
    :root {
        --green: SeaGreen;
    }
    
    * {
        font-family: "Lucida Console", monospace;
    }
    
    body {
        background-color: HoneyDew;
        text-align: center;
    }
    Podgląd strony po tym kroku (gra.html)
  23. Krok 23: Nagłówek i stopka: marginesy wewnętrzne

    ok. 1 min
    Polecenie z arkusza

    Dla bloków nagłówkowego i stopki: marginesy wewnętrzne 20 px.

    Jedna reguła dla dwóch selektorów.

    styl.css CSS zmienione: 5 linii
    :root {
        --green: SeaGreen;
    }
    
    * {
        font-family: "Lucida Console", monospace;
    }
    
    body {
        background-color: HoneyDew;
        text-align: center;
    }
    
    header,
    footer {
        padding: 20px;
    }
    Podgląd strony po tym kroku (gra.html)
  24. Krok 24: Siatka trzech sekcji zgodna z ilustracją 3

    Kryteria:

    R.3.1 Układ bloków po uruchomieniu strony w przeglądarce jest zgodny z ilustracją 3 w arkuszu egzaminacyjnym (prawidłowo zastosowane właściwości CSS decydujące o układzie bloków na stronie, np. float i clear albo display flex albo grid albo position; żaden blok nie zachodzi na inne bloki - sprawdzić w inspektorze)

    ok. 2 min
    Polecenie z arkusza

    Podział zrealizowany za pomocą semantycznych znaczników języka HTML5 tak, aby po uruchomieniu w przeglądarce układ bloków był zgodny z ilustracją 3.

    Blok główny to siatka z kolumnami 20%, 60% i 20% - szerokości sekcji z arkusza w jednym miejscu (klucz R.4.3 dopuszcza grid-template-columns). Sekcje trafiają do kolumn w kolejności z kodu. align-items: start przyciąga je do góry: bez tego siatka rozciąga każdą sekcję na wysokość najwyższej (tabeli), a na ilustracji 2 zielony blok „Gra kółko” jest niski. Stopka stoi pod siatką bez clear (R.3.1).

    styl.css CSS zmienione: 6 linii
    :root {
        --green: SeaGreen;
    }
    
    * {
        font-family: "Lucida Console", monospace;
    }
    
    body {
        background-color: HoneyDew;
        text-align: center;
    }
    
    header,
    footer {
        padding: 20px;
    }
    
    main {
        display: grid;
        grid-template-columns: 20% 60% 20%;
        align-items: start;
    }
    Podgląd strony po tym kroku (gra.html)
  25. Krok 25: Sekcje boczne: tło, marginesy, zaokrąglenie

    Kryteria:

    R.4.2 kolor tła: ciało strony - HoneyDew, blok sekcji lewej i prawej - PaleGreen

    ok. 2 min
    Polecenie z arkusza

    Dla bloków sekcji lewej i prawej: kolor tła PaleGreen, szerokość 20%, marginesy wewnętrzne górny i dolny 80 px, boczne 0, zaokrąglenie rogów 40 px.

    Szerokość 20% dają kolumny siatki. padding: 80px 0 - góra i dół 80 px, boki 0. Z tłem HoneyDew ciała to R.4.2.

    styl.css CSS zmienione: 7 linii
    :root {
        --green: SeaGreen;
    }
    
    * {
        font-family: "Lucida Console", monospace;
    }
    
    body {
        background-color: HoneyDew;
        text-align: center;
    }
    
    header,
    footer {
        padding: 20px;
    }
    
    main {
        display: grid;
        grid-template-columns: 20% 60% 20%;
        align-items: start;
    }
    
    #left,
    #right {
        background-color: PaleGreen;
        padding: 80px 0;
        border-radius: 40px;
    }
    Podgląd strony po tym kroku (gra.html)
  26. Krok 26: Sekcja prawa ukryta

    Kryteria:

    R.4.8 blok sekcji prawej jest niewidoczny (visibility: hidden lub opacity: 0) (display: none jest błędem)

    ok. 1 min
    Polecenie z arkusza

    Dodatkowo dla bloku sekcji prawej: blok jest niewidoczny (ukryty).

    visibility: hidden - blok jest niewidoczny, ale zajmuje miejsce, więc plansza nie skacze przy zmianie gracza (R.4.8).

    Typowe błędy

    display: none usuwa blok z układu - klucz wprost uznaje to za błąd.

    styl.css CSS zmienione: 4 linie
    :root {
        --green: SeaGreen;
    }
    
    * {
        font-family: "Lucida Console", monospace;
    }
    
    body {
        background-color: HoneyDew;
        text-align: center;
    }
    
    header,
    footer {
        padding: 20px;
    }
    
    main {
        display: grid;
        grid-template-columns: 20% 60% 20%;
        align-items: start;
    }
    
    #left,
    #right {
        background-color: PaleGreen;
        padding: 80px 0;
        border-radius: 40px;
    }
    
    #right {
        visibility: hidden;
    }
    Podgląd strony po tym kroku (gra.html)
  27. Krok 27: Sekcja środkowa: cień

    Kryteria:

    R.4.4 styl bloków sekcji lewej i prawej: zaokrąglenie rogów (border-radius) - 40px styl bloku sekcji środkowej: cień bloku box-shadow: 0 0 10px DarkGreen;

    ok. 1 min
    Polecenie z arkusza

    Dla bloku sekcji środkowej: szerokość 60%, cień bloku bez przesunięcia o rozmyciu 10 px i kolorze DarkGreen.

    Szerokość 60% to środkowa kolumna siatki. box-shadow: 0 0 10px DarkGreen - przesunięcia 0 i 0, rozmycie 10 px (R.4.4 razem z zaokrągleniem sekcji bocznych).

    styl.css CSS zmienione: 4 linie
    :root {
        --green: SeaGreen;
    }
    
    * {
        font-family: "Lucida Console", monospace;
    }
    
    body {
        background-color: HoneyDew;
        text-align: center;
    }
    
    header,
    footer {
        padding: 20px;
    }
    
    main {
        display: grid;
        grid-template-columns: 20% 60% 20%;
        align-items: start;
    }
    
    #left,
    #right {
        background-color: PaleGreen;
        padding: 80px 0;
        border-radius: 40px;
    }
    
    #right {
        visibility: hidden;
    }
    
    #middle {
        box-shadow: 0 0 10px DarkGreen;
    }
    Podgląd strony po tym kroku (gra.html)
  28. Krok 28: Obraz: szerokość, marginesy, kursor

    Kryteria:

    R.4.7 styl obrazu: cursor: pointer;

    ok. 1 min
    Polecenie z arkusza

    Dla selektora obrazu: szerokość 80%, marginesy zewnętrzne 10 px, typ kursora pointer.

    Selektor znacznika img, jak każe uwaga arkusza. cursor: pointer - rączka nad polem (R.4.7).

    styl.css CSS zmienione: 6 linii
    :root {
        --green: SeaGreen;
    }
    
    * {
        font-family: "Lucida Console", monospace;
    }
    
    body {
        background-color: HoneyDew;
        text-align: center;
    }
    
    header,
    footer {
        padding: 20px;
    }
    
    main {
        display: grid;
        grid-template-columns: 20% 60% 20%;
        align-items: start;
    }
    
    #left,
    #right {
        background-color: PaleGreen;
        padding: 80px 0;
        border-radius: 40px;
    }
    
    #right {
        visibility: hidden;
    }
    
    #middle {
        box-shadow: 0 0 10px DarkGreen;
    }
    
    img {
        width: 80%;
        margin: 10px;
        cursor: pointer;
    }
    Podgląd strony po tym kroku (gra.html)
  29. Krok 29: Tabela: szerokość, marginesy, połączone obramowania

    Kryteria: ,

    R.4.3 szerokość: bloki sekcji lewej i prawej - 20%, środkowej - 60% (width lub grid-template- columns lub flex ), selektor img - 80%, selektor table - 90%

    R.4.6 marginesy wewnętrzne (padding ): blok nagłówkowy, stopka - 20px, bloki sekcji lewej i prawej - górny i dolny - 80px, boczne - 0 lub nieustawione marginesy zewnętrzne (margin ): obraz i tabela - 10px

    ok. 1 min
    Polecenie z arkusza

    Dla selektora tabeli: szerokość 90%, marginesy zewnętrzne 10 px, obramowanie tabeli i komórek połączone.

    border-collapse: collapse łączy obramowania komórek w jedną linię. Domyka kryteria szerokości (R.4.3) i marginesów (R.4.6).

    styl.css CSS zmienione: 6 linii
    :root {
        --green: SeaGreen;
    }
    
    * {
        font-family: "Lucida Console", monospace;
    }
    
    body {
        background-color: HoneyDew;
        text-align: center;
    }
    
    header,
    footer {
        padding: 20px;
    }
    
    main {
        display: grid;
        grid-template-columns: 20% 60% 20%;
        align-items: start;
    }
    
    #left,
    #right {
        background-color: PaleGreen;
        padding: 80px 0;
        border-radius: 40px;
    }
    
    #right {
        visibility: hidden;
    }
    
    #middle {
        box-shadow: 0 0 10px DarkGreen;
    }
    
    img {
        width: 80%;
        margin: 10px;
        cursor: pointer;
    }
    
    table {
        width: 90%;
        margin: 10px;
        border-collapse: collapse;
    }
    Podgląd strony po tym kroku (gra.html)
  30. Krok 30: Komórka: obramowanie

    Kryteria:

    R.4.9 obramowanie: selektor td - 3px SeaGreen dowolna, pojedyncza linia ciągła; tabela - border-collapse: collapse;

    ok. 1 min
    Polecenie z arkusza

    Dla selektora komórki tabeli: obramowanie linią ciągłą o szerokości 3 px i kolorze SeaGreen.

    Skrót border: grubość, solid, kolor ze zmiennej. Z border-collapse to R.4.9.

    styl.css CSS zmienione: 4 linie
    :root {
        --green: SeaGreen;
    }
    
    * {
        font-family: "Lucida Console", monospace;
    }
    
    body {
        background-color: HoneyDew;
        text-align: center;
    }
    
    header,
    footer {
        padding: 20px;
    }
    
    main {
        display: grid;
        grid-template-columns: 20% 60% 20%;
        align-items: start;
    }
    
    #left,
    #right {
        background-color: PaleGreen;
        padding: 80px 0;
        border-radius: 40px;
    }
    
    #right {
        visibility: hidden;
    }
    
    #middle {
        box-shadow: 0 0 10px DarkGreen;
    }
    
    img {
        width: 80%;
        margin: 10px;
        cursor: pointer;
    }
    
    table {
        width: 90%;
        margin: 10px;
        border-collapse: collapse;
    }
    
    td {
        border: 3px solid var(--green);
    }
    Podgląd strony po tym kroku (gra.html)
  31. Krok 31: Komórka podświetlana przy kliknięciu

    Kryteria:

    R.4.10 gdy komórka tabeli zostanie kliknięta, kolor tła zmienia się na SeaGreen (np. :active lub za pomocą obsługi kliknięcia w JavaScript)

    ok. 1 min
    Polecenie z arkusza

    Gdy komórka tabeli zostanie kliknięta, kolor tła zmienia się na SeaGreen.

    :active działa, dopóki przycisk myszy jest wciśnięty; przezroczysty obraz przepuszcza zielone tło (R.4.10).

    Typowe błędy

    td:hover reaguje na samo najechanie, a arkusz mówi o kliknięciu.

    styl.css CSS zmienione: 4 linie
    :root {
        --green: SeaGreen;
    }
    
    * {
        font-family: "Lucida Console", monospace;
    }
    
    body {
        background-color: HoneyDew;
        text-align: center;
    }
    
    header,
    footer {
        padding: 20px;
    }
    
    main {
        display: grid;
        grid-template-columns: 20% 60% 20%;
        align-items: start;
    }
    
    #left,
    #right {
        background-color: PaleGreen;
        padding: 80px 0;
        border-radius: 40px;
    }
    
    #right {
        visibility: hidden;
    }
    
    #middle {
        box-shadow: 0 0 10px DarkGreen;
    }
    
    img {
        width: 80%;
        margin: 10px;
        cursor: pointer;
    }
    
    table {
        width: 90%;
        margin: 10px;
        border-collapse: collapse;
    }
    
    td {
        border: 3px solid var(--green);
    }
    
    td:active {
        background-color: var(--green);
    }
    Podgląd strony po tym kroku (gra.html)
  32. Etap 4: JavaScript

    Kroki 32-37 · po tym etapie masz 34 z 34 kryteriów (pkt)

    Krok 32: Plik gra.js: kliknięcie każdego obrazu uruchamia funkcję

    Kryteria: ,

    R.3.4 Dla przynajmniej jednego obrazu lub komórki tabeli zostało zdefiniowane zdarzenie kliknięcia, które uruchamia funkcję skryptu

    R.5.1 Skrypt w języku JavaScript zawiera przynajmniej jedną poprawną składniowo instrukcję wynikającą z treści zadania

    ok. 3 min
    Polecenie z arkusza

    Dla każdego obrazu, gdy zostanie kliknięty, uruchamia się skrypt.

    Skrypt w osobnym pliku gra.js, podpięty w <head> z defer - wykona się po wczytaniu całego HTML-u, więc elementy <img> są już w drzewie dokumentu (same pliki obrazów mogą się jeszcze pobierać).

    • document.querySelector('main') - blok główny; w nim skrypt będzie zapisywał, kto gra,
    • document.querySelectorAll('td img') - wszystkie dziewięć obrazów z komórek,
    • fields.forEach(...) - dla każdego obrazu addEventListener('click', ...); funkcja strzałkowa przekazuje do makeMove właśnie kliknięty obraz.

    Funkcja makeMove(image) na razie jest pusta. Obsługę kliknięcia ma każdy obraz (R.3.4), a HTML nie ma ani jednego onclick.

    Typowe błędy

    field.addEventListener('click', makeMove(field)) bez funkcji strzałkowej wywołuje makeMove od razu przy wczytaniu strony, zamiast przy kliknięciu.

    gra.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Gra</title>
        <link rel="stylesheet" href="styl.css">
        <script src="gra.js" defer></script>
    </head>
    <body>
        <header>
            <h1>Zagraj w kółko i krzyżyk</h1>
        </header>
        <main>
            <section id="left">
                <h2>Gra kółko</h2>
            </section>
            <section id="middle">
                <table>
                    <tr>
                        <td><img src="nic.png" alt="puste pole"></td>
                        <td><img src="nic.png" alt="puste pole"></td>
                        <td><img src="nic.png" alt="puste pole"></td>
                    </tr>
                    <tr>
                        <td><img src="nic.png" alt="puste pole"></td>
                        <td><img src="nic.png" alt="puste pole"></td>
                        <td><img src="nic.png" alt="puste pole"></td>
                    </tr>
                    <tr>
                        <td><img src="nic.png" alt="puste pole"></td>
                        <td><img src="nic.png" alt="puste pole"></td>
                        <td><img src="nic.png" alt="puste pole"></td>
                    </tr>
                </table>
            </section>
            <section id="right">
                <h2>Gra krzyżyk</h2>
            </section>
        </main>
        <footer>
            <a href="https://pl.battleship-game.org/" target="_blank" rel="noopener">Zagraj w statki</a>
            <p>Grę opracował: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    gra.js JavaScript nowy plik
    const board = document.querySelector('main');
    const fields = document.querySelectorAll('td img');
    
    function makeMove(image) {
    }
    
    fields.forEach((field) => {
        field.addEventListener('click', () => makeMove(field));
    });
    Podgląd strony po tym kroku (gra.html)
  33. Krok 33: Zmienna z aktualnym graczem

    Kryteria: ,

    R.5.2 Zastosowana przynajmniej jedna zmienna lub funkcja oraz nazewnictwo jest w języku polskim lub angielskim i odzwierciedla cel zastosowania

    R.5.3 Gra rozpoczyna się od kółka (np. ustawiona wartość początkowa zmiennej)

    ok. 1 min
    Polecenie z arkusza

    Stan początkowy: aktualny gracz to kółko.

    let currentPlayer = 'o' poza funkcją - pamięta kolejkę między kliknięciami; let, bo wartość będzie się zmieniać. Grę zaczyna kółko (R.5.3), nazwa mówi, co przechowuje (R.5.2).

    Typowe błędy

    Zmienna zadeklarowana wewnątrz funkcji startuje od nowa przy każdym kliknięciu - zawsze grałoby kółko.

    gra.js JavaScript zmienione: 1 linia
    const board = document.querySelector('main');
    const fields = document.querySelectorAll('td img');
    let currentPlayer = 'o';
    
    function makeMove(image) {
    }
    
    fields.forEach((field) => {
        field.addEventListener('click', () => makeMove(field));
    });
    Podgląd strony po tym kroku (gra.html)
  34. Krok 34: Obraz gracza w klikniętym polu

    ok. 2 min
    Polecenie z arkusza

    Gdy gracz kółko kliknie w komórkę tabeli z obrazem nic.png: w komórce jest podmieniany obraz na o.png. Gdy gracz krzyżyk kliknie w komórkę tabeli z obrazem nic.png: w komórce jest podmieniany obraz na x.png

    Nazwa pliku powstaje z gracza: szablon tekstowy `${currentPlayer}.png` daje o.png albo x.png. Jedna linia obsługuje oba przypadki z arkusza („o.png” dla kółka, „x.png” dla krzyżyka) - nie ma dwóch gałęzi, w których można poprawić jedną i zapomnieć o drugiej. Kliknij pole w podglądzie: pojawia się kółko.

    gra.js JavaScript zmienione: 1 linia
    const board = document.querySelector('main');
    const fields = document.querySelectorAll('td img');
    let currentPlayer = 'o';
    
    function makeMove(image) {
        image.src = `${currentPlayer}.png`;
    }
    
    fields.forEach((field) => {
        field.addEventListener('click', () => makeMove(field));
    });
    Podgląd strony po tym kroku (gra.html)
  35. Krok 35: Kolejka przechodzi na drugiego gracza

    Kryteria:

    R.5.4 Uczestnicy grają naprzemiennie: raz kółko, raz krzyżyk (wystarczy np. warunek sprawdzający, kto aktualnie gra, oraz zmiana tej wartości na inną lub przeciwną )

    ok. 2 min
    Polecenie z arkusza

    Aktualny gracz jest zmieniany na krzyżyk. Aktualny gracz jest zmieniany na kółko.

    Operator warunkowy warunek ? a : b: jeśli grało kółko, teraz gra krzyżyk, i odwrotnie - sprawdzenie, kto gra, i zmiana na przeciwnego w jednej linii (R.5.4). Porównanie ścisłe === (bez zamiany typów). Przy okazji tekst alternatywny: czytnik ekranu mówi „kółko” albo „krzyżyk” zamiast „puste pole”.

    gra.js JavaScript zmienione: 2 linie
    const board = document.querySelector('main');
    const fields = document.querySelectorAll('td img');
    let currentPlayer = 'o';
    
    function makeMove(image) {
        image.src = `${currentPlayer}.png`;
        image.alt = currentPlayer === 'o' ? 'kółko' : 'krzyżyk';
        currentPlayer = currentPlayer === 'o' ? 'x' : 'o';
    }
    
    fields.forEach((field) => {
        field.addEventListener('click', () => makeMove(field));
    });
    Podgląd strony po tym kroku (gra.html)
  36. Krok 36: Widoczność sekcji z atrybutu data-player

    Kryteria: ,

    R.5.5 Kiedy ruch należy do kółka, wyświetlony jest blok sekcji lewej, a ukryty prawej. Kiedy ruch należy do krzyżyka wyświetlony jest blok sekcji prawej, a ukryty lewej (dopuszcza się również zastosowanie display= "none")

    R.5.6 Po kliknięciu komórki tabeli lub obrazu nic.png, kiedy ruch należy do kółka, wyświetlany jest tam obraz o.png, a kiedy ruch należy do krzyżyka - obraz x.png

    ok. 4 min
    Polecenie z arkusza

    Blok sekcji lewej staje się ukryty. Blok sekcji prawej staje się widoczny.

    Skrypt nie ustawia stylów - zapisuje tylko stan: board.dataset.player = currentPlayer tworzy w <main> atrybut data-player="x" albo "o" (atrybuty data-* są w HTML5 przeznaczone na dane dla skryptu i stylów). O wyglądzie decydują dwie reguły CSS z selektorem atrybutu: gdy gra krzyżyk, lewa sekcja jest ukryta, a prawa widoczna. Po ruchu krzyżyka (data-player="o") reguły nie pasują i działa styl początkowy: prawa ukryta, lewa widoczna.

    Stan jest w jednym miejscu, a wygląd w styl.css - nie da się ukryć obu sekcji naraz ani pokazać złej. Zagraj w podglądzie cztery ruchy z ilustracji 4 (R.5.5, R.5.6).

    Typowe błędy

    Reguły z data-player muszą stać po regule #right { visibility: hidden; } albo mieć silniejszy selektor - tu mają oba: main[data-player="x"] #right jest bardziej szczegółowy niż samo #right.

    gra.js JavaScript zmienione: 1 linia
    const board = document.querySelector('main');
    const fields = document.querySelectorAll('td img');
    let currentPlayer = 'o';
    
    function makeMove(image) {
        image.src = `${currentPlayer}.png`;
        image.alt = currentPlayer === 'o' ? 'kółko' : 'krzyżyk';
        currentPlayer = currentPlayer === 'o' ? 'x' : 'o';
        board.dataset.player = currentPlayer;
    }
    
    fields.forEach((field) => {
        field.addEventListener('click', () => makeMove(field));
    });
    styl.css CSS zmienione: 8 linii
    :root {
        --green: SeaGreen;
    }
    
    * {
        font-family: "Lucida Console", monospace;
    }
    
    body {
        background-color: HoneyDew;
        text-align: center;
    }
    
    header,
    footer {
        padding: 20px;
    }
    
    main {
        display: grid;
        grid-template-columns: 20% 60% 20%;
        align-items: start;
    }
    
    #left,
    #right {
        background-color: PaleGreen;
        padding: 80px 0;
        border-radius: 40px;
    }
    
    #right {
        visibility: hidden;
    }
    
    #middle {
        box-shadow: 0 0 10px DarkGreen;
    }
    
    img {
        width: 80%;
        margin: 10px;
        cursor: pointer;
    }
    
    table {
        width: 90%;
        margin: 10px;
        border-collapse: collapse;
    }
    
    td {
        border: 3px solid var(--green);
    }
    
    td:active {
        background-color: var(--green);
    }
    
    main[data-player="x"] #left {
        visibility: hidden;
    }
    
    main[data-player="x"] #right {
        visibility: visible;
    }
    Podgląd strony po tym kroku (gra.html)
  37. Krok 37: Zajęte pole: brak akcji

    Kryteria:

    R.5.7 Jeżeli w komórce tabeli znaduje się obraz kółka lub krzyżyka, ponowne kliknięcie w komórkę tabeli lub w obraz nie powoduje zmian obrazu

    ok. 2 min
    Polecenie z arkusza

    Gdy dowolny gracz kliknie komórkę tabeli z obrazem kółka lub krzyżyka – brak akcji.

    Na początku funkcji wczesny powrót: jeśli w polu nie ma już nic.png, return kończy funkcję i nic się nie zmienia (R.5.7). Reszta kodu nie musi stać we wcięciu warunku.

    getAttribute('src') zwraca dokładnie to, co jest zapisane w atrybucie (nic.png), a właściwość image.src - pełny adres (http://.../nic.png), więc porównanie z samą nazwą by się nie udało.

    Typowe błędy

    if (image.src !== 'nic.png') return; kończy funkcję przy każdym kliknięciu - plansza przestaje reagować.

    gra.js JavaScript zmienione: 3 linie
    const board = document.querySelector('main');
    const fields = document.querySelectorAll('td img');
    let currentPlayer = 'o';
    
    function makeMove(image) {
        if (image.getAttribute('src') !== 'nic.png') {
            return;
        }
        image.src = `${currentPlayer}.png`;
        image.alt = currentPlayer === 'o' ? 'kółko' : 'krzyżyk';
        currentPlayer = currentPlayer === 'o' ? 'x' : 'o';
        board.dataset.player = currentPlayer;
    }
    
    fields.forEach((field) => {
        field.addEventListener('click', () => makeMove(field));
    });
    Podgląd strony po tym kroku (gra.html)
  38. Etap 5: Porównanie z wersją podstawową

    Krok 38 · po tym etapie masz 34 z 34 kryteriów (pkt)

    Krok 38: Co jest inaczej i którą wersję wybrać na egzaminie

    ok. 2 min

    Obie wersje dają komplet 34 punktów. Różnice:

    wersja podstawowawersja nowoczesna
    układdisplay: flex + szerokości blokówgrid-template-columns: 20% 60% 20%
    skrypt<script> w HTML, 9 × onclick="makeMove(this)"gra.js z defer, forEach + addEventListener
    gałęzieif dla kółka i else dla krzyżykajedna ścieżka: ${currentPlayer}.png, operator ? :
    widoczność sekcjistyle.visibility ze skryptu, cztery liniedata-player w <main> + dwie reguły CSS
    zajęte polecała treść funkcji we wcięciu ifwczesny return

    Na egzaminie wersja podstawowa trzyma się dosłownie tabeli 1 arkusza (onclick, getElementById, style), więc łatwiej ją sprawdzić krok po kroku. Nowoczesna jest krótsza i odporna na niespójność: kolejka i wygląd nie mogą się rozjechać. Kolejny krok rozbudowy to delegacja zdarzeń - jeden nasłuchiwacz na tabeli zamiast dziewięciu i event.target jako kliknięte pole; na egzaminie bezpieczniej przypiąć zdarzenie bezpośrednio do obrazów, bo tak brzmi R.3.4. Wersja podstawowa pokazuje też, jak dopisać sprawdzanie wygranej.

    Podgląd strony bez zmian - taki jak po kroku 37.

  39. Etap 6: Oddanie pracy

    Krok 39 · po tym etapie masz 34 z 34 kryteriów (pkt)

    Krok 39: Plik przeglądarka.txt i nagranie płyty

    ok. 5 min
    Polecenie z arkusza

    Po zakończeniu pracy utwórz plik tekstowy o nazwie przeglądarka.txt. Zapisz w nim nazwę przeglądarki internetowej, w której weryfikowana była poprawność działania witryny. Umieść go w folderze z numerem zdającego. Nagraj płytę z rezultatami pracy.

    W folderze z numerem zdającego: gra.html, gra.js, styl.css, kwerendy.txt, import.png, kw1.png … kw4.png, nic.png, o.png, x.png, przeglądarka.txt. Bez gra.js plansza nie reaguje na kliknięcia. Płytę sprawdź po nagraniu.

    przeglądarka.txt Tekst nowy plik
    Google Chrome

    Podgląd strony bez zmian - taki jak po kroku 37.

Podgląd

To jedno z możliwych rozwiązań. Egzaminator ocenia spełnienie kryteriów z klucza odpowiedzi, a nie zgodność z tym kodem - inna, poprawna droga też daje punkty.

Autor rozwiązania: . Licencja CC BY-NC 4.0 - kopiowanie i przeróbki do celów niekomercyjnych, z podaniem autora i źródła (link do tej strony) (zasady wykorzystania). Treść arkusza i klucza oceniania pochodzi z CKE.