游戏角色开发
本课属于 Coddy Java 学习旅程的“面向对象编程”单元。第 86 课,共 87 课。
这个挑战将带你构建一个游戏角色成长系统,展示 OOP 在建模复杂交互实体方面的强大能力。
设计一个角色层次结构,其中基础 Character 类定义生命值、名称和等级等通用属性。Warrior、Mage 和 Archer 等专用类继承该基础类,并添加独特的能力和战斗风格。
接口在这里很适用:Attackable 可以定义战斗方法,而 Healable 负责处理恢复能力。Mage 可能会同时实现这两个接口,而 Warrior 则只专注于攻击。
可以考虑对不同的攻击行为使用 Strategy 模式,让角色能够动态切换战斗风格。State 模式可以管理角色的状态,例如正常、中毒或眩晕,这些状态会影响角色的行为。
想一想装备系统中的组合方式:角色“拥有”武器和护甲,而不是继承它们。使用枚举表示角色职业或伤害类型,并应用封装来保护属性,避免它们被无效修改。
挑战
简单让我们构建一个游戏角色开发系统,展示 OOP 在建模复杂、可交互的游戏实体方面的强大能力!你将创建一个角色层次结构,其中包含不同的战斗风格、特殊能力,以及会影响角色行为的状态系统。
你将把代码分成 7 个文件:
DamageType.java:创建一个枚举,表示游戏中的不同伤害类型。包含值PHYSICAL、MAGICAL和RANGED。添加一个私有字段description(String)、一个用于设置该字段的构造函数,以及一个 getter。物理伤害的描述应为 "brute force",魔法伤害的描述应为 "arcane energy",远程伤害的描述应为 "precision strike"。Attackable.java:创建一个定义战斗能力的接口。声明方法attack(Character target),返回一个描述攻击的 String;并声明方法getDamageType(),返回一个 DamageType。Healable.java:创建一个用于恢复能力的接口。声明方法heal(int amount),返回一个描述治疗行为的 String。Character.java:创建一个供所有游戏角色使用的抽象基类。添加以下私有字段:name(String)、health(int)、maxHealth(int)和level(int)。构造函数接收 name、maxHealth 和 level,并在初始时将 health 设置为 maxHealth。为所有字段添加 getter。添加受保护的方法setHealth(int health),确保 health 始终处于 0 到 maxHealth 之间。创建方法takeDamage(int damage),用于减少 health,并返回"[name] takes [damage] damage! Health: [health]/[maxHealth]"。添加方法isAlive(),当 health 大于 0 时返回 true。声明一个返回 String 的抽象方法getCharacterClass()。Warrior.java:创建一个继承 Character 并实现 Attackable 的类。添加私有字段strength(int)。构造函数接收 name、maxHealth、level 和 strength。实现getCharacterClass(),使其返回"Warrior"。实现getDamageType(),使其返回PHYSICAL。实现attack(Character target),使造成的伤害等于 strength 加 level,调用目标的 takeDamage 方法,并返回"[name] strikes with [damageType description] for [damage] damage!",后接换行符和 takeDamage 的结果。Mage.java:创建一个继承 Character 并同时实现 Attackable 和 Healable 的类。添加私有字段intelligence(int)和mana(int)。构造函数接收 name、maxHealth、level、intelligence 和 mana。实现getCharacterClass(),使其返回"Mage"。实现getDamageType(),使其返回MAGICAL。实现attack(Character target),使造成的伤害等于 intelligence 乘以 2,格式与 Warrior 相同。实现heal(int amount),使用 setHealth 恢复 health,并返回"[name] channels healing magic! Health: [health]/[maxHealth]"。Main.java:让你的游戏系统运行起来!你会收到一个以逗号分隔的命令字符串:CREATE_WARRIOR:name:maxHealth:level:strengthCREATE_MAGE:name:maxHealth:level:intelligence:manaATTACK:attackerName:targetNameHEAL:mageName:amountSTATUS:characterName
维护一个角色集合。处理每条命令并打印以下内容:
- CREATE_WARRIOR/CREATE_MAGE:
[name] the [characterClass] joins the battle! - ATTACK:打印攻击结果(attack 方法返回的 String)
- HEAL:打印治疗结果;如果角色不是 Mage,则打印
[name] cannot heal - STATUS:
[name] ([characterClass]) - Level [level] - Health: [health]/[maxHealth] - [Alive/Defeated]
处理完所有命令后,打印
--- Battle Summary ---,然后打印每个角色的状态。
你会收到一个输入:以逗号分隔的命令字符串。
例如,输入为 CREATE_WARRIOR:Thorin:100:5:15,CREATE_MAGE:Gandalf:80:7:12:50,ATTACK:Thorin:Gandalf,HEAL:Gandalf:25,STATUS:Gandalf 时,输出将为:
Thorin the Warrior joins the battle!
Gandalf the Mage joins the battle!
Thorin strikes with brute force for 20 damage!
Gandalf takes 20 damage! Health: 60/80
Gandalf channels healing magic! Health: 80/80
Gandalf (Mage) - Level 7 - Health: 80/80 - Alive
--- Battle Summary ---
Thorin (Warrior) - Level 5 - Health: 100/100 - Alive
Gandalf (Mage) - Level 7 - Health: 80/80 - Alive这个挑战将继承(Character 层次结构)、多个接口的实现(Mage 同时实现 Attackable 和 Healable)、带有方法的枚举(DamageType)、多态(统一处理不同类型的角色)和封装(受保护的 health 管理)结合起来,构建出一个引人入胜的游戏系统!
亲手试试
import java.util.Scanner;
import java.util.HashMap;
import java.util.Map;
import java.util.LinkedHashMap;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String input = scanner.nextLine();
// TODO: 用集合管理角色(LinkedHashMap 保留插入顺序)
// LinkedHashMap<String, Character> characters = new LinkedHashMap<>();
// TODO: 按逗号拆分 input,得到各条命令
// String[] commands = input.split(",");
// TODO: 处理每条命令:
// - CREATE_WARRIOR:name:maxHealth:level:strength
// 打印:"[name] the Warrior joins the battle!"
//
// - CREATE_MAGE:name:maxHealth:level:intelligence:mana
// 打印:"[name] the Mage joins the battle!"
//
// - ATTACK:attackerName:targetName
// 打印 attack 方法返回的攻击结果
//
// - HEAL:mageName:amount
// 打印治疗结果;如果不是 Mage,则打印 "[name] cannot heal"
//
// - STATUS:characterName
// 打印:"[name] ([characterClass]) - Level [level] - Health: [health]/[maxHealth] - [Alive/Defeated]"
// TODO:处理完所有命令后,打印 "--- Battle Summary ---"
// 然后打印每个角色的状态
}
}
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: Java 在线编译器