Menu
CoddyTech

游戏角色组件

本课属于 Coddy C# 学习旅程的“面向对象编程”单元。第 69 课,共 70 课。

challenge icon

挑战

简单

让我们使用基于组件的架构模式来构建一个游戏角色系统!你不再创建僵化的继承层次结构,而是通过附加独立组件来组合角色,每个组件负责处理特定行为。这种灵活的方法在游戏开发中得到了广泛应用。

你需要将代码组织在 5 个文件中:

  • IComponent.cs:在 Game.Components 命名空间中定义 IComponent 接口。每个组件都必须有一个 Update() 方法,用于输出该组件正在执行的操作。
  • HealthComponent.cs:创建一个实现 IComponent 的 HealthComponent 类。它应跟踪当前生命值和最大生命值,并提供 TakeDamage(int amount) 和 Heal(int amount) 方法。生命值不能低于 0,也不能超过最大值。添加一个 event Action<int> HealthChanged 事件,每当生命值发生变化时触发,并传递新的生命值。Update() 方法应输出当前生命值状态。
  • InventoryComponent.cs:创建一个实现 IComponent 的 InventoryComponent 类。它管理一个物品名称列表,并提供 AddItem(string item) 和 RemoveItem(string item) 方法。RemoveItem(string item) 返回一个用于表示操作是否成功的 bool 值。Update() 方法应输出物品栏内容。
  • Character.cs:在 Game 命名空间中创建一个 Character 类,用于保存组件集合。你的角色需要有一个 Name 属性,以及以下方法:
    • AddComponent(IComponent component):将组件附加到角色上
    • GetComponent<T>(),其中 T : IComponent:返回第一个类型为 T 的组件;如果找不到,则返回 null
    • UpdateAll():对每个已附加的组件调用 Update()
  • Program.cs:通过创建角色、附加组件并处理命令,将所有内容组合起来。

你将收到以下输入:

  • 角色名称
  • HealthComponent 的初始最大生命值
  • 要处理的命令数量
  • 对于每条命令:操作及其相关数据

命令格式:

damage
{amount}

heal
{amount}

add_item
{itemName}

remove_item
{itemName}

update

输出格式:

  • 生命值发生变化时(通过事件):Health changed: {newHealth}
  • 添加物品时:Added: {itemName}
  • 移除物品时:Removed: {itemName} 或 Item not found: {itemName}
  • HealthComponent 的 Update():Health: {current}/{max}
  • InventoryComponent 的 Update():Inventory: {item1}, {item2}, ... 或 Inventory: empty

例如,输入如下:

Hero
100
7
add_item
Sword
add_item
Shield
damage
30
heal
10
remove_item
Potion
remove_item
Sword
update

输出应为:

Added: Sword
Added: Shield
Health changed: 70
Health changed: 80
Item not found: Potion
Removed: Sword
Health: 80/100
Inventory: Shield

注意,角色并不继承任何特殊类,而只是保存提供各种行为的组件。GetComponent<T>() 方法使用泛型来实现类型安全的检索,而事件会在生命值发生变化时发出通知。这种组合方式让你可以自由搭配各种组件!

亲手试试

using System;
using Game;
using Game.Components;

class Program
{
    public static void Main(string[] args)
    {
        // 读取角色名称
        string characterName = Console.ReadLine();
        
        // 读取初始最大生命值
        int maxHealth = Convert.ToInt32(Console.ReadLine());
        
        // 读取命令数量
        int numCommands = Convert.ToInt32(Console.ReadLine());
        
        // TODO: 用给定名称创建一个 Character
        
        // TODO: 用 maxHealth 创建 HealthComponent,并创建 InventoryComponent
        
        // TODO: 订阅 HealthChanged 事件,并输出:Health changed: {newHealth}
        
        // TODO: 将这两个组件添加到角色中
        
        // TODO: 处理每条命令
        for (int i = 0; i < numCommands; i++)
        {
            string command = Console.ReadLine();
            
            // TODO: 处理每种命令类型:
            // - "damage":读取数值,在生命值组件上调用 TakeDamage
            // - "heal":读取数值,在生命值组件上调用 Heal
            // - "add_item":读取物品名称,在物品栏组件上调用 AddItem
            // - "remove_item":读取物品名称,调用背包组件的 RemoveItem 方法
            // - "update":调用角色的 UpdateAll 方法
        }
    }
}

面向对象编程中的所有课

自己练习: C# 在线编译器