如何在n个玩家之间平均分配十六进制网格?


15

我正在制作一个简单的基于十六进制网格的游戏,我希望地图在玩家之间平均分配。该地图是随机创建的,我希望玩家拥有大约相等数量的单元,且区域相对较小。例如,如果地图上有4个玩家和80个像元,则每个玩家将有约20个像元(不必精确定位)。另外,每个玩家的相邻单元格不得超过四个。也就是说,在生成地图时,最大的“块”不能超过四个单元。

我知道这对两个或三个玩家来说并不总是可能的(因为这类似于“为地图着色”的问题),我可以为他们做其他解决方案(例如创建可以解决问题的地图)。但是,对于四到八名球员,我该如何解决这个问题?


细胞自动机是一种简单的方法,类似于此:一个简单的地图,四个生物群落以及如何分布
MichaelHouse

Answers:


3

这就是我要做的:

  1. 将所有单元分配给随机玩家。在大地图上,这很可能会为所有玩家产生几乎均匀数量的图块,在小地图上,您可能需要进行一些校正。
  2. 分解太大的块。最简单的方法是将所有图块分成块,然后再次随机分配每个图块。
  3. 在单元数量不平衡的情况下(例如,玩家A有24个单元,玩家B有16个单元),将几个单元从代表人数过多的玩家重新分配给代表不足的玩家。
  4. 再次检查是否有块。如果步骤3引入了新的块,请返回步骤2。

PS:我认为这个问题永远不可能解决,地图着色问题完全不同(一方面,形状->颜色而不是颜色->平铺分配是另一种方式)。
Junuxx

我相当喜欢这种方法,但是它不可能长时间运行以尝试平衡区域大小吗?
manabreak

1
@manabreak:我做了一些尝试。只需对第2步进行少量更改(通过在所有玩家之间循环进行重新分配,而不是随机重新分配),它的效果就很好。有空的时候我会尽量写出来。
Junuxx

1
那正是我想要的。:)
manabreak

1

假设你有一个hexmap n细胞总数,和p球员,其中p <= n,为了解决这个最好的方法是通过轮询分配通过元胞自动机(CA)。

初始化

随机(和/或使用某种或其他启发式方法,例如距地图中心的距离)为每个玩家选择一个起始单元。由于p <= n,这应该不是问题。

细胞自动机

您需要六角单元之间的完全连接。我建议每个单元格由6个邻居组成:

class Cell
{
   //... other members...
   Cell[6] neighbours = new Cell[6];
}

固定大小的数组的使用允许在单元之间存在地形方向的概念,而列表或矢量则不会。我建议您这样做,因为它可能会使某些导航操作变得更容易。

您还可以将hexmap存储在2D数组中,每行具有偏移量。但是,这仅是因为每隔一行上的几何偏移量,所以它比每个单元存储一个邻居数组的直观性要差一些。

确保每个单元都连接到邻近的所有单元。您可以在生成完整的十六进制图时逐行,逐个单元地执行此操作。PS:如果您最终想要一个非矩形边界的六边形图,则可以简单地删除单个单元格和对这些单元格的引用,以形成负数空间,从而可以创建有机的地图轮廓。

轮循分配

伪代码:

count number of neutral cells in entire map, minus those starting cells taken by players
while neutral cells remain (or while true)
   for each player
      if player has not yet reached expected territory size in cells
         for each cell already constituting this player's territory
           if territory can grow by one cell into a neutral neighbour
              grow into neighbour
              reduce neutral cell count for entire map by one
              if no more neutral cells remain in map
                 break out of outermost while loop immediately
              else
                 continue to next player immediately
begin game

该算法将使每个玩家都有机会以循环方式将其领土扩大一个,前提是该玩家的领土仍具有有效的增长空间。如果某些球员进一步成长受阻,该算法将尽管如此不断成长的球员谁的领土仍然具有有效的成长空间。一旦其中一个玩家达到极限,您可以轻松地将每个玩家限制在相同数量的单元格中,但是如果需要的话,这应该足够容易让您找出来。

