同时将玩家移至同一广场?


15

考虑一个2 x 2的正方形网格。在以下情况下,玩家可以移动到广场上:

  • 没有其他玩家想在下一回合进入广场
  • 没有其他玩家等待,并且此回合仍在占据广场

示例图

我已包含上面的图像来描述我的问题。

玩家同时移动。

如果2个(或更多)玩家尝试移动到相同的正方形,则两个都不移动。


1
玩家可以一步一步移动彼此吗?例如,黄色和蓝色能否以完全相同的步骤放置(蓝色向左移动一格,黄色向右移动一格)?
Ali1S232 2011年

Gajet是的。但是在某些时候,我不希望2个相邻的玩家能够直接交换位置
t123 2011年

然后我的答案解决了这个问题。
Ali1S232 2011年

2
非常相关:检查外交行动规则。en.wikipedia.org/wiki/Diplomacy_(game)#Movement_phase
TehShrike 2011年

Answers:


11
  1. 将所有玩家标记为静止或移动,具体取决于他们是否在本回合中提交了移动。
  2. 浏览动作列表。如果有两个动作指向同一位置,请将其从列表中删除,并将播放器固定。
  3. 遍历列表,删除指向固定玩家或其他障碍物的所有动作。重复执行此操作,直到遍历列表不变为止。
  4. 移动所有玩家。

我认为应该可以。它确实适用于您发布的案例,以及我测试过的其他一些琐碎的案例。


是的,应该可以。请注意,您实际上并不想在播放器列表中重复循环;实际上,通过回溯解决冲突将更加有效。
Ilmari Karonen 2011年

16

解决冲突,而不是预防冲突。

只需移动对象,然后检查是否有任何碰撞。如果与另一个方块发生了碰撞,请移回上一个方块,或者根据游戏类型,选择另一个方块。


1
是的,但是如果一个人必须后退,那么其他人也必须后退...
t123 2011年

2
您是正确的,但是同样取决于实际的游戏类型,需要更多信息,并且情况会根据类型而改变。这是关于最通用的答案。
ultifinitus 2011年

5
您不必一步一步解决所有冲突。移动所有对象,检查是否有任何碰撞,在该碰撞中进行反向移动,重复此过程,直到没有碰撞为止。
Ali1S232 2011年

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 2011年

我知道的用于碰撞检测的最简单的实现是我的和ultifinitus的混合。我最好检查零件是否彼此交叉,而unltifinitus很适合解决其他类型的碰撞。
Ali1S232'9

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无法移动或不会移动,或者两个(或更多)玩家试图同时移动到S,并且都被拒绝。
  • 否则,squares[S]将包含玩家想要从其移动到平方的平方的索引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

由于每个动作只能计划一次,最多只能取消一次,因此即使在最坏的情况下,该算法也会在O(n)时间内为n个玩家运行。

(las,这种算法不会阻止玩家切换位置或沿对角线穿越路径。也许有可能使Gajet的两步戏法适应它,但是完全天真的方法行不通,我太累了以找出一种更好的方法。)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.