2 x 2 격자의 정사각형을 고려하십시오. 다음과 같은 경우 플레이어는 사각형으로 이동할 수 있습니다.
- 다른 플레이어는 다음 턴에 광장으로 이동하기를 원하지 않습니다
- 이번 턴에는 다른 플레이어가 기다리지 않고 여전히 광장을 차지하고 있습니다
내 문제를 설명하기 위해 위의 이미지를 포함 시켰습니다.
플레이어는 동시에 움직입니다.
2 명 이상의 플레이어가 같은 광장으로 이동하려고하면 둘 다 움직이지 않습니다.
2 x 2 격자의 정사각형을 고려하십시오. 다음과 같은 경우 플레이어는 사각형으로 이동할 수 있습니다.
- 다른 플레이어는 다음 턴에 광장으로 이동하기를 원하지 않습니다
- 이번 턴에는 다른 플레이어가 기다리지 않고 여전히 광장을 차지하고 있습니다
내 문제를 설명하기 위해 위의 이미지를 포함 시켰습니다.
플레이어는 동시에 움직입니다.
2 명 이상의 플레이어가 같은 광장으로 이동하려고하면 둘 다 움직이지 않습니다.
답변:
나는 그것이 작동해야한다고 생각합니다. 그것은 당신이 게시 한 사건과 내가 테스트 한 다른 사소한 사건에 확실히 작동합니다.
충돌 방지 대신 충돌 해결.
물체를 옮기고 충돌이 있는지 확인하십시오. 다른 블록과 충돌이 발생한 경우 이전 사각형으로 돌아가거나 게임 유형에 따라 다른 사각형으로 이동하십시오.
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 배 큰지도를 사용하는 것입니다. 플레이어를 움직일 때마다 두 번 움직여서 플레이어는 항상 X와 Y의 값이 모두 같은 타일에 착륙합니다. 다시주의를 기울여야 할 경우가 있지만 드물게 발생할 수 있지만 대부분의 경우는 해결됩니다. 설명) 두 번 생각하지 않고.
배열 또는 맵을 사용하여 요청 된 모든 이동을 등록하십시오.
충돌이있는 경우 해당 이동 요청을 되 돌리십시오. 객체가 사각형으로 반환되면 다른 객체가 차지하려고 시도하는 경우 요청하는 객체의 요청을 되돌립니다.
의사 코드 :
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);
}
}
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 단계 트릭 을 적용 할 수는 있지만 완전히 순진한 방법은 작동하지 않으며 너무 피곤합니다. 지금 더 나은 방법을 찾아야합니다.)