Menu
CoddyTech

游戏角色开发

本课属于 Coddy PHP 学习旅程的“面向对象编程”单元。第 90 课,共 91 课。

challenge icon

挑战

简单

让我们构建一个游戏角色成长系统,让不同角色职业使用独特技能进行战斗。你将创建一个包含经验值和升级系统的角色层级结构,展示继承、接口、trait 和封装如何在游戏中协同工作。

你将把代码分布在 6 个文件中:

  • Ability.php:定义一个 Ability 接口,包含两个方法:getName(): string 和 use(Character $target): string。这个契约可以确保所有技能都能以一致的方式使用,而不受其具体效果影响。
  • CombatLogger.php:创建一个 CombatLogger trait,其中提供一个 logAction(string $action): string 方法。此方法应返回前缀为 "[COMBAT] " 的动作字符串。角色将使用这个 trait,以一致的格式生成战斗消息。
  • Character.php:引入 Ability 和 CombatLogger 文件。创建一个使用 CombatLogger trait 的抽象 Character 类。使用构造函数属性提升来声明 name(string,public readonly)。添加私有属性:health(int,初始值为 100)、level(int,初始值为 1)和 experience(int,初始值为 0)。实现以下内容:
    • getHealth(): int 和 getLevel(): int:获取私有属性的 getter
    • takeDamage(int $amount): void:减少生命值,但不会低于 0
    • heal(int $amount): void:增加生命值,但不会高于 100
    • gainExperience(int $xp): string:增加经验值;如果经验值达到或超过 100,则升级(将经验值重置为 0,等级加 1,恢复 20 HP),并返回 "[name] leveled up to [level]!";否则返回 "[name] gained [xp] XP"
    • isAlive(): bool:如果生命值大于 0,则返回 true
    • abstract getSpecialAbility(): Ability:每种角色类型都提供自己的独特技能
    • attack(Character $target): string:对目标造成 10 点伤害,并使用 logAction() 返回 "[COMBAT] [name] attacks [target name] for 10 damage"
  • Warrior.php:引入 Character 文件。创建一个继承 Character 的 Warrior 类。实现 getSpecialAbility(),使其返回一个实现 Ability 的匿名类:
    • getName() 返回 "Shield Bash"
    • use() 造成 25 点伤害,并返回 "[COMBAT] Shield Bash hits [target name] for 25 damage!"(使用 trait 的 logAction())
  • Mage.php:引入 Character 文件。创建一个继承 Character 的 Mage 类。实现 getSpecialAbility(),使其返回一个实现 Ability 的匿名类:
    • getName() 返回 "Fireball"
    • use() 造成 35 点伤害,并返回 "[COMBAT] Fireball engulfs [target name] for 35 damage!"
  • main.php:引入 Warrior 和 Mage 文件。你将收到两个输入:角色数据(JSON)和一系列战斗动作(JSON)。

    角色 JSON 格式:

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

    动作 JSON 格式:

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

    创建所有角色,并将它们存储在一个数组中(索引为 0、1 等)。处理每个动作:

    • "attack":索引为 attacker 的角色攻击目标;打印结果
    • "special":角色对目标使用特殊技能;打印结果
    • "xp":角色获得经验值;打印结果
    • "heal":角色按给定数量恢复生命值;打印 "[name] healed to [health] HP"
    • "status":打印 "[name] - Level [level], HP: [health], Alive: [Yes/No]"

    将每个结果打印在新的一行。

这个系统展示了抽象类如何定义角色的共同行为,接口如何确保技能遵循一致的契约,trait 如何提供可复用的日志记录功能,以及匿名类如何创建独特的技能实现,而不让只使用一次的类弄乱你的代码库。

亲手试试

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

// 读取输入
$charactersJson = trim(fgets(STDIN));
$actionsJson = trim(fgets(STDIN));

// 解析 JSON 输入
$charactersData = (array)json_decode($charactersJson, true);
$actionsData = (array)json_decode($actionsJson, true);

// TODO:创建一个数组来存储角色对象
$characters = [];

// TODO:遍历 $charactersData,创建 Warrior 或 Mage 对象
// 根据 "type" 字段,将它们存入 $characters 数组

// TODO:处理 $actionsData 中的每个操作
// 处理以下操作类型:
// “attack”:攻击者索引对应的角色攻击目标;输出结果
// “special”:角色对目标使用 getSpecialAbility()->use();输出结果
// “xp”:角色获得经验值;输出结果
// “heal”:角色恢复生命值;输出 "[name] healed to [health] HP"
// “status”:输出 "[name] - Level [level], HP: [health], Alive: [Yes/No]"

?>

面向对象编程中的所有课

自己练习: PHP 在线编译器