如何在内存中表示六边形/十六进制网格?


118

假设我正在用六角网格构建棋盘游戏,例如《卡坦的定居者》

主持者imgur.com

请注意,每个顶点和边都可以具有属性(上方的道路和沉降)。

我将如何制作代表该板的数据结构?访问每个图块的邻居,边缘和顶点有哪些模式?


您还可以使用希尔伯特曲线,它们是间距归档曲线,因此可以线性编码保留平面中的邻接关系。查看空间索引以及如何使用它们!v有趣
pbordeaux

Answers:



18

这样的网格可以用二维数组表示:

如果

   2
7     3
   1   
6     4
   5

是十六进制网格中的第一位,其邻居在那,那么您可以将其放入2D数组中,如下所示:

2 3
7 1 4
  6 5

显然,不仅通过水平或垂直相邻,而且使用一个对角线来确定该网格中的邻居。

不过,您也可以使用图表。


凉。边和顶点的数据呢?
的付费书呆子

1
我可能会分开存放它们。无论您是主要看图块还是边缘/顶点,数据的另一半都是痛苦的还是多余的。
乔伊,

请参阅“付费书呆子”答案中的阿米特·帕特尔(Amit Patel)的文章。
aredridel 2013年

11

本文介绍了如何设置Isomeric / Hexagonal网格游戏。我建议您看一下该Forcing Isometric and Hexagonal Maps onto a Rectangular Grid部分和运动部分。尽管它与您要查找的内容不同,但可以帮助您制定如何做自己想要的事情。


2

我已经用六角形处理了很多东西。在这种情况下,您需要跟踪六边形边界的6个点。这使您可以轻松绘制它。

您将只有一个代表十六进制的对象数组。这些十六进制对象中的每一个还具有指向另一个“边”数组的6个“指针”(或指向另一个数组的索引)。“顶点”也是一样。当然,顶点将具有3个指向相邻十六进制的指针,而边将具有2个指针。

因此,十六进制可能类似于:X,Y,Point(6),Vertices(6),Sides(6)

然后,您将得到一个十六进制数组,顶点数组和侧面数组。

然后,很容易找到一个十六进制等的顶点/边。

当我说指针时,它可以很容易地是一个指向顶点或边数组或其他元素的整数。当然,数组可以是列表或其他任何东西。


0
   2
7     3
   1   
6     4
   5

您也可以尝试“平放”地图中的行。对于此示例将是:

  2
7 1 3
6 5 4

在一行中排成一行有时更有用:P


1
这可能会有一些混乱的邻居检查代码,因为例如1和6是邻居,而3和5不是邻居,但是它们具有相同的相对位置。
Bernhard Barker

0

我建议类似以下内容(我将使用Delphi样式的声明):

type
  THexEdge = record
    Hexes: array[1..2] of Integer; // Index of adjoining hexes.
    // Other edge stuff goes here.
  end;

  THexVertex = record
    Hexes: array[1..3] of Integer; // Index of adjoining hexes.
    // Other vertex stuff goes here.
  end;

  THex = record
    Edges: array[1..6] of Integer; // Index of edge.
    Vertices: array[1..6] of Integer; // Index of vertex.
    // Other hex stuff goes here.
  end;

var
  Edges: array of THexEdge;
  Vertices: array of THexVertex;
  HexMap: array of THex;

每个十六进制具有六个边和六个顶点。每个边缘都跟踪其两个相邻的十六进制,每个顶点都跟踪其三个相邻的十六进制(地图边缘上的十六进制是一种特殊情况)。

当然,您可以采取许多不同的方法。您可以使用指针而不是数组,可以使用对象而不是记录,并且可以将十六进制存储在二维数组中,如其他回答者所建议的那样。

希望这可以给您一些解决方法的一些想法。


0

我们为一个班级项目实现了Catan AI的定居者,并从答案中修改了代码(这是有问题的),以创建具有恒定时间随机访问顶点和边的Board。这是一个很有趣的问题,但是开发板花了很多时间,所以如果有人还在寻找简单的实现,这是我们的Python代码:

