ターン制バトルゲームから学ぶオブジェクト指向
C#の基礎、またオブジェクト指向からポリモーフィズムを学んだ方向けの学習用サンプルになります
ターン制の戦士と魔導士のバトルのイメージで眺めてください
コード
Character warrior = new Warrior(100, 20, 10);
Character mage = new Mage(80, 10, 15);
Character[] characters = { warrior, mage };
Console.WriteLine("バトル開始");
int turn = 0;
while (warrior.CurrentHP > 0 && mage.CurrentHP > 0)
{
Console.WriteLine("ターン " + (turn + 1));
Character attacker = characters[turn % 2];
Character defender = characters[(turn + 1) % 2];
int damage = attacker.Strength + attacker.GetAdditionalStat() - defender.Defense;
defender.TakeDamage(damage);
Console.WriteLine(attacker.GetType().Name + "が" + defender.GetType().Name + "に攻撃!" + damage + "のダメージ");
Console.WriteLine(defender.GetType().Name + "のHPは、残り" + defender.CurrentHP + "です");
turn++;
}
Console.WriteLine("バトル終了");
Console.WriteLine(warrior.CurrentHP > 0 ? "戦士の勝ち!" : "魔導士の勝ち!");
abstract class Character
{
public int MaxHP { get; set; }
public int CurrentHP { get; set; }
public int Strength { get; set; }
public int Defense { get; set; }
public Character(int maxHP, int strength, int defense)
{
MaxHP = maxHP;
CurrentHP = MaxHP;
Strength = strength;
Defense = defense;
}
public void TakeDamage(int damage)
{
CurrentHP -= damage;
if (CurrentHP < 0)
{
CurrentHP = 0;
}
}
public abstract int GetAdditionalStat();
}
class Warrior : Character
{
public Warrior(int maxHP, int strength, int defense) : base(maxHP, strength, defense) { }
public override int GetAdditionalStat()
{
return Strength / 2;
}
}
class Mage : Character
{
public Mage(int maxHP, int strength, int defense) : base(maxHP, strength, defense) { }
public override int GetAdditionalStat()
{
return Defense / 2;
}
}
実行結果
バトル開始
ターン 1
WarriorがMageに攻撃!15のダメージ
MageのHPは、残り65です
ターン 2
MageがWarriorに攻撃!7のダメージ
WarriorのHPは、残り93です
ターン 3
WarriorがMageに攻撃!15のダメージ
MageのHPは、残り50です
ターン 4
MageがWarriorに攻撃!7のダメージ
WarriorのHPは、残り86です
ターン 5
WarriorがMageに攻撃!15のダメージ
MageのHPは、残り35です
ターン 6
MageがWarriorに攻撃!7のダメージ
WarriorのHPは、残り79です
ターン 7
WarriorがMageに攻撃!15のダメージ
MageのHPは、残り20です
ターン 8
MageがWarriorに攻撃!7のダメージ
WarriorのHPは、残り72です
ターン 9
WarriorがMageに攻撃!15のダメージ
MageのHPは、残り5です
ターン 10
MageがWarriorに攻撃!7のダメージ
WarriorのHPは、残り65です
ターン 11
WarriorがMageに攻撃!15のダメージ
MageのHPは、残り0です
バトル終了
戦士の勝ち!
解説
全体の流れ
このコードは、C#によるターン制バトルシミュレーションのプログラムです。
- キャラクタークラスは抽象クラスとして定義され、キャラクターのステータス(MaxHP, CurrentHP, Strength, Defense)のプロパティと、ダメージを受ける(TakeDamage)、追加のスタットを取得する(GetAdditionalStat)ためのメソッドを保持しています。
- WarriorクラスはCharacterクラスを継承し、Strength / 2を返すように追加ステータスを実装しています。
- MageクラスはCharacterクラスを継承しており、Defense / 2を返す追加ステータスを実装しています。
- Warrior変数には、MaxHP 100、Strength 20、Defense 10を持つWarriorクラスのインスタンスが格納されます。
- mage変数にはMageクラスのインスタンスが格納され、MaxHP80、Strength10、Defense15となります。
- 文字配列には戦士変数と魔道士変数が格納されます。
- turn 変数はターン数を表します.
- whileループの中では、戦士の現在HPと魔導士の現在HPがともに0以上の間、処理が継続されます。
- 毎ターン、attacker変数には攻撃側のキャラクターが、defender変数には防御側のキャラクターが格納されます。
- ダメージ変数には、攻撃側の体力+追加ステータス-防御側の防御力が格納されます。
- 防御側のCurrentHPはダメージ量だけ減少します。
- コンソールには攻撃メッセージと各キャラクターのHPの状態が表示されます。
- ターン変数が1つインクリメントされる。
- whileループ終了後、勝者(戦士のCurrentHP>0)がコンソールに表示される。
コード解説
Character warrior = new Warrior(100, 20, 10);
Character mage = new Mage(80, 10, 15);
Character[] characters = { warrior, mage };
Console.WriteLine("バトル開始");
この部分は、2つのキャラクターオブジェクト(戦士、魔導士)を作成し、それらをキャラクター配列に格納しています。また、「バトル開始」というメッセージをコンソールに表示します。
Character warrior = new Warrior(100, 20, 10);
:ここでは、Warrior
クラスから新しい戦士オブジェクトを作成し、Character
型の変数warrior
に代入します。引数100, 20, 10
は、戦士の最大HP、攻撃力、防御力を表します。Character mage = new Mage(80, 10, 15);
:ここでは、Mage
クラスから新しい魔法使いオブジェクトを作成し、Character
型の変数mage
に代入します。引数80, 10, 15
は、魔法使いの最大HP、攻撃力、防御力を表します。Character[] characters = { warrior, mage };
:ここでは、作成した戦士と魔法使いオブジェクトを含む配列を作成します。Console.WriteLine("バトル開始");
:ここでは、「バトル開始」というメッセージをコンソールに表示します。
int turn = 0;
while (warrior.CurrentHP > 0 && mage.CurrentHP > 0)
{
Console.WriteLine("ターン " + (turn + 1));
Character attacker = characters[turn % 2];
Character defender = characters[(turn + 1) % 2];
int damage = attacker.Strength + attacker.GetAdditionalStat() - defender.Defense;
defender.TakeDamage(damage);
Console.WriteLine(attacker.GetType().Name + "が" + defender.GetType().Name + "に攻撃!" + damage + "のダメージ");
Console.WriteLine(defender.GetType().Name + "のHPは、残り" + defender.CurrentHP + "です");
turn++;
}
このコードは、ターン制のバトルシミュレーションを行っています。
- 変数
turn
が宣言され、初期値は0
となっています。 - 以下の処理が、
warrior
キャラクターのCurrentHP
が0
以上、かつmage
キャラクターのCurrentHP
が0
以上の間繰り返されます。- 現在のターン番号を表示します。
- 攻撃するキャラクター
attacker
と防御するキャラクターdefender
が決定されます。キャラクターの順番は、配列characters
内のインデックスを切り替えて決定されます。 damage
変数に攻撃力に加えて、追加のステータス値を引いた値から防御力を引いた値が代入されます。この計算は、attacker
のStrength
プロパティとGetAdditionalStat()
メソッド、defender
のDefense
プロパティを利用しています。defender
がdamage
分のダメージを受けます。このダメージ処理は、TakeDamage()
メソッドを利用しています。- 攻撃者と被害者のキャラクター名と、与えたダメージと、残りのHPが表示されます。
turn
変数に1を加えます。
- どちらかのキャラクターのHPが0以下になったら、バトルは終了します。そして、生き残ったキャラクターの名前が表示されます。
Console.WriteLine("バトル終了");
Console.WriteLine(warrior.CurrentHP > 0 ? "戦士の勝ち!" : "魔導士の勝ち!");
このコードは、「バトル終了」という文字列を出力し、その後、warrior
オブジェクトのCurrentHP
が0より大きい場合に「戦士の勝ち!」、0以下の場合に「魔導士の勝ち!」という文字列を出力するものです。ここで、この文字列の出力結果は、勝者を示すものになります。
abstract class Character
{
public int MaxHP { get; set; }
public int CurrentHP { get; set; }
public int Strength { get; set; }
public int Defense { get; set; }
public Character(int maxHP, int strength, int defense)
{
MaxHP = maxHP;
CurrentHP = MaxHP;
Strength = strength;
Defense = defense;
}
public void TakeDamage(int damage)
{
CurrentHP -= damage;
if (CurrentHP < 0)
{
CurrentHP = 0;
}
}
public abstract int GetAdditionalStat();
}
このコードは、RPGゲームのキャラクターを表す抽象クラスCharacter
を定義しています。
このクラスは、以下のフィールドを定義しています:
MaxHP
: キャラクターの最大HPCurrentHP
: キャラクターの現在のHPStrength
: キャラクターの戦闘力Defense
: キャラクターの防御力
また、以下のメソッドを定義しています:
TakeDamage
: 与えられたダメージを受ける。現在のHPが0未満にならないように調整されます。GetAdditionalStat
: 追加のステータス値を取得するための抽象メソッド。このメソッドは継承先でオーバーライドされます。
このクラスは抽象クラスであり、抽象メソッドを1つ持っています。抽象クラスは継承して使用することができ、継承先で抽象メソッドを実装する必要があります。
class Warrior : Character
{
public Warrior(int maxHP, int strength, int defense) : base(maxHP, strength, defense) { }
public override int GetAdditionalStat()
{
return Strength / 2;
}
}
class Mage : Character
{
public Mage(int maxHP, int strength, int defense) : base(maxHP, strength, defense) { }
public override int GetAdditionalStat()
{
return Defense / 2;
}
}
このコードは、「Warrior」クラスと「Mage」クラスを定義しています。これらのクラスは「Character」クラスを継承しています。「Character」クラスは抽象クラスであり、「MaxHP」、「CurrentHP」、「Strength」、「Defense」というプロパティを持っています。また、「TakeDamage」と「GetAdditionalStat」という抽象メソッドも定義されています。
「Warrior」クラスは「Character」クラスを継承しています。「Warrior」クラスは「MaxHP」、「Strength」、「Defense」というパラメータを受け取り、「Character」クラスのコンストラクタを呼び出して初期化します。「Warrior」クラスは「GetAdditionalStat」メソッドをオーバーライドして、「Strength」プロパティを2で割った値を返します。
「Mage」クラスも「Character」クラスを継承しています。「Mage」クラスは「MaxHP」、「Strength」、「Defense」というパラメータを受け取り、「Character」クラスのコンストラクタを呼び出して初期化します。「Mage」クラスは「GetAdditionalStat」メソッドをオーバーライドして、「Defense」プロパティを2で割った値を返します。
ディスカッション
コメント一覧
まだ、コメントがありません