1

コンテキストとして、私はゲームをポケモンのラインに沿ったものにしようとしています. モンスターを入手し、訓練し、戦います。

モンスターの各種は、抽象基本クラスから継承するクラスであり (そのため、固有の動作を持つことができます)、ゲーム全体で非常に多くの異なる種が存在することを願っています。元:

abstract class Monster {
  int hp;
  void attack();
  //Etc.
}

public class FireBreathingDragon extends Monster {
  static String species_name = "Fire Breathing Dragon";
  //Blah
}

そのため、プレイヤーが探索しているとき、彼らはランダムに地域に固有のモンスターに遭遇します. 次に、ゲームは、その地域に生息する種のリストからランダムにモンスターを作成する必要があります。このコードを領域間で再利用できるようにする (そして、コード内の他の場所で動的にモンスターを簡単に作成できるようにする) ために、可能性を領域にハードコーディングしたくありません。代わりに、特定の種のモンスターをオンデマンドで作成する工場のようなものが欲しいと思います。たとえば、次のようなものです。

public class MonsterFactory {
  Monster createMonster(
    String species_name,
    //Possibly other paramters
  );
}

問題は、createMonster(潜在的に)数十または数百の異なるモンスタークラスがある場合に、「素敵な」または「エレガントな」方法で実装することです。もちろん、非常に長いif-else if-elseorswitchステートメントを使用することもできますが、それを書いて拡張するのは恐ろしいことです。これを行う良い方法はありますか?また、モンスターを追加する際に比較的簡単に拡張できると良いです。

または、代わりに使用する必要があるまったく異なるデザインがありますか?

免責事項: 私の Java は少し錆びており、構文が完全ではない可能性があります。申し訳ありません。

4

6 に答える 6

4

Monsterすべての実装クラスを に登録できますList

List<Class<? extends Monster>> monsterTypes = new LinkedList<>();
monsterTypes.add(FireBreathingDragon.class);
// more

これはハードコードする必要はありません。XML、Json、またはその他のファイル形式に外部化できます。

ファクトリ インスタンスまたはクラスは、ランダムなインデックスでリストからモンスター タイプを選択できます。その後、リフレクションを使用して型をインスタンス化できます。

于 2013-08-13T18:16:09.220 に答える
2

最も簡単な解決策は、データ ドリブン モンスター クラスを使用することです。つまり、クラスは 1 つ (または少数) しかなく、このクラスはさまざまな属性と能力を持つ多種多様なモンスターに使用できます。

各種と、その種のすべての属性と能力を含む CSV ファイルを作成できます。このようにして、スプレッドシートに行を追加することで種を追加できます。

于 2013-08-13T18:16:16.553 に答える
0

Cartesian Product Algorithmを見てください。製品のすべての組み合わせが生成され、ランダムに 1 つを選択できます。

基本的に、アルゴリズムは属性の配列を取り、さまざまな属性の一意の組み合わせを作成し、それらを配列に追加します。その後、敵を作成するときに配列からキーをランダムに選択できます。そうすれば、すべての敵がランダムに任意の数の属性を持つ可能性があります。

于 2013-08-13T18:36:35.307 に答える
0

モンスターを提供するインターフェイスまたは基本クラスを持っています。

このウィキ ビットを含めようと思いました。「ファクトリ メソッド パターンは、ファクトリの概念を実装するためのオブジェクト指向の作成設計パターンであり、オブジェクトの正確なクラスを指定せずにオブジェクト (製品) を作成する問題を処理します。作成されます。」

これにより、インターフェイスの特定のサブタイプを知る必要なく、スーパークラスのメソッドまたはインターフェイスを排他的に使用できます。を呼び出すことができないため、これは重要ですnew base_monster()

abstract class base_monster  {
  abstract base_monster factory();
}

/// make sure every monster has a name...
//
abstract class Monster extends base_monster { 
   String name; 
   static int object_counter = 0;

    Monster factory() { 
       name = Integer(object_counter).toString(); 
       object_counter();
       return this; 
    }

    /// this class has a useful setter
    void object_counter( int c ) { object_counter++; out.println( object_counter );    }
}

class Griffon extends Monster {
  Monster factory() { return new Griffon(); }
}


class Harpy extends Monster {
  Harpy() { name = "Grizelda WhuttleThut III"; }
  Harpy factory() { return new Harpy(); }
}


class BlackHarpy  extends Harpy {
  BlackHarpy  factory() { super.factory(); return new BlackHarpy(); }
}


// we assume that each class has a default constructor. But, 
// if the array is filled with monsters of different subclasses we
// would have to use reflection or nasty instanceof switches to be
// able to call a (specific) defined constructor.

ArrayList<Monster> monsters = new ArrayList<Monster>();    

monsters.add( new BlackHarpy() );
for( int I = 0; I < ave_monsters_appearing; I++ )
    monsters.add( new Harpy() );
//
// an array of ten harpies and a boss Harpy.

///
// how can this array of monsters be copied into the other array?
// (we want object copies, not reference copies)
///

ArrayList<Monster> local_monsters = new ArrayList<Monster>();    

/// solution: use the factory method
for( Monster m : monsters ) 
   local_monsters.add( m.factory() ); 

.
. これにより、静的メソッドがないという問題が解決されることを願っています。

于 2013-08-19T03:15:43.613 に答える