这将为每个玩家提供最大尺寸的“家园”。如果您还想拥有“岛屿”领土,为了满足该玩家的游戏室数量配额,那么一旦玩家用尽了本地空间来成长,您就可以从中立的游戏室列表中选择一个新的开始游戏室,从那里继续进行相同的“增长”过程。这样,您最终将获得适合每个玩家的大小合适且连贯的孤岛,而不是随机的杂音。


尽管您为算法提供了出色的文档和伪代码,但我不确定这是否与发问者的要求相符。该问题提到“最大的“块”每个不能超过四个单元格”,而您的算法会创建尽可能大的连接组。

@fnord不,不是。您没有正确阅读我的答案。我在伪代码中明确地设置了一个限制:“如果播放器尚未达到预期的单元格区域大小”。请删除您的否决票。请随意检查问题的修订历史记录,以使自己满意,因为在您发表评论和下注之前,就是这种情况。
工程师

该问题要求具有“不超过四个相邻的单元”,但每个用户都具有地图的预期部分。对我而言,这意味着e会采取类似于“风险”游戏如何将地图随机分配给所有玩家的方式。您的答案将地图分为“最大尺寸的“本国领土””。的确,当达到预期的区域大小限制时,您的算法就会停止,但是我看不到该玩家获取新“岛”的方法,尽管您在后面的文章中确实提到了它。
2013年

@fnord您的逻辑有误。在您的最后一句话中,您承认我的算法停止在孤岛大小上n,此后与您说“您看不到路”而我却在“稍后的内容中提到[如何获得孤岛]”相矛盾。我是否回答过这个问题?此通用算法可用于分散单元(通过限制n为1)或创建岛(通过设置n> 1)。因此,在一种算法中,您不仅具有分散能力,而且具有分组能力。这怎么不能回答OP的问题?怎么值得一票?
工程师

我将在上面编辑我的评论,但为时已晚。“我在您的算法中看不到任何方法”。尽管您在以后的文章中确实提到了这个概念。

0

另一种方法是从“公平”但有规律的分布开始,然后使用类似于“模拟退火”的方法破坏规律性而又不失去公平性:

  • 首先,以规则的模式为网格的所有单元格分配颜色(例如,在第一行中具有重复的“ 123412341234”模式,在下一行中具有“ 341234123412”,等等)。如果您的地图形状特别差,这可能会导致颜色分布不均匀,但是我假设您是从固定的地图开始的,因此您应该能够找到它的一些均匀分布的常规着色。
  • 然后根据您的需要重复执行以下步骤(没有真正的“完成”标准,因此实验将告诉您最小合理的步骤数):
    • 随机选择网格的两个元素
    • 如果它们具有相同的颜色,请重试(否则没有任何意义,因为这样一来,就不会进行交换了。您只有1/4的机会会遇到相同的颜色,而1/16的机会会遇到相同的颜色连续两次,因此您永远不必重试太多)
    • 临时交换这两个元素的颜色
    • 交换后测试元素位置中新形成的区域的大小:
      • 从每个元素的新位置向外进行简单的泛洪填充,以确定交换将使该颜色的区域大小。
    • 如果这两个区域中的任何一个大于您的阈值,请撤消临时交换;否则,请执行以下操作。否则,“完成”两个元素颜色的交换。

这里的关键是,您要交换两个斑点的事实意味着您永远不会使颜色不平衡,同样,在完成交换之前进行的测试可确保您永远不会创建太大的区域。如果您有某种显示网格的方法,您甚至可以可视化此过程,以观察它如何通过重复交换来“构建”其区域。

顺便说一句,如果您不能从均匀分布的常规着色开始,那么您仍然应该能够做一些类似于均匀分布着色的事情:当您的颜色不是均匀分布时,随机选择一个元素;然后,如果它是过度代表的颜色之一,则将其颜色临时设置为代表性不足的一种颜色,然后检查以确保不会产生太大的新颜色区域。


随机方法效率低下。对于像我的这样的方法,它采取了经过考虑的步骤,对于n个地图单元,运行时方法接近O(n)。对于您的算法,它是O(n * m),其中m是每个岛(实际上是每个潜在岛)所需的像元数。始终最好针对具有易于估计的运行时间的算法。与其修复随意生成的地图,不如先分n步生成不会损坏或随意的地图,从而保持可控,有效的过程。
工程师
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.