class Board:
  # Layout is just a double list of Tiles, some will be None
  def __init__(self, layout=None):
    self.numRows = len(layout)
    self.numCols = len(layout[0])
    self.hexagons = [[None for x in xrange(self.numCols)] for x in xrange(self.numRows)] 
    self.edges = [[None for x in xrange(self.numCols*2+2)] for x in xrange(self.numRows*2+2)] 
    self.vertices = [[None for x in xrange(self.numCols*2+2)] for x in xrange(self.numRows*2+2)] 
    for row in self.hexagons:
      for hexagon in row:
        if hexagon == None: continue
        edgeLocations = self.getEdgeLocations(hexagon)
        vertexLocations = self.getVertexLocations(hexagon)
        for xLoc,yLoc in edgeLocations:
          if self.edges[xLoc][yLoc] == None:
            self.edges[xLoc][yLoc] = Edge(xLoc,yLoc)
        for xLoc,yLoc in vertexLocations:
          if self.vertices[xLoc][yLoc] == None:
            self.vertices[xLoc][yLoc] = Vertex(xLoc,yLoc)

  def getNeighborHexes(self, hex):
    neighbors = []
    x = hex.X
    y = hex.Y
    offset = 1
    if x % 2 != 0:
      offset = -1

    if (y+1) < len(self.hexagons[x]):
      hexOne = self.hexagons[x][y+1]
      if hexOne != None: neighbors.append(hexOne)
    if y > 0:
      hexTwo = self.hexagons[x][y-1]
      if hexTwo != None: neighbors.append(hexTwo)
    if (x+1) < len(self.hexagons):
      hexThree = self.hexagons[x+1][y]
      if hexThree != None: neighbors.append(hexThree)
    if x > 0:
      hexFour = self.hexagons[x-1][y]
      if hexFour != None: neighbors.append(hexFour)
    if (y+offset) >= 0 and (y+offset) < len(self.hexagons[x]):
      if (x+1) < len(self.hexagons):
        hexFive = self.hexagons[x+1][y+offset]
        if hexFive != None: neighbors.append(hexFive)
      if x > 0:
        hexSix = self.hexagons[x-1][y+offset]
        if hexSix != None: neighbors.append(hexSix)
    return neighbors

  def getNeighborVertices(self, vertex):
    neighbors = []
    x = vertex.X
    y = vertex.Y
    offset = -1
    if x % 2 == y % 2: offset = 1
    # Logic from thinking that this is saying getEdgesOfVertex
    # and then for each edge getVertexEnds, taking out the three that are ==vertex
    if (y+1) < len(self.vertices[0]):
      vertexOne = self.vertices[x][y+1]
      if vertexOne != None: neighbors.append(vertexOne)
    if y > 0:
      vertexTwo = self.vertices[x][y-1]
      if vertexTwo != None: neighbors.append(vertexTwo)
    if (x+offset) >= 0 and (x+offset) < len(self.vertices):
      vertexThree = self.vertices[x+offset][y]
      if vertexThree != None: neighbors.append(vertexThree)
    return neighbors

  # used to initially create vertices
  def getVertexLocations(self, hex):
    vertexLocations = []
    x = hex.X
    y = hex.Y
    offset = x % 2
    offset = 0-offset
    vertexLocations.append((x, 2*y+offset))
    vertexLocations.append((x, 2*y+1+offset))
    vertexLocations.append((x, 2*y+2+offset))
    vertexLocations.append((x+1, 2*y+offset))
    vertexLocations.append((x+1, 2*y+1+offset))
    vertexLocations.append((x+1, 2*y+2+offset))
    return vertexLocations

  # used to initially create edges
  def getEdgeLocations(self, hex):
    edgeLocations = []
    x = hex.X
    y = hex.Y
    offset = x % 2
    offset = 0-offset
    edgeLocations.append((2*x,2*y+offset))
    edgeLocations.append((2*x,2*y+1+offset))
    edgeLocations.append((2*x+1,2*y+offset))
    edgeLocations.append((2*x+1,2*y+2+offset))
    edgeLocations.append((2*x+2,2*y+offset))
    edgeLocations.append((2*x+2,2*y+1+offset))
    return edgeLocations

  def getVertices(self, hex):
    hexVertices = []
    x = hex.X
    y = hex.Y
    offset = x % 2
    offset = 0-offset
    hexVertices.append(self.vertices[x][2*y+offset]) # top vertex
    hexVertices.append(self.vertices[x][2*y+1+offset]) # left top vertex
    hexVertices.append(self.vertices[x][2*y+2+offset]) # left bottom vertex
    hexVertices.append(self.vertices[x+1][2*y+offset]) # right top vertex
    hexVertices.append(self.vertices[x+1][2*y+1+offset]) # right bottom vertex
    hexVertices.append(self.vertices[x+1][2*y+2+offset]) # bottom vertex
    return hexVertices

  def getEdges(self, hex):
    hexEdges = []
    x = hex.X
    y = hex.Y
    offset = x % 2
    offset = 0-offset
    hexEdges.append(self.edges[2*x][2*y+offset])
    hexEdges.append(self.edges[2*x][2*y+1+offset])
    hexEdges.append(self.edges[2*x+1][2*y+offset])
    hexEdges.append(self.edges[2*x+1][2*y+2+offset])
    hexEdges.append(self.edges[2*x+2][2*y+offset])
    hexEdges.append(self.edges[2*x+2][2*y+1+offset])
    return hexEdges

  # returns (start, end) tuple
  def getVertexEnds(self, edge):
    x = edge.X
    y = edge.Y
    vertexOne = self.vertices[(x-1)/2][y]
    vertexTwo = self.vertices[(x+1)/2][y]
    if x%2 == 0:
      vertexOne = self.vertices[x/2][y]
      vertexTwo = self.vertices[x/2][y+1]
    return (vertexOne, vertexTwo)

  def getEdgesOfVertex(self, vertex):
    vertexEdges = []
    x = vertex.X
    y = vertex.Y
    offset = -1
    if x % 2 == y % 2: offset = 1
    edgeOne = self.edges[x*2][y-1]
    edgeTwo = self.edges[x*2][y]
    edgeThree = self.edges[x*2+offset][y]
    if edgeOne != None: vertexEdges.append(edgeOne)
    if edgeTwo != None: vertexEdges.append(edgeTwo)
    if edgeThree != None: vertexEdges.append(edgeThree)
    return vertexEdges

  def getHexes(self, vertex):
    vertexHexes = []
    x = vertex.X
    y = vertex.Y
    xOffset = x % 2
    yOffset = y % 2

    if x < len(self.hexagons) and y/2 < len(self.hexagons[x]):
      hexOne = self.hexagons[x][y/2]
      if hexOne != None: vertexHexes.append(hexOne)

    weirdX = x
    if (xOffset+yOffset) == 1: weirdX = x-1
    weirdY = y/2 
    if yOffset == 1: weirdY += 1
    else: weirdY -= 1
    if weirdX >= 0 and weirdX < len(self.hexagons) and weirdY >= 0 and weirdY < len(self.hexagons):
      hexTwo = self.hexagons[weirdX][weirdY]
      if hexTwo != None: vertexHexes.append(hexTwo)

    if x > 0 and x < len(self.hexagons) and y/2 < len(self.hexagons[x]):
      hexThree = self.hexagons[x-1][y/2]
      if hexThree != None: vertexHexes.append(hexThree)

    return vertexHexes

