Menu
Coddy logo textTech

Entwicklung einer Spielfigur

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

challenge icon

Aufgabe

Einfach

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

Du organisierst deinen Code über sechs Dateien:

  • Ability.php: Definiere ein Ability-Interface mit zwei Methoden: getName(): string und use(Character $target): string. Dieser Vertrag stellt sicher, dass alle Fähigkeiten unabhängig von ihren spezifischen Effekten einheitlich verwendet werden können.
  • CombatLogger.php: Erstelle ein CombatLogger-Trait, das eine logAction(string $action): string-Methode bereitstellt. Diese Methode soll den Aktions-String mit dem Präfix "[COMBAT] " zurückgeben. Charaktere verwenden dieses Trait, um ihre Kampfnachrichten einheitlich zu formatieren.
  • Character.php: Binde die Dateien Ability und CombatLogger ein. Erstelle eine abstrakte Character-Klasse, die das CombatLogger-Trait verwendet. Verwende Constructor Promotion für name (string, public readonly). Füge private Eigenschaften für health (int, beginnend bei 100), level (int, beginnend bei 1) und experience (int, beginnend bei 0) hinzu. Implementiere:
    • 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, steigt der Charakter ein Level auf (XP auf 0 zurücksetzen, Level erhöhen, 20 HP heilen), und "[name] leveled up to [level]!" wird zurückgegeben; andernfalls wird "[name] gained [xp] XP" zurückgegeben
    • isAlive(): bool: gibt true zurück, wenn die Gesundheit größer als 0 ist
    • abstract getSpecialAbility(): Ability: jeder Charaktertyp stellt seine einzigartige Fähigkeit bereit
    • attack(Character $target): string: verursacht beim Ziel 10 Schaden und verwendet logAction(), um "[COMBAT] [name] attacks [target name] for 10 damage" zurückzugeben
  • Warrior.php: Binde die Character-Datei ein. Erstelle eine Warrior-Klasse, die Character erweitert. Implementiere getSpecialAbility(), sodass 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 (verwende das logAction() des Traits)
  • Mage.php: Binde die Character-Datei ein. Erstelle eine Mage-Klasse, die Character erweitert. Implementiere getSpecialAbility(), sodass 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: Binde die Warrior- und Mage-Dateien ein. Du erhältst zwei Eingaben: Charakterdaten (JSON) und eine Abfolge von Kampfaktionen (JSON).

    JSON-Format der Charaktere:

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

    JSON-Format der Aktionen:

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

    Erstelle alle Charaktere und speichere sie in einem Array (Index 0, 1 usw.). Verarbeite jede Aktion:

    • "attack": Der Charakter am Angreifer-Index greift das Ziel an; gib das Ergebnis aus
    • "special": Der Charakter verwendet seine Spezialfähigkeit auf das Ziel; gib das Ergebnis aus
    • "xp": Der Charakter sammelt Erfahrung; gib das Ergebnis aus
    • "heal": Der Charakter heilt sich um den angegebenen Betrag; gib "[name] healed to [health] HP" aus
    • "status": Gib "[name] - Level [level], HP: [health], Alive: [Yes/No]" aus

    Gib jedes Ergebnis in einer neuen Zeile aus.

Dieses System zeigt, wie abstrakte Klassen gemeinsames Charakterverhalten definieren, Interfaces sicherstellen, dass Fähigkeiten einem einheitlichen Vertrag folgen, Traits wiederverwendbare Protokollierungsfunktionen bereitstellen und anonyme Klassen einzigartige Fähigkeitsimplementierungen erstellen, ohne deine Codebasis mit nur einmal verwendeten Klassen zu überladen.

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 zum Speichern von Charakterobjekten
$characters = [];

// TODO: Durchlaufe $charactersData und erstelle Warrior- oder Mage-Objekte
// basierend auf dem "type"-Feld, 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 verwendet getSpecialAbility()->use() auf das Ziel; Ergebnis ausgeben
// - "xp": Charakter erhält Erfahrung; Ergebnis ausgeben
// - "heal": Charakter heilt; gib "[name] healed to [health] HP" aus
// - "status": Gib "[name] - Level [level], HP: [health], Alive: [Yes/No]" aus

?>

Alle Lektionen in Objektorientierte Programmierung

Übe selbstständig: Online-PHP-Compiler