Menu
Coddy logo textTech

Spielcharakter-Entwicklung

Teil des Abschnitts Objektorientierte Programmierung der PHP-Journey von Coddy — Lektion 90 von 91.

challenge icon

Aufgabe

Einfach

Lassen Sie uns ein Game Character Development System entwickeln, in dem verschiedene Charakterklassen mit einzigartigen Fähigkeiten gegeneinander kämpfen. Sie werden eine Hierarchie von Charakteren mit einem Erfahrungs- und Levelsystem erstellen und dabei demonstrieren, wie Vererbung, Interfaces, Traits und Kapselung in einem Spielkontext zusammenwirken.

Sie werden Ihren Code in sechs Dateien organisieren:

  • Ability.php — Definieren Sie ein Ability Interface mit zwei Methoden: getName(): string und use(Character $target): string. Dieser Vertrag stellt sicher, dass alle Fähigkeiten konsistent genutzt werden können, unabhängig von ihren spezifischen Effekten.
  • CombatLogger.php — Erstellen Sie einen CombatLogger Trait, der eine logAction(string $action): string Methode bereitstellt. Diese Methode sollte den Aktions-String mit dem Präfix "[COMBAT] " zurückgeben. Charaktere werden diesen Trait verwenden, um ihre Kampfmitteilungen konsistent zu formatieren.
  • Character.php — Binden Sie die Dateien Ability und CombatLogger ein. Erstellen Sie eine abstrakte Character Klasse, die den CombatLogger Trait verwendet. Nutzen Sie Constructor Promotion für name (string, public readonly). Fügen Sie private Eigenschaften für health (int, Startwert 100), level (int, Startwert 1) und experience (int, Startwert 0) hinzu. Implementieren Sie:
    • getHealth(): int und getLevel(): int — Getter für die privaten Eigenschaften
    • takeDamage(int $amount): void — reduziert die Gesundheit, aber niemals unter 0
    • heal(int $amount): void — erhöht die Gesundheit, aber niemals über 100
    • gainExperience(int $xp): string — fügt XP hinzu; wenn die Erfahrung 100 oder mehr erreicht, erfolgt ein Level-Up (XP auf 0 zurücksetzen, Level erhöhen, 20 HP heilen), geben Sie "{$this->name} leveled up to {$this->level}!" zurück; andernfalls geben Sie "{$this->name} gained {$xp} XP" zurück
    • isAlive(): bool — gibt true zurück, wenn die Gesundheit größer als 0 ist
    • abstract getSpecialAbility(): Ability — jeder Charaktertyp stellt seine eigene, einzigartige Fähigkeit bereit
    • attack(Character $target): string — fügt dem Ziel 10 Schaden zu, verwendet logAction(), um "[COMBAT] {$this->name} attacks {$target->name} for 10 damage" zurückzugeben
  • Warrior.php — Binden Sie die Datei Character ein. Erstellen Sie eine Klasse Warrior, die Character erweitert. Implementieren Sie getSpecialAbility() so, dass eine anonyme Klasse zurückgegeben wird, die Ability implementiert:
    • getName() gibt "Shield Bash" zurück
    • use() verursacht 25 Schaden und gibt "[COMBAT] Shield Bash hits {$target->name} for 25 damage!" zurück (verwenden Sie logAction() des Traits)
  • Mage.php — Binden Sie die Datei Character ein. Erstellen Sie eine Klasse Mage, die Character erweitert. Implementieren Sie getSpecialAbility() so, dass eine anonyme Klasse zurückgegeben wird, die Ability implementiert:
    • getName() gibt "Fireball" zurück
    • use() verursacht 35 Schaden und gibt "[COMBAT] Fireball engulfs {$target->name} for 35 damage!" zurück
  • main.php — Binden Sie die Dateien Warrior und Mage ein. Sie erhalten zwei Eingaben: Charakterdaten (JSON) und eine Sequenz von Kampfaktionen (JSON).

    JSON-Format für Charaktere:

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

    JSON-Format für Aktionen:

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

    Erstellen Sie alle Charaktere und speichern Sie diese in einem Array (Index 0, 1, etc.). Verarbeiten Sie jede Aktion:

    • "attack" — Der Charakter am Attacker-Index greift das Ziel an; geben Sie das Ergebnis aus
    • "special" — Der Charakter nutzt seine Spezialfähigkeit auf das Ziel; geben Sie das Ergebnis aus
    • "xp" — Der Charakter erhält Erfahrung; geben Sie das Ergebnis aus
    • "heal" — Der Charakter heilt um den angegebenen Betrag; geben Sie "{$character->name} healed to {$character->getHealth()} HP" aus
    • "status" — Geben Sie "{$character->name} - Level {$character->getLevel()}, HP: {$character->getHealth()}, Alive: {$alive}" aus (wobei $alive entweder 'Yes' oder 'No' ist)

    Geben Sie jedes Ergebnis in einer neuen Zeile aus.

Dieses System demonstriert, wie abstrakte Klassen gemeinsames Charakterverhalten definieren, Interfaces sicherstellen, dass Fähigkeiten einem konsistenten Vertrag folgen, Traits wiederverwendbare Logging-Funktionalität bieten und anonyme Klassen einzigartige Implementierungen von Fähigkeiten ermöglichen, ohne die Codebasis mit Klassen zu überladen, die nur einmal verwendet werden.

Probier es selbst

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

// Eingabe lesen
$charactersJson = trim(fgets(STDIN));
$actionsJson = trim(fgets(STDIN));

// JSON-Eingaben parsen
$charactersData = (array)json_decode($charactersJson, true);
$actionsData = (array)json_decode($actionsJson, true);

// TODO: Erstelle ein Array, um Charakter-Objekte zu speichern
$characters = [];

// TODO: Durchlaufe $charactersData und erstelle Warrior- oder Mage-Objekte
// basierend auf dem Feld "type", speichere sie im $characters Array

// TODO: Verarbeite jede Aktion in $actionsData
// Behandle diese Aktionstypen:
// - "attack": Charakter am Angreifer-Index greift Ziel an; Ergebnis ausgeben
// - "special": Charakter nutzt getSpecialAbility()->use() auf Ziel; Ergebnis ausgeben
// - "xp": Charakter erhält Erfahrung; Ergebnis ausgeben
// - "heal": Charakter heilt; "[name] healed to [health] HP" ausgeben
// - "status": "[name] - Level [level], HP: [health], Alive: [Yes/No]" ausgeben

?>

Alle Lektionen in Objektorientierte Programmierung