Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 经典解决方案;百视达”;_Algorithm_Puzzle - Fatal编程技术网

Algorithm 经典解决方案;百视达”;

Algorithm 经典解决方案;百视达”;,algorithm,puzzle,Algorithm,Puzzle,在整个80年代和90年代(我相信也是70年代!)的英国,有一个名为“百视达”的经典电视节目,它在蜂窝状网格中显示六边形,如下所示(很抱歉照片模糊!): (来源:) 如您所见,共有5列字母和4行。一个人或团队尝试水平旅行,一个人尝试垂直旅行。回答一个问题就赢得了一个六边形,答案将以该六边形中显示的字母开始 获胜的人或球队是第一个“连接一条线”——注意,这可能是自相矛盾的(例如,如果它被获胜的对手队阻挡),因此有很多很多可能的获胜组合 几年前,当我刚开始编写代码时,我根据这个拼图编写了一个会议游戏

在整个80年代和90年代(我相信也是70年代!)的英国,有一个名为“百视达”的经典电视节目,它在蜂窝状网格中显示六边形,如下所示(很抱歉照片模糊!):


(来源:)

如您所见,共有5列字母和4行。一个人或团队尝试水平旅行,一个人尝试垂直旅行。回答一个问题就赢得了一个六边形,答案将以该六边形中显示的字母开始

获胜的人或球队是第一个“连接一条线”——注意,这可能是自相矛盾的(例如,如果它被获胜的对手队阻挡),因此有很多很多可能的获胜组合

几年前,当我刚开始编写代码时,我根据这个拼图编写了一个会议游戏(我们让它交替使用八角形和正方形以避免侵犯版权!),但我一直在努力的一点是检查何时完成一条完整的线的算法。简单的很好,但是那些上下来回的我真的被卡住了

我最终基本上编写了一个庞大的蛮力循环,但仍然没有捕捉到所有可能发生的事情。因此,我不得不在会议组织者的屏幕上设置一个按钮,以便他们在逻辑没有检测到的情况下快速宣布获胜!谈论肮脏的黑客

现在我回想起我必须解决的这个难题,我想知道你们中是否有人愿意提出一个更优雅的解决方案?当然,语言不可知论者(包括伪代码在内)


编辑可以按照您想要的方式存储数据。我把它放在一个数组中。

一个简单的图形算法可以做到这一点

它也可以通过简单的多通道方法来实现-blockbuster board非常小,以至于我认为多次访问每个单元都不会对性能产生任何明显影响-因此我建议首先尝试这种方法:

对于每个玩家,循环遍历所有单元格;如果该单元格为玩家所有,并且与此填充例程“标记”的单元格六边相邻,则该单元格也会被标记。再次循环遍历所有单元格,直到没有单元格标记到当前播放机。下面是一些伪代码:

for player in players:
  # those on the starting edge that the player owns get 'marked'
  for cells in cells.start_edge(player):
    if cell.owner = player:
      cell.mark = player
  do:
    count = 0
    for cell in cells:
      if cell.mark == None && cell.owner == player:
        for adjacent in cell.neighbours:
          if adjacent.mark == player
            cell.owner = player
            count += 1
            break
  while count
  for cell in cells.stop_edge(player):
     if cell.mark == player
       player won!!

此时,如果棋盘适当一侧的任何单元格属于播放机,播放机将到达棋盘的那一侧。

您的问题转化为两个节点是否在图形中连接

  • 您可以将电路板视为非定向“图形”。节点是单元,如果它们是相邻单元,则它们具有边
  • 边也是图形中的节点,这些边与相邻的单元有边
  • 获取可以使用的节点子图(如果检查该播放器,则包括顶部和底部)
  • 检查顶部和底部是否使用DFS连接

诀窍是为每个块指定坐标

你可以把它想象成一个简单的4x4正方形网格,x坐标在0到4之间,y坐标在0到3之间

绘图算法负责将奇数编号的x单元(1和3)向下偏移六角半径的一半,以便它们正确地装配在一起

为每个单元格考虑一个
isAdjacent(other)
方法。在正方形网格中,您可以通过一个简单的检查来推断出是否相邻:如果self.x==other.x±1和self.x==other.x±1。要检查的8个相关组合为-1,0,1代表x,-1,0,1代表y

在六边形网格中,邻接有点不同。如果self.y==other.y±1,self.x==other.x是它的一部分。但是x邻接取决于self所在的列。如果x是偶数列(0,2,4),则相邻单元格位于奇数列中,这意味着self.y==other.y或self.y==other.y+1。类似地,如果x是奇数列(1,3),则相邻单元位于偶数列中。我把剩下的工作交给你去做

“边缘呢”?容易的。将它们包括在
网格中。get()
方法中。对于越界坐标,返回一个从未被占用的特殊虚拟单元。这使得比较更简单

好的,给定
isAdjacent()
如何找到水平或垂直的连接路径

实际上,您需要两种形式的枚举。您要创建
枚举相邻垂直(y\U偏移量)
枚举相邻水平(x\U偏移量)
。要枚举垂直相邻的值,将产生三个值
(self.x-1,self.y+y\u偏移量),(self.x,self.y+y\u偏移量),(self.x+1,self.y+y\u偏移量)
。若要枚举水平相邻的,请在self.x位于奇数列时生成两个值:
(self.x+x\u offset,self.y),(self.x+x\u offset,self.y+1)
。如果self.x位于偶数列中:
(self.x+x\u偏移,self.y),(self.x+x\u偏移,self.y-1)

这是相对直截了当的。给定一个边缘单元,您希望沿特定方向“穿过”或“向下”电路板到相邻单元


假设从左向右(增加x)。您想在
enum_nextended_horiz
列表中查找相邻单元格。要从上到下(增加y),您可以在
enum\u adjancent\u vert
列表中找到一个相邻的单元格。

啊,是的,Blockbuster。。。“什么是一个受欢迎的程序员问答网站?”是的,这是一个鼓舞人心的喜剧的诞生地,比如“我想要‘P’请Bob”!。。。原始游戏名为Hex:。还有很多变体,最有趣的是Twixt.Flood-fill看起来不错。仍然试图让我的头围绕着“如果该单元是空的,并且与一个属于玩家的单元相邻,那么该单元属于玩家”的比特!您能稍微扩展一下吗?@h4xxr:在开始之前,怀特“拥有”了电路板顶部的半填充六角体。蓝色“拥有”右边的六角体。