3

私は今日、小さなゲームのアイデアについて考えていて、それを実装する方法に出くわしました。プレイヤーは少しの効果をもたらす一連の動きをすることができますが、特定のシーケンスで行われた場合、より大きな効果をもたらすという考え方です。これまでのところ、これは私が行う方法を知っています。明らかに、私はそれをより複雑にする必要がありました(私たちはそれをより複雑にするのが好きなので)、それで私は、異なるものではありますが、両方がより大きな効果を引き起こすシーケンスの可能なパスが複数ある可能性があると思いました。また、一部のシーケンスは他のシーケンスの始まりである可能性があり、シーケンス全体でさえ他のより大きなシーケンスに含まれている可能性があります。今、私はこれを実装するための最良の方法を確かに知りません。しかし、私にはいくつかのアイデアがありました。

1)循環nリンクリストを実装できます。しかし、移動のリストは決して終わらないので、スタックオーバーフロー™を引き起こす可能性があるのではないかと心配しています。すべてのノードにn個の子があり、コマンドを受信すると、その子の1つに誘導されるか、そのようなコマンドに使用できる子がない場合は、最初に戻る可能性があります。子供が到着すると、いくつかの機能が実行され、小さな効果と大きな効果が発生します。ただし、これにより、ツリー上に多数の重複ノードが発生し、特定の移動で終了する可能性のあるすべてのシーケンスにさまざまな効果で対処できるようになる可能性があります。これは維持するのが面倒かもしれませんが、よくわかりません。理論的にのみ、コードでこれほど複雑なことを試したことはありません。このアルゴリズムは存在し、名前がありますか?それは良い考えですか?

2)ステートマシンを実装できました。次に、リンクリストをさまよっている代わりに、関数を呼び出してそれに応じてマシンの状態を更新する巨大なネストされたスイッチがあります。実装するのは簡単なようですが...まあ...面白くないようです...エレガントでもありません。巨大なスイッチはいつも私には醜いように見えますが、これはもっとうまくいくでしょうか?

3)提案?私は良いですが、私ははるかに経験が浅いです。コーディング分野の良いところは、あなたの問題がどんなに奇妙であっても、誰かが過去にそれを解決したことですが、どこを見ればよいかを知っている必要があります。誰かが私が持っていたものよりも良いアイデアを持っているかもしれません、そして私は本当に提案を聞きたかったです。

4

7 に答える 7

3

あなたの言っていることを正確に理解しているかどうかは完全にはわかりませんが、類似した状況として、誰かがキーボードで無限の数字の流れを入力しているとしましょう。'117' はマジック シーケンス、'468' は別のシーケンス、'411799' は別のシーケンス (最初のシーケンスを含む) です。

したがって、ユーザーが次のように入力した場合:

55468411799

*s で「マジック イベント」を発生させたい場合:

55468*4117*99*

またはそのようなものですよね?それがあなたが話している問題に類似している場合、次のようなものはどうですか(Javaのような疑似コード):

MagicSequence fireworks = new MagicSequence(new FireworksAction(), 1, 1, 7);
MagicSequence playMusic = new MagicSequence(new MusicAction(), 4, 6, 8);
MagicSequence fixUserADrink = new MagicSequence(new ManhattanAction(), 4, 1, 1, 7, 9, 9);

Collection<MagicSequence> sequences = ... all of the above ...;

while (true) {
  int num = readNumberFromUser();
  for (MagicSequence seq : sequences) {
    seq.handleNumber(num);
  }
}

MagicSequence には次のようなものがあります。

Action action = ... populated from constructor ...;
int[] sequence = ... populated from constructor ...;
int position = 0;

public void handleNumber(int num) {
  if (num == sequence[position]) {
    // They've entered the next number in the sequence
    position++;
    if (position == sequence.length) {
       // They've got it all!
       action.fire();
       position = 0; // Or disable this Sequence from accepting more numbers if it's a once-off
    }
  } else {
    position = 0; // missed a number, start again!
  }
}
于 2008-10-09T13:53:59.437 に答える
2

とにかくステートマシンを実装したいかもしれませんが、状態遷移をハードコーディングする必要はありません。
状態のグラフを作成してみてください。状態 A と状態 B の間のリンクは、A が B につながることを意味します。
次に、実行時にグラフを走査して、プレーヤーの移動先を見つけることができます。

編集: グラフ ノードを次のように定義できます:
-state-id
-他の状態へのリンクのリスト。各リンクは次を定義します:
-state-id -
前提条件、この状態に行く前に訪問する必要がある状態のリスト

于 2008-10-09T13:36:05.120 に答える
1

必要なエフェクトごとに小さなステートマシンを作成します。各ユーザーアクションで、すべてのステートマシンに「ブロードキャスト」します。ほとんどの場合は気になりませんが、前進するものもあれば、後退するものもあります。それらの1つが目標に到達したら、目的の効果を生み出します。

コードをきちんと保つために、ステートマシンをハードコーディングせずに、状態グラフをエンコードする単純なデータ構造を構築します。各状態は、興味深いイベントのリストを持つノードであり、それぞれが次の状態のノードを指します。各マシンの状態は、単に適切な状態ノードへの参照です。

編集:コーワンのアドバイスはこれと同等のようですが、彼はステートマシンを最適化して単純なシーケンスのみを表現します。特定の問題には十分なようですが、より複雑な条件では、より一般的な解決策が必要になる可能性があります。

于 2008-10-09T14:06:54.543 に答える
1

あなたが説明していることは、ゲームのライブ シヴィライゼーションのテクノロジー ツリーに非常によく似ています。

Civ の作成者がどのように作成したかはわかりませんが、可能な「動き」を表現するためにマルチグラフを使用する傾向があります。「経験」がなくても開始できるものもあります。 、最後まで複数のパスがあります。

ゲームの各段階で考えられる選択肢を引き出し、いくつかの選択肢から他の選択肢へと線を引きます。

グラフは[比較的]実装と利用が簡単な概念であるため、これで実装の開始が可能になります。

于 2008-10-09T13:29:46.240 に答える
1

ニューラル ネットワークのように聞こえます。作成したものをトレーニングして、探しているさまざまな効果を引き起こすパターンを認識することができます。

于 2008-10-09T13:39:08.750 に答える
1

あなたが説明していることは、依存グラフや単語グラフに多少似ています。あなたはそれらを調べるかもしれません。

于 2008-10-09T13:50:19.710 に答える
1

@Cowan、@Javier: 良いアイデアです。追加してもよろしいですか?

MagicSequence オブジェクトがユーザー入力の着信ストリームをリッスンするようにします。つまり、入力を通知し (ブロードキャスト)、各オブジェクトに入力を内部入力ストリームに追加させます。入力が、MagicSequence がそのアクションを起動するパターンで予想される次の入力ではない場合、このストリームはクリアされます。パターンが完了するとすぐに、アクションを起動し、内部入力ストリームをクリアします。

入力を待機している MagicSequences にのみ入力を供給することで、これを最適化します。これには、次の 2 つの方法があります。

  1. パターン内の数字に対応するイベントにすべての MagicSequence を接続できるようにするオブジェクトがあります。MagicSequence(1,1,7) は、自分自身を got1 と got7 に追加します。次に例を示します。

    UserInput.got1 += MagicSequence[i].SendMeInput;

  2. これを最適化して、各入力後に MagicSequence が無効なイベントから登録解除し、有効なイベントに登録するようにすることができます。

于 2008-10-09T14:29:39.410 に答える