플레이어를 동시에 같은 광장으로 옮기시겠습니까?


15

2 x 2 격자의 정사각형을 고려하십시오. 다음과 같은 경우 플레이어는 사각형으로 이동할 수 있습니다.

  • 다른 플레이어는 다음 턴에 광장으로 이동하기를 원하지 않습니다
  • 이번 턴에는 다른 플레이어가 기다리지 않고 여전히 광장을 차지하고 있습니다

예제 다이어그램

내 문제를 설명하기 위해 위의 이미지를 포함 시켰습니다.

플레이어는 동시에 움직입니다.

2 명 이상의 플레이어가 같은 광장으로 이동하려고하면 둘 다 움직이지 않습니다.


1
플레이어가 한 단계에서 서로 타일을 이동할 수 있습니까? 예를 들어, 노랑과 파랑은 정확히 같은 단계로 장소를 바꿀 수 있습니까?
Ali1S232

가젯 예. 그러나 어느 시점에서 나는 이웃 플레이어 2 명이 직접 장소를 교환 할 수 있기를
원하지 않습니다.

내 대답은 그 문제를 해결합니다.
Ali1S232

2
매우 관련성 : 외교 운동 규칙을 확인하십시오. en.wikipedia.org/wiki/Diplomacy_(game)#Movement_phase
TehShrike 2018 년

답변:


11
  1. 이번 턴에 이동을 제출했는지 여부에 따라 모든 플레이어를 고정 또는 이동으로 표시하십시오.
  2. 이동 목록을 살펴보십시오. 두 이동이 같은 위치를 가리키는 경우, 목록에서 제거하고 플레이어를 고정하십시오.
  3. 고정 플레이어 또는 기타 장애물을 가리키는 모든 동작을 제거하여 목록을 반복합니다. 목록을 통과 할 때 목록이 변경되지 않을 때까지이 작업을 반복하십시오.
  4. 모든 플레이어를 움직입니다.

나는 그것이 작동해야한다고 생각합니다. 그것은 당신이 게시 한 사건과 내가 테스트 한 다른 사소한 사건에 확실히 작동합니다.


예, 이것이 작동합니다. 실제로 플레이어 목록을 반복해서 반복하고 싶지는 않습니다. 실제로 역 추적을 통해 충돌을 해결하는 것이 훨씬 더 효율적입니다.
Ilmari Karonen

16

충돌 방지 대신 충돌 해결.

물체를 옮기고 충돌이 있는지 확인하십시오. 다른 블록과 충돌이 발생한 경우 이전 사각형으로 돌아가거나 게임 유형에 따라 다른 사각형으로 이동하십시오.


1
그렇습니다.하지만 한 사람이 뒤로 물러 나면 다른 사람들도
물러서야합니다

2
당신은 정확하지만 실제 게임 유형에 따라 더 많은 정보가 필요하며 상황에 따라 상황이 바뀔 수 있습니다. 이것은 가장 일반적인 답변이었습니다.
ultifinitus

5
한 번에 모든 충돌을 해결할 필요는 없습니다. 모든 객체를 이동하고 충돌과 관련된 충돌이 있는지 확인합니다. 충돌이 없을 때까지이 과정을 반복합니다.
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

이를 위해서는 각 플레이어가 방금 이동 한 위치를 기억하여 돌아올 수 있도록해야하며이 턴을 옮겼는지 여부도 기억해야합니다. 이 두 번째 검사는 각 조각이 한 번만 반환하면 알고리즘이 제대로 종료되도록 보장한다는 의미입니다. 또한 이동 한 플레이어 만 반환되도록합니다. 원래 탑승자는 제거 대상으로 간주되지 않으므로 그대로 유지됩니다.


3

또 다른 해결책은 현재 표시된 것보다 2 배 큰지도를 사용하는 것입니다. 플레이어를 움직일 때마다 두 번 움직여서 플레이어는 항상 X와 Y의 값이 모두 같은 타일에 착륙합니다. 다시주의를 기울여야 할 경우가 있지만 드물게 발생할 수 있지만 대부분의 경우는 해결됩니다. 설명) 두 번 생각하지 않고.


나는 당신이 여기에 염두에두고 있다고 생각하지만, 당신의 대답에는 나오지 않습니다. 2x 맵을 사용하면 충돌 문제를 어떻게 해결합니까?
Zan Lynx

괜찮아. 나는 대답을 본 것 같아요. 반대 방향으로 움직이는 두 조각은 같은 정사각형에 착륙하여 충돌합니다. 시계 방향으로 움직이는 조각은 반 걸음 이동하며 항상 다른 조각이 들어갈 수 있도록 열린 공간을 남겨 둡니다.
Zan Lynx

@ 잔 린스 (ZanLynx) : 그것이 문제를 정확히 해결하는 방법입니다. 유일한 문제는 두 조각 (녹색과 파란색)이 충돌하고 다른 조각 (노란색)이 녹색의 마지막 위치를 채울 때입니다. 이와 유사한 경우 (가능한 경우) ultifinitus가 제안한대로 충돌을 해결해야합니다.
Ali1S232

충돌 감지를 위해 가장 쉬운 방법은 내 것과 ultifinitus를 혼합 한 것입니다. 광산은 조각이 서로 교차하는지 확인하고 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의 답변바탕 으로 다음과 같은 명시 적 알고리즘이 있습니다.

LET squares플레이어의 위치에 의해 인덱싱 배열 함유하고, 각각의 가능한 위치는, 어느 다른 위치 또는 특수 값의 인덱스 될 NULL. (이를 희소 배열로 저장하려고 할 수 있습니다.)이 배열에서 가능한 항목 값은 다음과 같이 해석 될 수 있습니다.

  • 만약 squares[S] 이고 NULL, 사각형은S 으로 이동 무료입니다.
  • 만약 squares[S] == S 플레이어 S가 움직일 수 없거나 움직일 수 없거나 두 명 이상의 플레이어가S 가 동시에 모두 거부되었습니다.
  • 그렇지 않으면, squares[S] 플레이어가 square로 이동하려는 사각형의 인덱스를 포함합니다 S.

매 턴마다 squares to의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

각 이동은 한 번만 계획하고 최대 한 번 취소 할 수 있으므로이 알고리즘은 최악의 경우에도 n 명의 플레이어에 대해 O ( n ) 시간 동안 실행됩니다 .

(아아,이 알고리즘은 플레이어가 장소를 전환하거나 대각선으로 경로를 건너는 것을 막지 않습니다. Gajet의 2 단계 트릭 을 적용 할 수는 있지만 완전히 순진한 방법은 작동하지 않으며 너무 피곤합니다. 지금 더 나은 방법을 찾아야합니다.)

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.