How do I represent a hextile/hex grid in memory?

前端 未结 9 556
迷失自我
迷失自我 2020-12-04 05:23

Say I\'m building a board game with a hextile grid, like Settlers of Catan:

\"Hosted

Note that

9条回答
  •  孤城傲影
    2020-12-04 06:01

    We implemented a Settlers of Catan AI for a class project, and modified code from this answer (which was buggy) to create a Board with constant time random access to vertices and edges. It was a fun problem, but the board took a lot of time, so in case anyone is still looking for a simple implementation here is our Python code:

    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
    

提交回复
热议问题