Pętle
Szybki quiz – przypomnienie poprzedniej lekcji
1. Co zostanie wyświetlone? Dlaczego?
$x = 0;
if ($x = 5) {
echo "pięć";
} else {
echo "inna";
}
2. Co zostanie wyświetlone?
$poziom = 2;
switch ($poziom) {
case 1:
echo "A";
case 2:
echo "B";
case 3:
echo "C";
break;
default:
echo "D";
}
3. Zmienna $ocena zawiera tekst "5". Co wyświetli match, a co wyświetliłby switch z case 5:? Z czego wynika różnica?
$ocena = "5";
echo match ($ocena) {
5 => "bdb",
default => "inna"
};
4. Co stanie się po wykonaniu kodu?
$ranga = 3;
echo match ($ranga) {
1 => "Brąz",
2 => "Srebro"
};
5. Co zostanie wyświetlone w każdej z trzech linii?
$imie = null;
$nick = "";
echo $imie ?? "Gość";
echo $nick ?? "Gość";
echo $nick ?: "Gość";
6. Jaki tytuł otrzyma użytkownik z $xp = 150? Co by się stało, gdyby zamienić kolejność dwóch pierwszych warunków?
$tytul = match (true) {
$xp >= 200 => "Mistrz",
$xp >= 100 => "Wojownik",
default => "Nowicjusz"
};
7. TaskQuest: uzupełnij jedną linię tak, aby $status przyjmował wartość "Aktywny" lub "Nieaktywny" w zależności od $wykonalDzisiajZadanie. Użyj operatora warunkowego.
$status = ______________________________;
Odpowiedzi
pięć. W warunku użyto=(przypisanie) zamiast==. Zmienna dostaje wartość 5, a 5 jest traktowane jakotrue, więc warunek zawsze jest spełniony.BC. Wcase 2brakujebreak, więc wykonanie „przechodzi” docase 3(fall-through) i zatrzymuje się dopiero na jegobreak.matchwyświetliinna,switchwyświetliłbybdb.matchporównuje ściśle (===) – tekst"5"to nie liczba5.switchporównuje luźno (==).- Błąd
UnhandledMatchError– żadna wartość nie pasuje, a nie madefault. Gość, pusty tekst (nic się nie wyświetli),Gość. Operator??reaguje tylko nanulllub nieistniejącą zmienną. Operator?:reaguje na każdą wartość traktowaną jako fałsz, także na pusty tekst.Wojownik.match (true)wybiera pierwszy prawdziwy warunek. Po zamianie kolejności użytkownik z 250 XP dostałbyWojownikzamiastMistrz, bo warunek$xp >= 100byłby sprawdzany jako pierwszy.$status = $wykonalDzisiajZadanie ? "Aktywny" : "Nieaktywny";
Pętle (ang. loops, iterations) to instrukcje, które pozwalają wielokrotnie powtórzyć fragment programu. W PHP dostępne są następujące rodzaje pętli:
for – gdy znamy liczbę iteracji
foreach – do iteracji po elementach tablicy
while – gdy warunek sprawdzamy przed wykonaniem iteracji
do…while – gdy warunek sprawdzamy po wykonaniu iteracji
Pętle for… i foreach…
Budowa pętli for wygląda następująco
for( inicjalizacja zmiennych; sprawdzenie warunku; modyfikacja zmiennych)
{
instrukcja1;
instrukcja...;
}
Elementy pętli for:
- Inicjalizacja – wykonywana raz przed pierwszą iteracją
- Warunek – sprawdzany przed każdą iteracją; jeśli false, pętla kończy działanie
- Modyfikacja – wykonywana po każdej iteracji
Przykład 1: Napisz skrypt, który wyświetli 100 kolejnych liczb całkowitych począwszy od 3.
for ($i = 3; $i <= 102; $i++) {
echo $i;
if ($i < 102) {
echo ', ';
}
}
Przykład 2: Napisz skrypt, obliczający n! (n silnia).
$n = 5;
if ($n == 0 || $n == 1) {
$silnia = 1;
} else {
$silnia = 1;
for ($i = 2; $i <= $n; $i++) {
$silnia *= $i;
}
}
echo "Silnia z $n = $silnia";
// Wynik: Silnia z 5 = 120
Przykład 3: Napisz skrypt, który za pomocą znaków * (gwiazdki) narysuje trójkąt.
define('X', 15); // liczba musi być nieparzysta
echo '<pre>';
for ($w = 1; $w <= X; $w++) {
for ($k = 1; $k <= X + $w; $k++) {
if ($k == X + $w) {
echo "\n";
} elseif ($k > X - $w && $k < X + $w) {
echo '*';
} else {
echo ' ';
}
}
}
echo '</pre>';
//uproszczona wersja
$wysokosc = 8;
echo '<pre>';
for ($i = 1; $i <= $wysokosc; $i++) {
echo str_repeat(' ', $wysokosc - $i);
echo str_repeat('*', 2 * $i - 1);
echo "\n";
}
echo '</pre>';
Przykład 4: Napisz skrypt wyświetlający ciąg Fibonacciego i wypisz wartość ostatniego elementu.
$n = 10;
if ($n <= 0) {
echo "n musi być liczbą dodatnią";
} elseif ($n == 1) {
echo "1. element ciągu Fibonacciego to: 0";
} elseif ($n == 2) {
echo "2. element ciągu Fibonacciego to: 1";
} else {
$f1 = 0; // pierwszy element
$f2 = 1; // drugi element
echo "0 1 ";
for ($i = 3; $i <= $n; $i++) {
$fn = $f1 + $f2;
echo $fn . " ";
$f1 = $f2;
$f2 = $fn;
}
echo "<br>$n. elementem ciągu Fibonacciego jest $f2";
}
Pętla for może operować na literach, zakres literowy jest podobny jak podział kolumn w Excelu
for ($i = 'a'; $i <= 'z'; $i++) {
echo $i . ' ';
}
// Wynik: a b c d e f g h i j k l m n o p q r s t u v w x y z
Pętla for może mieć postać nieskończoną:
$i = 1;
for (;;) {
echo "Wykonuję się $i raz<br>";
if ($i == 10) {
break;
}
$i++;
}
//Uwaga: Zawsze upewnij się, że pętla nieskończona ma warunek przerwania (break), inaczej spowoduje zawieszenie skryptu!
Pętla for może przyjmować wiele warunków, będą one wykonywane po sobie
for ($i = 1, $j = 0; $i <= 10; $j += $i, print "i wynosi = $i, a j = $j<br/>", $i++);
Możemy z pętli wyciągnąć warunki:
for ($i = 1; ; $i++) {
if ($i > 10) {
break;
}
echo $i;
}
foreach
Pętla foreach służy do wykonywania operacji na kolejnych elementach tablicy.
$tablica = ['jabłko', 'banan', 'gruszka'];
foreach ($tablica as $wartosc) {
echo $wartosc . '<br>';
}
jeżeli chcemy operować również na indeksach, możemy je pobrać:
$tablica = [
'a' => 'jabłko',
'b' => 'banan',
'c' => 'gruszka'
];
foreach ($tablica as $klucz => $wartosc) {
echo "$klucz -> $wartosc<br>";
}
Pętle while…
Pętla while wykonuje instrukcje tak długo, jak długo warunek jest prawdziwy. Warunek sprawdzany jest przed każdą iteracją.
while (warunek) {
// instrukcje
}
Przykład 1: Wyświetl wszystkie liczby całkowite nieujemne, mniejsze od podanej liczby.
$x = 10;
$min = 0;
echo "Liczby całkowite mniejsze od $x, to:<br>";
while ($min < $x) {
echo $min;
if ($min < $x - 1) {
echo ' ';
}
$min++;
}
// Wynik: 0 1 2 3 4 5 6 7 8 9
Przykład 2: Napisz skrypt wyznaczający NWD (największy wspólny dzielnik).
$x = 15;
$y = 10;
$a=$x;
$b=$y;
while($a!=$b)
{
if($a>$b) $a-=$b;
else $b-=$a;
}
$nwd = $a; // lub b - obie zmienne przechowują wynik NWD(a,b)
echo('Dla a='.$x.' i b='.$y.' NWD = '.$nwd);
Pętle do… while…
Pętla do…while wykonuje instrukcje co najmniej raz, a następnie sprawdza warunek. Warunek sprawdzany jest po każdej iteracji.
do {
// instrukcje
} while (warunek);
Przykład 1: Napisz skrypt wyświetlający wszystkie liczby całkowite od zera do danej liczby.
$x = 15;
$min = 0;
do {
echo $min;
if ($min < $x) {
echo ' ';
}
$min++;
} while ($min <= $x);
// Wynik: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
Różnica między while a do…while
// while - może w ogóle się nie wykonać
$i = 10;
while ($i < 5) {
echo "Nie wypisze się";
}
// do...while - wykona się przynajmniej raz
$i = 10;
do {
echo "Wypisze się raz"; // wykona się mimo że warunek jest fałszywy
} while ($i < 5);
Kontrola przepływu pętli
Działanie pętli lub skryptu możemy przerwać w dowolnej chwili lub możemy pominąć część instrukcji do wykonania:
- instrukcja break; powoduje natychmiastowe wyjście z pętli
- instrukcja continue; powoduje przeskoczenie do następnego obiegu pętli
- instrukcja exit; powoduje zakończenie wykonywania skryptu
Przerywanie działania pętli za pomocą instrukcji break;
for ($i = 3; $i <= 100; $i++) {
if ($i > 90) {
break; // wyjście z pętli
}
echo $i . ' ';
}
echo '<br>Ta instrukcja zostanie wykonana';
// Wypisze liczby 3-90, a następnie tekst
// Przerwij dwie pętle naraz
for ($i = 0; $i < 5; $i++) {
for ($j = 0; $j < 5; $j++) {
if ($j == 2) {
break 2; // wyjdź z obu pętli
}
echo "[$i][$j] ";
}
}
Przeskok do następnej iteracji (obiegu pętli) za pomocą instrukcji continue;
// Wypisz tylko liczby parzyste od 1 do 100
for ($i = 1; $i <= 100; $i++) {
if ($i % 2 != 0) {
continue; // pomiń nieparzyste
}
echo $i;
if ($i < 100) {
echo ', ';
}
}
Przerywanie wykonywania skryptu za pomocą instrukcji exit;
for ($i = 3; $i <= 10; $i++) {
if ($i > 9) {
exit('Koniec skryptu'); // lub die()
}
echo $i . ' ';
}
echo '<br>Ta instrukcja NIE zostanie wykonana';
Tabela porównawcza pętli
| Pętla | Warunek sprawdzany | Min. wykonań | Przypadek użycia |
|---|---|---|---|
| for | Przed iteracją | 0 | Znana liczba iteracji |
| foreach | Automatycznie | 0 (jeśli tablica pusta) | Iteracja po tablicy/obiekcie |
| while | Przed iteracją | 0 | Nieznana liczba iteracji, warunek przed |
| do…while | Po iteracji | 1 | Nieznana liczba iteracji, warunek po |
Kiedy używać poszczególnych pętli:
- for – gdy znasz dokładną liczbę iteracji lub potrzebujesz indeksu
- foreach – gdy iterujesz po tablicy lub kolekcji
- while – gdy nie znasz liczby iteracji, warunek sprawdzany przed wykonaniem
- do…while – gdy pętla musi wykonać się przynajmniej raz
Pamiętaj:
- Zawsze upewnij się, że pętla ma warunek zakończenia
- Używaj break i continue świadomie
- Preferuj wbudowane funkcje (array_map, array_filter) zamiast ręcznych pętli
- Unset referencji po foreach z &
- Unikaj modyfikacji tablicy podczas iteracji foreach
- Używaj składni alternatywnej w szablonach HTML
Zadania do samodzielnego wykonania:
Zadanie 1 (dla klas, które miały już HTMLa): Za pomocą pętli for stwórz tabelę w HTML składająca się z 2 wierszy i 10 kolumn.
Zadanie 1 (dla klas, które nie miały HTMLa): Za pomocą pętli for wypisz na ekranie dowolne znaki, tak aby układały się w 2 wiersze po 10 znaków.
Zadanie 2: Za pomocą pętli for, while i do… while napisz skrypt, który będzie zwiększał zmienną $i od 1 do 100 o 2, a następnie zmniejszał ją do 1 o 4.
Zadanie 3: Napisz skrypt, który dla zmiennej $n=10 i $n>0 będzie ją zmniejszał o 1 i wypisywał: wartości kwadratów zmiennej $n; następnie wartości kwadratów zmiennej $n dla $n parzystych.
Zadanie 4: Za pomocą pętli for, while i do… while napisz skrypt, który wypisze ilość iteracji pętli dla zmiennej $i<=10. Tam gdzie to możliwe zastosuj $i++, ++$i, $i- -, – -$i.
Zadanie 5: Napisz skrypt, który sprawdzi, czy podana liczba jest liczbą pierwszą.
Zadanie 6: Za pomocą pętli for stwórz tabliczkę mnożenia wg przykładu:

