inheritance - Your object's family tree - design, class model, implemention
Head First C Sharp: A Learner’s Guide to Real-World Programming with C Sharp and .NET (Andrew Stellman(著)、Jennifer Greene(著)、O’Reilly Media)の Chapter 6(inheritance - Your object’s family tree)、p.311(Exercise)の解答を求めてみる。
コード
Program.cs
Random random = new Random();
int RollDice(int numberOfRolls)
{
int roll = 0;
for (int i = 0; i < numberOfRolls; i++)
{
roll += random.Next(1, 7);
}
return roll;
}
SwordDamage swordDamage = new SwordDamage(RollDice(3));
ArrowDamage arrowDamage = new ArrowDamage(RollDice(1));
while (true)
{
Console.Write("0 fur no magic/flaming, 1 for magic, 2 for flaming, 3 for both, anything else to quit: ");
char key = Console.ReadKey(false).KeyChar;
if (key < '0' || '3' < key)
{
break;
}
Console.Write("\nS for sword, A for arrow, anything else to quit: ");
char weaponKey = Char.ToUpper(Console.ReadKey().KeyChar);
switch (weaponKey)
{
case 'S':
swordDamage.Roll = RollDice(3);
swordDamage.Magic = key == '1' || key == '3';
swordDamage.Flaming = key == '2' || key == '3';
Console.WriteLine($"\nRolled {swordDamage.Roll} for {swordDamage.Damage} HP\n");
break;
case 'A':
arrowDamage.Roll = RollDice(1);
arrowDamage.Magic = key == '1' || key == '3';
arrowDamage.Flaming = key == '2' || key == '3';
Console.WriteLine($"\nRolled {arrowDamage.Roll} for {arrowDamage.Damage} HP\n");
break;
default:
return;
}
}
class WeaponDamage
{
private int roll;
public int Roll
{
get { return roll; }
set
{
roll = value;
CalculateDamage();
}
}
private bool magic;
public bool Magic
{
get { return magic; }
set
{
magic = value;
CalculateDamage();
}
}
private bool flaming;
public bool Flaming
{
get { return flaming; }
set
{
flaming = value;
CalculateDamage();
}
}
public int Damage { get; set; }
protected virtual void CalculateDamage() { }
public WeaponDamage(int roll)
{
this.roll = roll;
CalculateDamage();
}
}
class SwordDamage : WeaponDamage
{
private const int BASE_DAMAGE = 3;
private const int FLAME_DAMAGE = 2;
public SwordDamage(int roll) : base(roll) { }
protected override void CalculateDamage()
{
Damage = BASE_DAMAGE;
if (Magic)
{
Damage = (int)(Roll * 1.75M) + BASE_DAMAGE;
}
else
{
Damage = Roll + BASE_DAMAGE;
}
if (Flaming)
{
Damage += FLAME_DAMAGE;
}
}
}
class ArrowDamage : WeaponDamage
{
private const decimal BASE_MULTIPLIER = 0.35M;
private const decimal MAGIC_MULTIPLIER = 2.5M;
private const decimal FLAME_DAMAGE = 1.25M;
public ArrowDamage(int roll) : base(roll) { }
protected override void CalculateDamage()
{
decimal baseDamage = Roll * BASE_MULTIPLIER;
if (Magic)
{
baseDamage *= MAGIC_MULTIPLIER;
}
if (Flaming)
{
Damage += (int)Math.Ceiling(baseDamage + FLAME_DAMAGE);
}
else
{
Damage = (int)Math.Ceiling(baseDamage);
}
}
}
入出力結果(Terminal, Zsh)
% dotnet run
0 fur no magic/flaming, 1 for magic, 2 for flaming, 3 for both, anything else to quit: 0
S for sword, A for arrow, anything else to quit: s
Rolled 7 for 10 HP
0 fur no magic/flaming, 1 for magic, 2 for flaming, 3 for both, anything else to quit: 0
S for sword, A for arrow, anything else to quit: a
Rolled 3 for 2 HP
0 fur no magic/flaming, 1 for magic, 2 for flaming, 3 for both, anything else to quit: 1
S for sword, A for arrow, anything else to quit: s
Rolled 7 for 15 HP
0 fur no magic/flaming, 1 for magic, 2 for flaming, 3 for both, anything else to quit: 1
S for sword, A for arrow, anything else to quit: a
Rolled 3 for 3 HP
0 fur no magic/flaming, 1 for magic, 2 for flaming, 3 for both, anything else to quit: 2
S for sword, A for arrow, anything else to quit: s
Rolled 9 for 14 HP
0 fur no magic/flaming, 1 for magic, 2 for flaming, 3 for both, anything else to quit: 2
S for sword, A for arrow, anything else to quit: a
Rolled 4 for 5 HP
0 fur no magic/flaming, 1 for magic, 2 for flaming, 3 for both, anything else to quit: 3
S for sword, A for arrow, anything else to quit: s
Rolled 14 for 29 HP
0 fur no magic/flaming, 1 for magic, 2 for flaming, 3 for both, anything else to quit: 3
S for sword, A for arrow, anything else to quit: a
Rolled 2 for 13 HP
0 fur no magic/flaming, 1 for magic, 2 for flaming, 3 for both, anything else to quit: 0
S for sword, A for arrow, anything else to quit: b%