プレイヤーを同じマスに同時に移動しますか?


15

2 x 2の正方形のグリッドを考えます。次の場合、プレイヤーは広場に移動できます。

  • 次のターンに他のプレイヤーは広場に移動したくない
  • 他のプレイヤーは誰も待っておらず、このターンはまだ広場を占領しています

サンプル図

私の問題を説明するために上の画像を含めました。

プレイヤーは同時に動きます。

2人(またはそれ以上)のプレイヤーが同じマスに移動しようとした場合、どちらも移動しません。


1
プレイヤーは1ステップでお互いのタイルに移動できますか?たとえば、黄色と青はまったく同じステップで場所を切り替えることができます(青はタイルを1つ左に移動し、黄色はタイルを1つ右に移動します)。
Ali1S232

ガジェットは今のところはい。しかし、ある時点で、近隣の2人のプレイヤーが場所を直接交換できるようにし
たくない-t123

それから私の答えはその問題を解決します。
Ali1S232

2
非常に関連性の高い:外交の移動ルールをご覧ください。en.wikipedia.org/wiki/Diplomacy_(game)#Movement_phase
TehShrike

回答:


11
  1. このターンに移動を提出したかどうかに応じて、すべてのプレイヤーに静止または移動のフラグを立てます。
  2. 手のリストを確認します。2つの動きが同じ場所を指している場合、それらをリストから削除し、プレーヤーを静止させます。
  3. リストをループして、静止したプレーヤーまたは他の障害物を指すすべての動きを削除します。リストを通過するときにリストが変更されなくなるまで、これを繰り返します。
  4. すべてのプレイヤーを移動します。

うまくいくと思う。それは確かにあなたが投稿したケースと、私がテストした他のいくつかのささいなケースに有効です。


はい、これは動作するはずです。実際には、プレーヤーのリストを繰り返しループしたくないことに注意してください。実際には、バックトラッキングにより衝突を解決する方がはるかに効率的です。
イルマリカロネン

16

衝突防止の代わりの衝突解決。

オブジェクトを単に移動し、衝突があったかどうかを確認します。別のブロックとの衝突があった場合、前の正方形に戻るか、ゲームの種類に応じて、別の正方形に移動します。


1
はい。ただし、1つ戻る必要がある場合は、他の人も戻る必要があります
...-t123

2
あなたは正しいですが、やはり実際のゲームの種類によって異なります。より多くの情報が必要になり、状況は状況に応じて変化します。これは利用可能な最も一般的な答えについてでした。
アルティフィニタス

5
1つのステップですべての衝突を解決する必要はありません。すべてのオブジェクトを移動し、その衝突に関連する逆方向の移動があるかどうかを確認し、衝突がなくなるまでこのプロセスを繰り返します。
Ali1S232

4
Move all players according to their request.
while there are still some squares multiply occupied:
    For each square that is now multiply occupied:
        For each player in that square that moved there this turn:
            Return them to their previous square
            Mark them as having not moved this turn

これには、各プレイヤーが自分がどこから移動したかを覚えておく必要があります。そうすれば、彼らは戻ってくることができ、このターンに移動したかどうかも覚えています。この2番目のチェックは、各ピースが1回だけ戻る必要があり、アルゴリズムが正しく終了することを保証する必要があることを意味します。また、移動したプレイヤーのみが返されるようにします-元の居住者は、削除の対象と見なされないため、そのまま残ります。


3

別の解決策は、表示しているものより2倍大きいマップを使用することです。プレーヤーを移動するたびに2回移動し、XとYの両方の値が等しいタイルに着地するようにします。再び注意が必要なまれなケースがいくつかありますが、可能なケースのほとんどは解決されます(説明)二度考えないで。


ここで何かを念頭に置いていると思いますが、それはあなたの答えには現れません。2xマップを使用すると、衝突の問題はどのように解決されますか?
ザンリンクス

はい。答えがわかると思います。反対方向に移動する2つの破片が同じ正方形に着地し、衝突します。時計回りに動き回るピースは半ステップ移動し、常に別のピースが入るスペースを残します。
ザンリンクス

