2017-11-04 13 views
3

私はOOPの理解を深めようとしているので、コンソールアドベンチャーゲームを作成しました。私は基本的に3つの方法がある戦闘クラスを持っています:オーバーロードが原因でコードが肥大化する

public static void StartFight(Dragon dragonWarrior, Goblin goblinEnemy) 
public static string YouAttack(Dragon dragonWarrior, Goblin goblinEnemy) 
public static string EnemyAttack(Goblin goblinEnemy, Dragon dragonWarrior) 

最初の人は誰かが死ぬまでもう一方を呼び出します。 YouAttackとEnemyAttackのようなメッセージが含まれます:

全てにおいて
Console.WriteLine("{0} the dragon attacks {1} and has dealt {2} damage", 
        dragonWarrior.Name, goblinEnemy.Name, damageDone); 

を、することができますが、私の3つの方法をまとめたコードの90行を取ると言っています。

私の問題はこれです。私はオークを持っています。私は簡単にメソッドをコピーして貼り付けて、次のようにオーバーロードすることができます:

public static void StartFight(Orc orcWarrior, Goblin goblinEnemy) 

しかし、それは膨らんでしまいます。特にオブジェクト戦士の数が増えるにつれて(ケンタウルス、デーモン、ドワーフ等)

どのオブジェクトが渡されたのかを知るためにオブジェクトとコンパイラを渡す方法はありますか?もしあれば、良いチュートリアルを知っている人はいますか?私は研究することができる別の解決策はありますか?

これはゴミの問題かもしれないが、私は完全に自己教えられていることを知っている。私はすべての問題が闘争になることができるようにコードを書く友人や教師はいません。 は継承(link)とポリモーフィズム(link)あなたが探していると呼ばれる事前

+0

抽象クラスまたはそれより優れたインタフェースを探します。彼らはあなたが尋ねたものを正確に援助します。 –

+0

"インターフェース"、 "継承"、 "多形性"、そしておそらく "ジェネリック"というコンセプトに精通している必要がある検索用語。 – dlatikay

+0

継承と仮想メソッドについても読んでください。 – Shoter

答えて

1

でいただきありがとうございます - 両方(第3つのカプセル化(link)である)OOPの3つの主要な柱の一つである

彼らはあなたがオブジェクトを使用できるようにしますそのうちの正確なクラスはわかりませんが、APIやメソッドについてはまだ説明できます。

いくつかの使用例がここで見つけることができます:あなたの例ではWhat is the real significance(use) of polymorphism

を、DragonOrcWarriorクラスを拡張言うことができます、とGoblinGnomeEnemyクラスを拡張することを言うことができます。次に、あなたの方法には、次のようになります。

public static void StartFight(Warror warrior, Enemy enemy) 
public static string YouAttack(Warror warrior, Enemy enemy) 
public static string EnemyAttack(Enemy enemy, Warror warrior) 

そして、あなたはEnemyWarriorクラスを拡張する任意のオブジェクトを渡すことができます。

この継承ツリーはほんの一例に過ぎません。他の人も触れたように、必要に応じて抽象的なデザインを設計できます。

+0

第3の「OOPの柱」とは何ですか? –

+1

@UweKeimカプセル化 –

+0

私は参照してください。 1994年以来このことをしてきた私は、この[柱の概念](http://cs.smu.ca/~porter/csc/common_341_342/notes/oop_3pillars.html)について聞いたことはありません。 –

1

良い抽象化を行うために、私はあなたが多くのチュートリアルを通過する必要があると思う...しかし、あなたは単純なものから始めることができます:

public interface IUnit 
{ 
    string Name { get; } 
    int HP  { get; set; } 
    int Armor { get; } 
    int Damage { get; } 
} 

public class Goblin : IUnit 
{ 
    public string Name { get; } = "Goblin"; 

    public int HP { get; set; } = 80; 

    public int Armor => 3; 
    public int Damage => 8; 
} 

public class Knight : IUnit 
{ 
    public string Name { get; } = "Knight"; 

    public int HP { get; set; } = 120; 

    public int Armor => 5; 
    public int Damage => 12; 
} 

public class BattleSystem 
{ 
    public void ProcessAttack (IUnit attacker, IUnit target) 
    { 
     Console.WriteLine (attacker.Name + " is attacking " + target.Name); 

     int damage = Math.Max (0, attacker.Damage - target.Armor); 

     target.HP -= damage; 

     if (target.HP <= 0) 
     { 
      Console.WriteLine ("Enemy unit died..."); 
     } 
    } 
} 

Goblinなどの具体的な種類を使用しないようにしてください、Warriorなど1つがユニットに2番目の特殊武器がある場合は、どのユニットにも2番目の武器を持たせる抽象化を実装する必要があります(しかし、ほとんどのものはもちろん武器1つしか使用しません)。

Game programming patterns

+0

これはうまく見えますが、あなたが言うように、私はインターフェイスに関するチュートリアルを見つける必要がありますか? – Rich

+0

@Rich:インターフェース、抽象クラス、多態性、ゲーム関連のデザインパターン。 – apocalypse

1

あなたは完全に異なるアプローチを検討するかもしれない:

生き物の統計情報やスキルレベルを保持する構造体やクラスを定義します。fireball_skill creature_name、強さ、敏捷性、sword_skill、archery_skill、、。 ..

おそらくBowAttack(skill_level、距離、arrow_type、...)、または火の玉のようなサブ機能を呼び出す、AA単一アタック()関数を定義します(skill_level、距離を、...)

orc = new Creature("Orc A", 11, 0, 5, 1, 0, 0, 0, 0, ...): 
player = new Creature("Hero Bob", 20, 10, 11, 11, 1, 1, 1, 0, ...); 

Fight(Creature& player, Creature& enemy) 
while (player.health > 0 && enemy.health > 0) 
{ 
player.Attack(enemy); 
enemy.Attack(player); 
} 

これは、両側の配列を渡し、それぞれのクリーチャーの攻撃の順番が反射またはイニシアチブスキルによって選択される「ラウンド」またはターンを持つことにより、より派手になる可能性があります。

関連する問題