Menu
Coddy logo textTech

ゲームキャラクター開発

CoddyのJavaジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 86/87。

このチャレンジでは、複雑でインタラクティブなエンティティのモデル化におけるOOPの力を示す、ゲームキャラクター開発システムを構築します。

Character クラスの base が、health、name、level などの共通属性を定義するキャラクター階層を設計します。WarriorMageArcher などの特殊化されたクラスは、固有の abilities と combat スタイルでこの base を拡張します。

ここではインターフェースが自然に機能します。Attackable は戦闘メソッドを定義し、Healable は回復能力を扱うことができます。Mage は両方を実装する一方で、Warrior は攻撃だけに集中するかもしれません。

異なる攻撃動作に Strategy パターンを使用することを検討し、キャラクターが戦闘スタイルを動的に切り替えられるようにします。State パターンを使えば、動作に影響を与える通常、毒状態、スタン状態などのキャラクターの状態を管理できます。

character が武器や防具を継承するのではなく、それらを「持つ」装備システムについて考えてみましょう。character class や damage の種類には enum を使用し、カプセル化を適用して、無効な変更からステータスを保護します。

challenge icon

チャレンジ

簡単

OOPによる複雑でインタラクティブなゲームエンティティのモデル化の力を示す、ゲーム Character Development システムを構築しましょう!異なる combat スタイル、特殊な abilities、そして Character の振る舞いに影響する state システムを備えた Character hierarchy を作成します。

コードを7つのファイルに整理します。

  • DamageType.java: ゲーム内のさまざまな damage の種類を表す enum を作成します。PHYSICALMAGICALRANGED の値を含めます。private フィールド description(String)、それを設定する constructor、および getter を追加します。Physical damage の description は "brute force"、magical は "arcane energy"、ranged は "precision strike" にします。
  • Attackable.java: combat capabilities を定義する interface を作成します。攻撃を説明する String を返す attack(Character target) メソッドと、DamageType を返す getDamageType() メソッドを宣言します。
  • Healable.java: 回復 abilities のための interface を作成します。回復アクションを説明する String を返す heal(int amount) メソッドを宣言します。
  • Character.java: すべてのゲーム Character の abstract な base class を作成します。name(String)、health(int)、maxHealth(int)、level(int)の private フィールドを含めます。constructor は name、maxHealth、level を受け取り、最初に health を maxHealth と等しく設定します。すべてのフィールドの getter を含めます。health が 0 以上 maxHealth 以下に保たれるようにする protected メソッド setHealth(int health) を追加します。health を減少させ、"[name] takes [damage] damage! Health: [health]/[maxHealth]" を返す takeDamage(int damage) メソッドを作成します。health が 0 より大きい場合に true を返す isAlive() メソッドを追加します。String を返す abstract メソッド getCharacterClass() を宣言します。
  • Warrior.java: Character を拡張し、Attackable を実装する class を作成します。strength(int)の private フィールドを追加します。constructor は name、maxHealth、level、strength を受け取ります。getCharacterClass()"Warrior" を返すように実装します。getDamageType()PHYSICAL を返すように実装します。attack(Character target) は strength と level の合計に等しい damage を与え、target の takeDamage メソッドを呼び出し、"[name] strikes with [damageType description] for [damage] damage!" に改行と takeDamage の結果を続けたものを返すように実装します。
  • Mage.java: Character を拡張し、Attackable と Healable の両方を実装する class を作成します。intelligence(int)と mana(int)の private フィールドを追加します。constructor は name、maxHealth、level、intelligence、mana を受け取ります。getCharacterClass()"Mage" を返すように実装します。getDamageType()MAGICAL を返すように実装します。attack(Character target) は intelligence の 2 倍に等しい damage を与え、Warrior と同じ形式にします。heal(int amount) は setHealth を使用して health を回復し、"[name] channels healing magic! Health: [health]/[maxHealth]" を返すように実装します。
  • Main.java: ゲームシステムを動かしましょう!カンマ区切りの command 文字列を受け取ります。
    • CREATE_WARRIOR:name:maxHealth:level:strength
    • CREATE_MAGE:name:maxHealth:level:intelligence:mana
    • ATTACK:attackerName:targetName
    • HEAL:mageName:amount
    • STATUS:characterName

    Character の collection を管理します。各 command を処理し、次の内容を出力します。

    • CREATE_WARRIOR/CREATE_MAGE: [name] the [characterClass] joins the battle!
    • ATTACK: 攻撃結果(attack メソッドが返す String)を出力します
    • HEAL: heal の結果を出力します。Character が Mage でない場合は [name] cannot heal を出力します
    • STATUS: [name] ([characterClass]) - Level [level] - Health: [health]/[maxHealth] - [Alive/Defeated]

    すべての command の後に --- Battle Summary --- を出力し、その後に各 Character の status を出力します。

入力として1つのカンマ区切りの command 文字列を受け取ります。

たとえば、入力が 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

この challenge では、継承(Character hierarchy)、複数の interface 実装(Mage は Attackable と Healable の両方を実装)、メソッドを持つ enum(DamageType)、polymorphism(異なる Character の種類を統一的に扱うこと)、encapsulation(protected による 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: 入力をカンマで分割して個々のコマンドを取得する
        // String[] commands = input.split(",");
        
        // TODO: 各コマンドを処理する:
        // - CREATE_WARRIOR:name:maxHealth:level:strength
        //   Print: "[name] the Warrior joins the battle!"
        // 
        // - CREATE_MAGE:name:maxHealth:level:intelligence:mana
        //   Print: "[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: After all commands, print "--- Battle Summary ---"
        // 次に各キャラクターのステータスを出力する
    }
}
quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

オブジェクト指向プログラミングのすべてのレッスン

自分で練習してみよう: Javaオンラインコンパイラ