Menu
Coddy logo textTech

Tworzenie postaci do gry

Część sekcji Programowanie obiektowe ścieżki PHP w Coddy. Lekcja 90 z 91.

challenge icon

Wyzwanie

Łatwy

Zbudujmy system Rozwoju postaci w grze, w którym różne klasy postaci walczą, używając unikalnych zdolności. Stworzysz hierarchię postaci z systemem doświadczenia i awansowania na kolejne poziomy, pokazując, jak dziedziczenie, interfejsy, cechy i enkapsulacja współdziałają w kontekście gry.

Rozmieścisz kod w sześciu plikach:

  • Ability.php: Zdefiniuj interfejs Ability z dwiema metodami: getName(): string i use(Character $target): string. Ten kontrakt zapewnia, że wszystkie zdolności można stosować w spójny sposób, niezależnie od ich konkretnych efektów.
  • CombatLogger.php: Utwórz cechę CombatLogger, która udostępnia metodę logAction(string $action): string. Metoda ta powinna zwracać ciąg znaków opisujący akcję z prefiksem "[COMBAT] ". Postacie będą używać tej cechy, aby formatować komunikaty dotyczące walki w spójny sposób.
  • Character.php: Dołącz pliki Ability i CombatLogger. Utwórz abstrakcyjną klasę Character, która używa cechy CombatLogger. Użyj promocji konstruktora dla name (string, public readonly). Dodaj prywatne właściwości: health (int, początkowo 100), level (int, początkowo 1) oraz experience (int, początkowo 0). Zaimplementuj:
    • getHealth(): int i getLevel(): int: metody pobierające wartości prywatnych właściwości
    • takeDamage(int $amount): void: zmniejsza zdrowie, ale nigdy poniżej 0
    • heal(int $amount): void: zwiększa zdrowie, ale nigdy powyżej 100
    • gainExperience(int $xp): string: dodaje PD; jeśli doświadczenie osiągnie co najmniej 100, postać awansuje na kolejny poziom (ustawia PD na 0, zwiększa poziom, przywraca 20 HP) i zwraca "[name] leveled up to [level]!"; w przeciwnym razie zwraca "[name] gained [xp] XP"
    • isAlive(): bool: zwraca true, jeśli zdrowie jest większe niż 0
    • abstract getSpecialAbility(): Ability: każdy typ postaci udostępnia swoją unikalną zdolność
    • attack(Character $target): string: zadaje celowi 10 punktów obrażeń, używa logAction(), aby zwrócić "[COMBAT] [name] attacks [target name] for 10 damage"
  • Warrior.php: Dołącz plik Character. Utwórz klasę Warrior rozszerzającą Character. Zaimplementuj getSpecialAbility(), aby zwracała klasę anonimową implementującą Ability:
    • getName() zwraca "Shield Bash"
    • use() zadaje 25 punktów obrażeń i zwraca "[COMBAT] Shield Bash hits [target name] for 25 damage!" (użyj metody logAction() z cechy)
  • Mage.php: Dołącz plik Character. Utwórz klasę Mage rozszerzającą Character. Zaimplementuj getSpecialAbility(), aby zwracała klasę anonimową implementującą Ability:
    • getName() zwraca "Fireball"
    • use() zadaje 35 punktów obrażeń i zwraca "[COMBAT] Fireball engulfs [target name] for 35 damage!"
  • main.php: Dołącz pliki Warrior i Mage. Otrzymasz dwa wejścia: dane postaci (JSON) i sekwencję akcji bojowych (JSON).

    Format JSON postaci:

    [{"type": "warrior", "name": "Thorin"}, {"type": "mage", "name": "Gandalf"}]

    Format JSON akcji:

    [{"action": "attack", "attacker": 0, "target": 1}, {"action": "special", "attacker": 1, "target": 0}, {"action": "xp", "character": 0, "amount": 100}, {"action": "status", "character": 0}]

    Utwórz wszystkie postacie i przechowaj je w tablicy (indeksy 0, 1 itd.). Przetwórz każdą akcję:

    • "attack": postać o indeksie attacker atakuje cel; wypisz wynik
    • "special": postać używa swojej specjalnej zdolności na celu; wypisz wynik
    • "xp": postać zdobywa doświadczenie; wypisz wynik
    • "heal": postać odzyskuje zdrowie o podaną wartość; wypisz "[name] healed to [health] HP"
    • "status": wypisz "[name] - Level [level], HP: [health], Alive: [Yes/No]"

    Wypisz każdy wynik w nowym wierszu.

Ten system pokazuje, jak klasy abstrakcyjne definiują wspólne zachowania postaci, interfejsy zapewniają zgodność zdolności ze spójnym kontraktem, cechy udostępniają funkcjonalność rejestrowania możliwą do ponownego użycia, a klasy anonimowe pozwalają tworzyć unikalne implementacje zdolności bez zaśmiecania bazy kodu klasami używanymi tylko raz.

Spróbuj swoich sił

<?php
require_once 'Warrior.php';
require_once 'Mage.php';

// Odczytaj dane wejściowe
$charactersJson = trim(fgets(STDIN));
$actionsJson = trim(fgets(STDIN));

// Przetwórz dane wejściowe JSON
$charactersData = (array)json_decode($charactersJson, true);
$actionsData = (array)json_decode($actionsJson, true);

// TODO: Utwórz tablicę do przechowywania obiektów postaci
$characters = [];

// TODO: Przejdź przez $charactersData i utwórz obiekty Warrior lub Mage
// na podstawie pola "type", a następnie zapisz je w tablicy $characters

// TODO: Przetwórz każdą akcję w $actionsData
// Obsłuż następujące typy akcji:
// - "attack": Postać o indeksie atakującego atakuje cel; wypisz wynik
// - "special": Postać używa getSpecialAbility()->use() na celu; wypisz wynik
// - "xp": Postać zdobywa doświadczenie; wypisz wynik
// - "heal": Postać się leczy; wypisz "[name] healed to [health] HP"
// - "status": Wypisz "[name] - Level [level], HP: [health], Alive: [Yes/No]"

?>

Wszystkie lekcje w sekcji Programowanie obiektowe

Poćwicz samodzielnie: Kompilator PHP online