Zadanie 7: Napisz skrypt, który za pomocą znaków * (gwiazdki) narysuje kwadrat. Gwiazdki leżące na obwodzie mają mieć kolor niebieski, a gwiazdki leżące na przekątnych zielone.
Zadanie 8: Napisz skrypt, który po podaniu przez użytkownika promienia koła, za pomocą znaków * (gwiazdki), narysuje je.
Zadanie 9: Oblicz ilość bloków z jakich został zbudowany sześcian o boku długości 6.
Zadanie 10: Wyświetl kolejno liczby od 1 do 10 (każda w nowej linii). Wykorzystaj pętle for
Zadanie 11: Wyświetl liczby malejąco od 10 do 0. Użyj pętli for.
Zadanie 12: Wyświetl kolejno liczby od 10 do 0 z krokiem 0,5. Użyj pętli for.
Zadanie 13: Wyświetl: „PHP1 PHP2 PHP3 PHP4 PHP5 PHP6 PHP7 PHP8 PHP9 PHP10”. Użyj pętli while
Zadanie 14: Napisz skrypt z użyciem pętli do…while wyświetlający następującą listę:
• Element nr 1
• Element nr 2
• Element nr 3
• Element nr 4
Zadanie 15: Napisz skrypt sumujący wszystkie liczby nieparzyste z przedziału od 0 do 10. Użyj instrukcji continue.
Zadanie 16: Napisz skrypt wyświetlający: “1-2-3-5-6-7-8-9”. Użyj dowolnej pętli i instrukcji przerywającej (wykluczono wartość 4).
Zadanie 17: Napisz skrypt wyświetlający szachownicę.
TaskQuest — Twój projekt na cały semestr
KARTA PRACY
Karta pracy — lekcja 5
PHP — pętle oraz składnia alternatywna
Projekt: TaskQuest — grywalizowana aplikacja do zarządzania zadaniami. Użytkownik loguje się, dodaje zadania, za ich wykonanie zdobywa punkty XP, awansuje na poziomy, zdobywa odznaki i widzi swoją pozycję w rankingu klasy.
Każda lekcja rozbudowuje tę samą aplikację o kolejny element.
Cel lekcji
Wykorzystać pętle do rozwiązania problemów, których nie dało się poprawnie obsłużyć pojedynczą instrukcją warunkową.
Po tej lekcji TaskQuest:
poprawnie obsłuży zdobycie dużej liczby XP,
pozwoli awansować o kilka poziomów jednocześnie,
automatycznie wygeneruje wizualny pasek postępu XP,
wykorzysta pętlę
whiletam, gdzie nie znamy wcześniej liczby powtórzeń,wykorzysta pętlę
fortam, gdzie liczba powtórzeń jest znana.
Co dziś budujesz?
TaskQuest 0.5 — poprawny system poziomów
Na poprzedniej lekcji nauczyliśmy TaskQuest podejmować decyzję:
Czy użytkownik zdobył już wystarczająco dużo XP, aby awansować?
Wykorzystaliśmy do tego instrukcję:
if
Działała dobrze, dopóki użytkownik przekraczał tylko jeden próg.
Dzisiaj naprawimy to ograniczenie.
1. Punkt startowy — kontynuujemy kod z lekcji 4
Nie twórz nowego projektu.
Otwórz dotychczasowy plik index.php projektu TaskQuest.
Po lekcji 4 logika związana z XP może wyglądać mniej więcej tak:
<?php
echo "<h1>TaskQuest</h1>";
echo "<p>Zdobywaj punkty za wykonane zadania!</p>";
define('XP_NA_POZIOM', 100);
$imieUzytkownika = "Kasia";
$xp = 250;
$poziom = 1;
// Próg potrzebny do awansu
$progNastepnegoPoziomu = $poziom * XP_NA_POZIOM;
// Sprawdzenie awansu
if ($xp >= $progNastepnegoPoziomu) {
$poziom++;
echo "Awansowałeś na poziom $poziom!<br>";
}
// Tytuł użytkownika
switch ($poziom) {
case 1:
$tytul = "Nowicjusz";
break;
case 2:
$tytul = "Wojownik";
break;
default:
$tytul = "Mistrz";
}
// Aktywność — nadal ustawiana ręcznie.
// Prawdziwe sprawdzanie aktywności zrobimy przy obsłudze dat.
$wykonalDzisiajZadanie = true;
$status = $wykonalDzisiajZadanie ? "Aktywny" : "Nieaktywny";
// Postęp XP w aktualnym poziomie
$procentPostepu = (($xp - ($poziom - 1) * XP_NA_POZIOM) / XP_NA_POZIOM) * 100;
echo "Witaj, $imieUzytkownika! Twój poziom: $poziom. Status: $status. Tytuł: $tytul<br>";
echo "Masz $xp XP z " . XP_NA_POZIOM . " potrzebnych do poziomu ".++$poziom." (" . $procentPostepu . "%)";
?>
Jeżeli Twój dotychczasowy kod zawiera więcej HTML lub CSS — nie usuwaj go.
Modyfikujemy tylko mechanizm odpowiedzialny za poziomy i dodajemy pasek XP.
2. Najpierw znajdź problem
Spójrz na dane:
$xp = 250;
$poziom = 1;
Progi TaskQuest wyglądają następująco:
| Awans | Wymagane łączne XP |
|---|---|
| poziom 1 → 2 | 100 XP |
| poziom 2 → 3 | 200 XP |
| poziom 3 → 4 | 300 XP |
| poziom 4 → 5 | 400 XP |
Użytkownik posiada:
250 XP
Powinien więc znaleźć się na:
poziomie 3
Ale nasz kod wykona instrukcję:
$poziom++;
tylko jeden raz.
Wynikiem będzie:
poziom 2
mimo że użytkownik ma już wystarczająco dużo XP na poziom 3.
Pytanie
Dlaczego zwykły if nie rozwiązuje tego problemu?
Zastanów się, zanim przejdziesz dalej.
3. SAMODZIELNIE — napraw system awansu
Twoim pierwszym zadaniem jest zmodyfikowanie programu tak, aby sprawdzał próg awansu:
tak długo, jak długo użytkownik posiada wystarczająco dużo XP.
Nie wiemy wcześniej, ile razy trzeba będzie wykonać sprawdzenie.
Dla:
$xp = 40;
nie wykonamy żadnego awansu.
Dla:
$xp = 150;
wykonamy jeden.
Dla:
$xp = 250;
wykonamy dwa.
Dla:
$xp = 550;
wykonamy pięć.
Zadanie
Znajdź w swoim kodzie:
if ($xp >= $progNastepnegoPoziomu) {
$poziom++;
echo "Awansowałeś na poziom $poziom!<br>";
}
i zastąp ten mechanizm odpowiednią pętlą.
HINT 1
Potrzebujemy pętli, której liczba wykonań nie jest znana przed uruchomieniem programu.
Warunek ma być sprawdzany przed każdą kolejną iteracją.
Która pętla najlepiej tutaj pasuje?
for
foreach
while
do...while
HINT 2
Warunek możemy zapisać bezpośrednio:
$xp >= $poziom * XP_NA_POZIOM
Pętla powinna działać mniej więcej tak:
while (WARUNEK) {
// awans
}
HINT 3
W każdej iteracji musi zmienić się coś, co wpływa na warunek.
W naszym przypadku zmienia się:
$poziom
czyli:
$poziom++;
POMOC
Spróbuj uzupełnić:
while ($xp >= __________________________) {
___________________;
}
Po każdej iteracji wartość $poziom rośnie.
To powoduje, że automatycznie rośnie również następny próg XP.
UWAGA — bardzo częsty błąd
Nie rób tego:
$progNastepnegoPoziomu = $poziom * XP_NA_POZIOM;
while ($xp >= $progNastepnegoPoziomu) {
$poziom++;
}
Dlaczego?
Jeżeli przed pętlą:
$progNastepnegoPoziomu = 100;
to jego wartość nie zmieni się tylko dlatego, że zwiększyliśmy $poziom.
Dla:
$xp = 250;
warunek:
250 >= 100
będzie zawsze prawdziwy.
Powstanie pętla nieskończona.
Dlatego możemy:
obliczać próg bezpośrednio w warunku,
albo
aktualizować
$progNastepnegoPoziomuwewnątrz pętli.
W naszym projekcie wybieramy prostszy pierwszy wariant.
4. Sprawdź swój mechanizm
Przetestuj kolejno:
$xp = 40;
$xp = 100;
$xp = 250;
$xp = 550;
Oczekiwane wyniki:
| XP | Poziom |
|---|---|
| 40 | 1 |
| 100 | 2 |
| 250 | 3 |
| 550 | 6 |
Jeżeli dla:
250 XP
otrzymujesz:
poziom 3
pierwsza część zadania działa poprawnie.
5. Policz, ile poziomów zdobył użytkownik
Chcemy również wiedzieć, czy podczas obliczeń nastąpił awans.
Przed pętlą zapamiętaj poziom startowy:
$poziomStartowy = $poziom;
Po zakończeniu pętli możesz policzyć:
$liczbaAwansow = $poziom - $poziomStartowy;
Jeżeli:
$liczbaAwansow > 0
wyświetl komunikat.
Przykład:
Awansowałeś o 2 poziomy!6. Zaktualizuj tytuł użytkownika
Dopiero po zakończeniu pętli ustal tytuł użytkownika.
Pozostaw mechanizm poznany w poprzedniej lekcji:
switch ($poziom) {
case 1:
$tytul = "Nowicjusz";
break;
case 2:
$tytul = "Wojownik";
break;
default:
$tytul = "Mistrz";
}
lub zastosuj nowocześniejsze podejście:
$tytul = match ($poziom) {
1 => "Nowicjusz",
2 => "Wojownik",
default => "Mistrz"
};
Dzięki temu:
40 XP → Nowicjusz
100 XP → Wojownik
250 XP → Mistrz7. Oblicz postęp wewnątrz aktualnego poziomu
Poziom został już poprawnie ustalony.
Teraz możemy policzyć postęp.
Najpierw ustal XP wymagane na początku aktualnego poziomu:
$xpNaPoczatkuPoziomu = ($poziom - 1) * XP_NA_POZIOM;
Następnie oblicz XP zdobyte już w tym poziomie:
$xpWAktualnymPoziomie = $xp - $xpNaPoczatkuPoziomu;
I zaktualizuj procent:
$procentPostepu = ($xpWAktualnymPoziomie / XP_NA_POZIOM) * 100;Przykład
Dla:
XP = 250
poziom = 3
początek poziomu 3 to:
200 XP
Użytkownik ma więc:
250 - 200 = 50 XP
w aktualnym poziomie.
Czyli:
50 / 100 = 50%8. Druga pętla — budujemy pasek XP
Teraz wykorzystamy for.
Dlaczego?
Chcemy zawsze wyświetlić dokładnie:
10 segmentów
Czyli znamy liczbę iteracji.
Pasek dla 50%
Powinien wyglądać np.:
█████░░░░░
lub graficznie:
[■■■■■□□□□□]SAMODZIELNIE
Oblicz liczbę aktywnych segmentów:
$liczbaAktywnychSegmentow =
(int) ($procentPostepu / 10);
Następnie wykonaj pętlę:
for ($segment = 1; $segment <= 10; $segment++) {
// jeżeli segment mieści się w postępie:
// wyświetl segment aktywny █
// w przeciwnym razie:
// wyświetl segment pusty ░
}
Wykorzystaj wiedzę o if z poprzedniej lekcji. Jeżeli chcesz możesz dodać style i elementy HTML.
HINT
Dla:
$liczbaAktywnychSegmentow = 5;
warunek:
$segment <= $liczbaAktywnychSegmentow
będzie prawdziwy dla:
1
2
3
4
5
i fałszywy dla:
6
7
8
9
10
9. Składnia alternatywna
W głównej części lekcji poznałeś/aś również składnię alternatywną.
W HTML zamiast:
for (...) {
}
możemy zapisać:
<?php for (...): ?>
<!-- HTML -->
<?php endfor; ?>Zadanie
Spróbuj wygenerować segmenty właśnie w ten sposób. W dalszej części stosuj składnię, która najbardziej Ci odpowiada.
Przykładowy schemat:
<div class="pasek-xp">
<?php for ($segment = 1; $segment <= 10; $segment++): ?>
<!-- jeden segment -->
<?php endfor; ?>
</div>10. Oczekiwany efekt
Dla danych:
$imieUzytkownika = "Kasia";
$xp = 250;
$poziom = 1;
$wykonalDzisiajZadanie = true;
TaskQuest powinien ostatecznie pokazać mniej więcej:

