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