这个答案太糟糕了。您只是粘贴了很多代码而没有解释任何内容(除了谁编写了代码)。即使在这里没问题,代码本身也是可怕的。没有文档字符串,几乎没有注释,并且其中包含的注释是难以理解的(逻辑上认为这是说getEdgesOfVertex,然后对于每个边缘getVertexEnds,取出== vertex的三个)。
卡尔·史密斯,

0

我坐在这里“用空闲时间编写有趣的代码”。就像这样...我会用语言告诉您它的外观。

  1. 六角形:它有六个相邻的六角形。它可以为每个相邻的十六进制图块提供参考。它可以告诉您它的成分(水,岩石,灰尘)。它可以将自己连接到其他人,反之亦然。它甚至可以自动连接他周围的其他人,以创建更大的领域,或者确保邻居可以解决所有领域。
  2. 一栋建筑物最多可参考三条道路和三块六角瓷砖。他们可以告诉你他们是谁。
  3. 一条道路参考了两个十六进制和其他道路,当它们被相邻的瓷砖修饰时。他们可以知道是哪些图块以及它们连接的道路或建筑物。

这只是我将如何工作的一个想法。


0

您可以创建一个2D数组,然后将有效位置视为:

  • 在偶数行(0,2,4,...):奇数单元格。
  • 在奇数行(1,3,5,...):偶数单元格。

对于每个单元,其邻居将是:

  • 同一列,向上2行
  • 同一列,向下2行
  • 剩下1个+ 1个
  • 剩下1个+ 1个向下
  • 1个右+ 1个
  • 1个右+ 1个向下

插图: 六角格

x标记为十六进制。彼此对角的x是邻居。| 连接垂直邻居。

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.