@ZanLynx:それはまさにそれが問題を解決する方法です。唯一の問題は、2つのピース(緑と青など)が衝突し、別のピース(黄色)が緑の最後の位置を埋めることです。これらに類似した場合(可能な場合)、ultifinitusが示唆したように衝突を解決する必要があります。
Ali1S232

衝突検出のために私が知っている最も簡単な実装は、私のものと究極の組み合わせです。鉱山は、ピースが互いに交差しているかどうかを確認するのに適しています。unltifinitusは、他のタイプの衝突を解決するのに適しています。
Ali1S232

0

配列またはマップを使用して、要求されたすべての動きを登録します。

競合がある場合は、問題の移動要求を元に戻します。それが別のオブジェクトが占有しようとしている正方形にオブジェクトを返す場合、要求元のオブジェクトの要求を元に戻します。

擬似コード:

int[][] game; // game board

var doMoves() {
    int[][] dest = [][]; // destinations; cleared each run

    for (obj in gameObjects)
        if (obj.moveRequest) {
            var o = dest[obj.moveX][obj.moveY];
            if (o) {
                // collision!
                o.doNotMove = true;
                obj.doNotMove = true;
            } else {
                dest[obj.moveX][obj.moveY] = obj;
            }
        }
    }

    // check move validity
    for (obj in gameObjects) {
        if (obj.doNotMove) continue;

        var o = game[obj.moveX][obj.moveY];
        if (o and o.doNotMove)
            revertRequest(obj, dest);
    }

    // process moves
    //etc
}

// recursive function to back up chained moves
var revertRequest(obj, dest) {
    if (!obj.doNotMove) {
        obj.doNotMove = true;
        var next = dest[obj.x][obj.y];
        if (next)
            revertRequest(next, dest);
    }
}

0

SimonWの答え基づいて、ここに明示的なアルゴリズムがあります:

ましょうsquaresプレーヤーの場所によってインデックス付けされた配列であり、可能な場所ごとに、別の場所のインデックスまたは特別な値のいずれかを含みますNULL。(これをスパース配列として保存することもできます。)この配列内のエントリの可能な値は、次のように解釈されます。

  • 場合squares[S]NULL、正方形はSに自由に移動します。
  • の場合squares[S] == S、プレイヤーSは移動できないか、移動しないか、2人(またはそれ以上)のプレイヤーSが同時に移動しようとし、両方とも拒否されました。
  • それ以外の場合、squares[S]プレイヤーがsquareに移動したい正方形のインデックスが含まれますS

各ターンで、squarestoのすべてのエントリを初期化してからNULL、次のアルゴリズムを実行します。

for each player:
   current := the player's current location;
   target := the location the player wants to move to (may equal current);
   if squares[target] is NULL:
      squares[target] := current;  // target is free, mark planned move
   else
      // mark the target square as contested, and if necessary, follow
      // the pointers to cancel any moves affected by this:
      while not (target is NULL or squares[target] == target):
         temp := squares[target];
         squares[target] := target;
         target := temp;
      end while
      // mark this player as stationary, and also cancel any moves that
      // would require some else to move to this square
      while not (current is NULL or squares[current] == current):
         temp := squares[current];
         squares[current] := current;
         current := temp;
      end while
   end if
end for

その後、再びプレーヤーのリストをループし、そうすることができるものを移動します。

for each player:
   current := the player's current location;
   if not squares[current] == current:
       move player;
   end if
end for

各動きは1回しか計画できず、1回しかキャンセルできないため、このアルゴリズムは最悪の場合でもn人のプレーヤーに対してO(n)時間で実行されます。

(残念ながら、このアルゴリズムはプレイヤーが場所を切り替えたり、パスを斜めに交差させたりするのを止めることはありません。Gajetの2ステップトリックをそれに適応させることは可能かもしれませんが、それを行う完全に素朴な方法は機能せず、疲れすぎます今より良い方法を見つけ出すために。)

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.