Spielcharakter-Entwicklung
Teil des Abschnitts Objektorientierte Programmierung der PHP-Journey von Coddy — Lektion 90 von 91.
Aufgabe
EinfachLassen 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 einAbilityInterface mit zwei Methoden:getName(): stringunduse(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 einenCombatLoggerTrait, der einelogAction(string $action): stringMethode 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 abstrakteCharacterKlasse, die denCombatLoggerTrait verwendet. Nutzen Sie Constructor Promotion fürname(string, public readonly). Fügen Sie private Eigenschaften fürhealth(int, Startwert 100),level(int, Startwert 1) undexperience(int, Startwert 0) hinzu. Implementieren Sie:getHealth(): intundgetLevel(): int— Getter für die privaten EigenschaftentakeDamage(int $amount): void— reduziert die Gesundheit, aber niemals unter 0heal(int $amount): void— erhöht die Gesundheit, aber niemals über 100gainExperience(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ückisAlive(): bool— gibt true zurück, wenn die Gesundheit größer als 0 istabstract getSpecialAbility(): Ability— jeder Charaktertyp stellt seine eigene, einzigartige Fähigkeit bereitattack(Character $target): string— fügt dem Ziel 10 Schaden zu, verwendetlogAction(), um"[COMBAT] {$this->name} attacks {$target->name} for 10 damage"zurückzugeben
Warrior.php— Binden Sie die Datei Character ein. Erstellen Sie eine KlasseWarrior, dieCharactererweitert. Implementieren SiegetSpecialAbility()so, dass eine anonyme Klasse zurückgegeben wird, dieAbilityimplementiert:getName()gibt"Shield Bash"zurückuse()verursacht 25 Schaden und gibt"[COMBAT] Shield Bash hits {$target->name} for 25 damage!"zurück (verwenden SielogAction()des Traits)
Mage.php— Binden Sie die Datei Character ein. Erstellen Sie eine KlasseMage, dieCharactererweitert. Implementieren SiegetSpecialAbility()so, dass eine anonyme Klasse zurückgegeben wird, dieAbilityimplementiert:getName()gibt"Fireball"zurückuse()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$aliveentweder'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
1Grundlagen der OOP
Externe DateienEinführung in die OOPKlassen vs. ObjekteDas $this-SchlüsselwortMethodenEigenschaftenKonstruktor (__construct)Destruktor (__destruct)Rückblick - Einfacher Taschenrechner4Vererbung
Grundlagen der VererbungDas parent:: SchlüsselwortMethoden überschreibenDas final SchlüsselwortAbstrakte KlassenZusammenfassung – Mitarbeiter-Hierarchie7Kapselung
Public, Protected, PrivateZugriffsmodifikatoren im DetailGetter und SetterInformation HidingConstructor Promotion (8.0)Zusammenfassung – Studentenverwaltungssystem2Namensräume & Autoloading
Einführung in NamensräumeDas use-SchlüsselwortPSR-4 Autoloading-StandardComposer AutoloaderZusammenfassung – Organisiertes Projekt5Interfaces & Verträge
Einführung in InterfacesInterfaces implementierenMehrfache Interface-ImplementierungInterface vs. Abstrakte KlasseType Hinting mit InterfacesZusammenfassung – Formen-Rechner8Magische Methoden
Einführung in magische Methoden__toString & __debugInfo__get, __set, __isset, __unset__call & __callStatic__clone & Objekt-Klonen__serialize & __unserializeZusammenfassung - Eigene Collection11Typsystem & Fehlerbehandlung
TypdeklarationenNullable-TypenUnion- & Intersection-TypenException-KlassenEigene Exception-HierarchieTry, Catch, FinallyZusammenfassung - Formular-Validator14Projekt: Bibliotheksverwaltung
ProjektübersichtBuch- und Benutzerklassen3Klasseneigenschaften
Instanz- vs. statische EigenschaftenKonstanten in KlassenStatische Methoden & EigenschaftenPrivate & geschützte EigenschaftenReadonly-Eigenschaften (PHP 8.1)Zusammenfassung – Bankkonto-Manager6Polymorphismus
Method Overriding erneut betrachtetPolymorphismus über InterfacesType Hinting & Union TypesLate Static BindingZusammenfassung – Payment Processor9Traits
Einführung in TraitsVerwendung mehrerer TraitsKonfliktlösung bei TraitsAbstrakte Methoden in TraitsTraits vs. Vererbung12Entwurfsmuster Teil 1
Einführung in EntwurfsmusterSingleton-MusterFactory-MusterObserver-MusterStrategy-Muster15Abschlussherausforderungen
E-Learning-PlattformBanksystemSpielcharakter-EntwicklungFahrzeugvermietung