Nie musisz uzyskać identycznego wyglądu graficznego.
Najważniejsze jest poprawne działanie logiki i wystąpienie niezbędnych (widocznych na zdjęciu) elementów.
11. PRZYKŁADOWE ROZWIĄZANIE
Rozwiń
Spróbuj wykonać zadanie samodzielnie przed otwarciem rozwiązania. Logika aplikacji powinna znajdować się na górze dokumentu, a elementy odpowiedzialne za wyświetlanie wewnątrz <body>. Spróbuj dodać własne style.
<?php
define('XP_NA_POZIOM', 100);
$imieUzytkownika = "Kama";
$xp = 250;
$poziom = 1;
$poziomStartowy = $poziom;
while ($xp >= $poziom * XP_NA_POZIOM) {
$poziom++;
}
$liczbaAwansow = $poziom - $poziomStartowy;
$tytul = match ($poziom) {
1 => "Nowicjusz",
2 => "Wojownik",
default => "Mistrz"
};
//postęp wewnątrz aktualnego poziomu
$xpNaPoczatkuPoziomu = ($poziom - 1) * XP_NA_POZIOM;
$xpWAktualnymPoziomie = $xp - $xpNaPoczatkuPoziomu;
$procentPostepu = ($xpWAktualnymPoziomie / XP_NA_POZIOM) * 100;
// Tymczasowo ustawiane ręcznie - w lekcji 7 zastąpimy to sprawdzeniem daty
$wykonalDzisiajZadanie = true;
$status = $wykonalDzisiajZadanie ? "Aktywny" : "Nieaktywny";
//pasek postępu
$liczbaAktywnychSegmentow = (int) ($procentPostepu / 10);
$progNastepnegoPoziomu = $poziom * XP_NA_POZIOM;
?>
<!DOCTYPE html>
<html lang="pl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>TaskQuest</title>
<style>
body {
font-family: Arial, sans-serif;
max-width: 700px;
margin: 40px auto;
padding: 20px;
}
.panel {
border: 1px solid #ccc;
padding: 24px;
border-radius: 12px;
}
.pasek-xp {
display: flex;
gap: 4px;
margin: 10px 0;
}
.segment {
width: 32px;
height: 18px;
background: #ddd;
border-radius: 3px;
}
.segment.aktywny {
background: #555;
}
.awans {
font-weight: bold;
}
</style>
</head>
<body>
<div class="panel">
<h1>TaskQuest</h1>
<p>Zdobywaj punkty za wykonane zadania!</p>
<h2>Witaj, <?= $imieUzytkownika; ?>!</h2>
<p>Poziom: <strong><?= $poziom; ?></strong></p>
<p>Tytuł: <strong><?= $tytul; ?></strong></p>
<p>Łączne XP: <strong><?= $xp; ?></strong></p>
<?php
if ($liczbaAwansow > 0){
echo "<p class=\"awans\">Awansowałeś o $liczbaAwansow poziomy!</p>";
}
?>
<h3>
<?= "Masz $xpWAktualnymPoziomie XP z " . XP_NA_POZIOM . " XP potrzebnych do poziomu ".++$poziom." (" . round($procentPostepu, 2) . "%)"; ?>
</h3>
<div class="pasek-xp">
<?php
for ($segment = 1; $segment <= 10; $segment++) {
if ($segment <= $liczbaAktywnychSegmentow) {
echo "█";
} else {
echo "░";
}
// lub z wykorzystaniem CSS
// if ($segment <= $liczbaAktywnychSegmentow) {
// echo "<span class=\"segment aktywny\"></span>";
// } else {
// echo "<span class=\"segment\"></span>";
// }
}
?>
</div>
<p>Kolejny próg: <?= $progNastepnegoPoziomu; ?> XP</p>
<p>
Status:<strong><?= $status; ?></strong>
</p>
</div>
</body>
</html>
12. Przetestuj rozwiązanie
Samo uruchomienie kodu jeden raz nie wystarcza.
Zmień tylko:
$xp
i sprawdź poniższe przypadki.
| Test | XP | Oczekiwany poziom | XP w poziomie | Postęp |
|---|---|---|---|---|
| 1 | 0 | 1 | 0 | 0% |
| 2 | 40 | 1 | 40 | 40% |
| 3 | 99 | 1 | 99 | 99% |
| 4 | 100 | 2 | 0 | 0% |
| 5 | 150 | 2 | 50 | 50% |
| 6 | 199 | 2 | 99 | 99% |
| 7 | 200 | 3 | 0 | 0% |
| 8 | 250 | 3 | 50 | 50% |
| 9 | 550 | 6 | 50 | 50% |
13. Obowiązkowy eksperyment
Na chwilę wróć do starej wersji:
if ($xp >= $poziom * XP_NA_POZIOM) {
$poziom++;
}
Ustaw:
$xp = 550;
Zapisz otrzymany poziom.
Następnie przywróć:
while
i sprawdź wynik ponownie.
Odpowiedz:
Dlaczego wyniki są różne?
14. Mini-zadanie — co się stanie?
Przeanalizuj kod bez uruchamiania go:
$xp = 250;
$poziom = 1;
while ($xp >= $poziom * 100) {
$poziom++;
}
echo $poziom;
Zapisz przewidywany wynik.
Dopiero później uruchom program i sprawdź swoją odpowiedź.
Do samodzielnego sprawdzenia
Kontynuuję projekt z poprzedniej lekcji — nie stworzyłem/am TaskQuest od początku.
Pojedynczy
ifodpowiedzialny za awans został zastąpiony pętląwhile.Użytkownik z 250 XP otrzymuje poziom 3.
Użytkownik z 550 XP otrzymuje poziom 6.
Potrafię wyjaśnić, dlaczego
whilemoże wykonać się kilka razy.Potrafię wskazać warunek zakończenia pętli.
Mój
whilenie tworzy pętli nieskończonej.Po awansie ponownie prawidłowo wyliczany jest procent postępu.
Pasek XP składa się z 10 segmentów.
Segmenty generowane są przez
for, a nie wpisane ręcznie.Przetestowałem/am minimum cztery różne wartości XP.
Potrafię powiedzieć, dlaczego do awansu wybraliśmy
while, a do paskafor.
Pytania kontrolne
Dlaczego pojedynczy
ifz lekcji 4 nie obsługiwał poprawnie użytkownika posiadającego 250 XP?Dlaczego
whilelepiej pasuje do systemu wielokrotnego awansu niżfor?Co w naszej pętli sprawia, że kiedyś przestaje się wykonywać?
Jaki poziom otrzyma użytkownik mający 550 XP?
Co stanie się, jeżeli zapiszemy:
$prog = $poziom * XP_NA_POZIOM;
while ($xp >= $prog) {
$poziom++;
}
i nie zmienimy $prog wewnątrz pętli?
Dlaczego do wygenerowania dziesięciu segmentów paska XP dobrze nadaje się
for?Czym różni się
whileoddo...while?Do czego służy
foreach?Jak działa
break?Jak działa
continue?
PODSUMOWANIE LEKCJI
W skrócie
- for – trzy części w nawiasie: inicjalizacja (wykonywana raz), warunek (sprawdzany przed każdym obiegiem), modyfikacja (wykonywana po każdym obiegu). Części oddzielamy średnikami, nie przecinkami.
- while – warunek sprawdzany przed obiegiem, więc pętla może nie wykonać się ani razu. W ciele pętli musi zmieniać się coś, od czego zależy warunek – inaczej powstaje pętla nieskończona.
- do…while – wykonuje się co najmniej raz, warunek sprawdzany jest po obiegu. Po
while (warunek)stawiamy średnik. - foreach – służy do przechodzenia po tablicy.
as $wartoscdaje same wartości,as $klucz => $wartosc– klucze i wartości. - Wartość obliczona przed pętlą nie zmieni się sama w trakcie jej działania. Jeżeli warunek ma zależeć od zmieniającej się zmiennej, licz go w warunku albo aktualizuj wewnątrz pętli (pułapka z
$progNastepnegoPoziomuw TaskQuest). - Zmienne sumujące i liczące (
$suma,$licznik) ustawiamy przed pętlą. Ustawione wewnątrz – zerują się w każdym obiegu. <a<=w warunku to często różnica jednego obiegu. Przy każdej pętli sprawdź, jaka jest pierwsza i ostatnia wartość licznika.- break wychodzi tylko z najbliższej pętli (
break 2– z dwóch zagnieżdżonych). continue pomija resztę bieżącego obiegu i przechodzi do następnego. exit kończy cały skrypt – kod po nim się nie wykona. - Wybór pętli: znana liczba powtórzeń →
for, tablica →foreach, powtarzanie „dopóki warunek jest spełniony” →while, „najpierw wykonaj, potem sprawdź” →do…while. - Składnia alternatywna (
:zamiast{, słowo kończące zamiast}) istnieje dlafor,foreachiwhile– dlado…whilenie. Stosujemy ją, gdy pętla generuje fragmenty HTML. Nie wolno mieszać obu zapisów w jednej pętli.
Co trzeba umieć na INF.03?
- dobrać rodzaj pętli do problemu i uzasadnić wybór,
- napisać pętlę, która generuje powtarzalny kod HTML: wiersze tabeli (
<tr><td>), opcje listy (<option>), elementy listy (<li>), odnośniki (<a>), - wstawiać wartości zmiennych do generowanego HTML (w
echoalbo przez<?= ?>w składni alternatywnej), - przewidzieć, ile razy wykona się pętla i co wyświetli,
- rozpoznać pętlę nieskończoną i wskazać jej przyczynę,
- zaimplementować proste algorytmy z użyciem pętli: sumowanie, zliczanie, szukanie wartości, silnia, NWD, sprawdzanie liczby pierwszej.
Minimum, które powinno wejść w pamięć
Jeżeli masz zapamiętać tylko kilka rzeczy z tej lekcji, zapamiętaj te:
for ($i = 1; $i <= 10; $i++)– średniki, nie przecinki.whilemoże nie wykonać się ani razu,do…whilewykona się zawsze co najmniej raz.- W
whilecoś w środku musi zmieniać warunek, inaczej pętla nigdy się nie skończy. foreach ($tablica as $klucz => $wartosc)– najpierw tablica, potemas.$suma = 0;przed pętlą, nie w środku.break– wyjdź z pętli,continue– przejdź do następnego obiegu.- Składnia alternatywna:
for (...):…endfor;,foreach (...):…endforeach;,while (...):…endwhile;.
Ściągawka – najważniejsze polecenia i składnia
Rodzaje pętli
for ($i = 1; $i <= 10; $i++) { ... } // znana liczba powtórzeń
foreach ($tablica as $wartosc) { ... } // tylko wartości
foreach ($tablica as $klucz => $wartosc) { ... }
while ($warunek) { ... } // 0 lub więcej obiegów
do { ... } while ($warunek); // 1 lub więcej obiegów – średnik!
Sterowanie pętlą
| Instrukcja | Działanie |
|---|---|
break; | wyjście z najbliższej pętli |
break 2; | wyjście z dwóch zagnieżdżonych pętli |
continue; | przejście do następnego obiegu |
exit; / exit('tekst'); | zakończenie całego skryptu |
Składnia alternatywna
| Zwykła | Alternatywna |
|---|---|
for (...) { } | for (...): … endfor; |
foreach (...) { } | foreach (...): … endforeach; |
while (...) { } | while (...): … endwhile; |
do { } while (...); | brak |
Schemat: generowanie HTML w pętli
<select name="liczba">
<?php for ($i = 1; $i <= 5; $i++): ?>
<option value="<?= $i ?>"><?= $i ?></option>
<?php endfor; ?>
</select>
To samo w zwykłej składni:
for ($i = 1; $i <= 5; $i++) {
echo "<option value=\"$i\">$i</option>";
}
Schemat: akumulator (suma, licznik)
$suma = 0; // przed pętlą
foreach ($liczby as $liczba) {
$suma += $liczba; // w pętli
}
echo $suma; // po pętli
Quiz – sprawdź się
1. Dobierz najlepszą pętlę do każdej sytuacji i krótko uzasadnij:
a) wyświetlenie dokładnie 10 segmentów paska XP,
b) wypisanie wszystkich imion zapisanych w tablicy $uczniowie,
c) awansowanie użytkownika, dopóki ma wystarczająco dużo XP,
d) wyświetlenie komunikatu, który musi pojawić się przynajmniej raz, a potem powtarza się zależnie od warunku.
2. Co zostanie wyświetlone?
for ($i = 10; $i > 0; $i -= 3) {
echo $i . " ";
}
3. Co wyświetli każdy z fragmentów?
// Fragment A
$i = 5;
while ($i < 5) {
echo $i;
$i++;
}
// Fragment B
$i = 5;
do {
echo $i;
$i++;
} while ($i < 5);
4. Znajdź błąd. Co stanie się po uruchomieniu tego kodu i jak go poprawić?
$i = 1;
while ($i <= 5) {
echo $i;
}
5. Co zostanie wyświetlone?
for ($i = 1; $i <= 6; $i++) {
if ($i % 3 == 0) {
continue;
}
echo $i;
}
6. Co zostanie wyświetlone? Czy napis „koniec” się pojawi?
for ($i = 1; $i <= 10; $i++) {
if ($i == 4) {
break;
}
echo $i;
}
echo " koniec";
7. Co zostanie wyświetlone? Jak zmieni się wynik po zamianie break; na break 2;?
for ($i = 1; $i <= 3; $i++) {
for ($j = 1; $j <= 3; $j++) {
if ($j == 2) {
break;
}
echo "$i$j ";
}
}
8. Uczeń chciał zsumować XP z tablicy, ale program wyświetla 30 zamiast 60. Dlaczego? Popraw kod.
foreach ([10, 20, 30] as $xp) {
$suma = 0;
$suma += $xp;
}
echo $suma;
9. Uzupełnij kod tak, aby dla tablicy poniżej wyświetlił się tekst Ala: 120 XP i Olek: 80 XP (każdy w nowej linii).
$ranking = ['Ala' => 120, 'Olek' => 80];
foreach (__________________________) {
echo __________________________;
}
10. Czego brakuje w miejscu ______?
<ul>
<?php foreach ($zadania as $zadanie): ?>
<li><?= $zadanie ?></li>
<?php ______ ?>
</ul>
11. Dlaczego ten kod powoduje błąd składni?
<?php for ($i = 1; $i <= 3; $i++): ?>
<p>Zadanie nr <?= $i ?></p>
<?php } ?>
12. TaskQuest: przeanalizuj kod bez uruchamiania go. Jaki poziom otrzyma użytkownik? Ile XP ma w aktualnym poziomie i jak będzie wyglądał jego 10-segmentowy pasek (█ – aktywny, ░ – pusty)?
define('XP_NA_POZIOM', 100);
$xp = 420;
$poziom = 1;
while ($xp >= $poziom * XP_NA_POZIOM) {
$poziom++;
}
13. Ile razy wykona się ciało pętli?
for ($i = 0; $i < 10; $i += 2) {
// ...
}
14. Zadanie praktyczne. Napisz pętlę, która wygeneruje tabelę HTML z jednym wierszem nagłówka Liczba | Kwadrat oraz pięcioma wierszami danych dla liczb od 1 do 5. Możesz użyć zwykłej lub alternatywnej składni.
Odpowiedzi
- a)
for– znana liczba powtórzeń; b)foreach– przechodzimy po tablicy; c)while– nie wiemy, ile będzie awansów, warunek trzeba sprawdzić przed pierwszym awansem (może nie być żadnego); d)do…while– ciało musi wykonać się co najmniej raz. 10 7 4 1- Fragment A nie wyświetli nic (warunek fałszywy od razu). Fragment B wyświetli
5– ciało wykonuje się przed sprawdzeniem warunku. - Pętla nieskończona:
$isię nie zmienia, więc1 <= 5jest zawsze prawdziwe. Poprawka: dodać$i++;w ciele pętli. 1245– dla 3 i 6continuepomijaecho.123 koniec.breakkończy tylko pętlę, kod po pętli wykonuje się normalnie.11 21 31–breakprzerywa tylko pętlę wewnętrzną, zewnętrzna działa dalej. Zbreak 2;wynik to11– obie pętle kończą się przy pierwszym$j == 2.$suma = 0;jest wewnątrz pętli, więc suma zeruje się w każdym obiegu i zostaje tylko ostatnia wartość. Przenieś$suma = 0;przed pętlę.- Przykładowo:
foreach ($ranking as $imie => $punkty) {
echo "$imie: $punkty XP<br>";
} endforeach;- Pętla otwarta w składni alternatywnej (
:) musi zostać zamknięta przezendfor;, a nie}. Nie wolno mieszać obu zapisów. - Poziom 5 (progi 100, 200, 300, 400 zostały przekroczone, 500 – nie). XP w aktualnym poziomie: 420 − 400 = 20, czyli 20%. Pasek:
██░░░░░░░░. - 5 razy (
$i= 0, 2, 4, 6, 8). - Przykładowe rozwiązanie:
<table>
<tr><th>Liczba</th><th>Kwadrat</th></tr>
<?php for ($i = 1; $i <= 5; $i++): ?>
<tr><td><?= $i ?></td><td><?= $i * $i ?></td></tr>
<?php endfor; ?>
</table>
Sprawdź: tabela ma 6 wierszy (1 nagłówek + 5 danych), ostatni wiersz to5 | 25.