Settlers of Catan 과 같이 육각 격자로 보드 게임을 만들고 있다고 가정 해 보겠습니다 .
각 정점과 모서리에는 속성 (위의 도로 및 정착지)이있을 수 있습니다.
이 보드를 나타내는 데이터 구조를 어떻게 만들 수 있습니까? 각 타일의 이웃, 가장자리 및 정점에 액세스하기위한 패턴은 무엇입니까?
Settlers of Catan 과 같이 육각 격자로 보드 게임을 만들고 있다고 가정 해 보겠습니다 .
각 정점과 모서리에는 속성 (위의 도로 및 정착지)이있을 수 있습니다.
이 보드를 나타내는 데이터 구조를 어떻게 만들 수 있습니까? 각 타일의 이웃, 가장자리 및 정점에 액세스하기위한 패턴은 무엇입니까?
답변:
이러한 그리드는 2 차원 배열로 표현할 수 있습니다.
만약
2
7 3
1
6 4
5
헥스 그리드에서 이웃이있는 숫자 1이면 다음과 같이 2D 배열에 넣을 수 있습니다.
2 3
7 1 4
6 5
분명히 인접성은 수평 또는 수직으로 인접 할뿐만 아니라 하나의 대각선을 사용하여이 그리드에서 결정됩니다.
그래도 원하는 경우 그래프를 사용할 수 있습니다.
나는 헥스를 많이 다루었습니다. 이와 같은 경우에는 16 진수의 경계에 대해 6 개 지점을 각각 추적합니다. 이렇게하면 아주 쉽게 그릴 수 있습니다.
헥스를 나타내는 단일 객체 배열이 있습니다. 이러한 각 16 진수 개체에는 "측면"의 다른 배열을 가리키는 6 개의 "포인터"(또는 다른 배열에 대한 인덱스)도 있습니다. "정점"도 마찬가지입니다. 물론 정점에는 인접한 헥스에 대한 3 개의 포인터가 있고 측면에는 2 개의 포인터가 있습니다.
따라서 16 진수는 X, Y, Point (6), Vertices (6), Sides (6)와 같을 수 있습니다.
그런 다음 Hex 배열, 정점 배열 및 측면 배열이 있습니다.
그런 다음 16 진수에 대한 정점 / 측면을 찾는 것은 매우 간단합니다.
내가 포인터를 말할 때 그것은 vertice 또는 side array 또는 무엇이든간에 요소를 가리키는 정수가 될 수 있습니다. 그리고 물론 배열은 목록 등이 될 수 있습니다.
다음과 같은 것을 제안합니다 (델파이 스타일 선언을 사용합니다).
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;
각 16 진수에는 6 개의 모서리와 6 개의 정점이 있습니다. 각 가장자리는 인접한 두 개의 헥스를 추적하고 각 정점은 인접한 세 개의 헥스를 추적합니다 (맵 가장자리의 헥스는 특별한 경우입니다).
물론 다른 방식으로 할 수있는 일이 많이 있습니다. 배열보다는 포인터를 사용할 수 있고, 레코드보다는 객체를 사용할 수 있으며, 다른 응답자가 제안한대로 헥스를 2 차원 배열에 저장할 수 있습니다.
바라건대, 그것에 접근하는 한 가지 방법에 대한 아이디어를 얻을 수 있습니다.
우리는 클래스 프로젝트를 위해 Settlers of Catan AI를 구현 하고이 답변 (버그가 많음)의 코드를 수정 하여 정점과 가장자리에 대한 일정한 시간 랜덤 액세스 권한이있는 보드를 만들었습니다. 재미있는 문제 였지만 보드는 많은 시간이 걸렸기 때문에 누군가가 여전히 간단한 구현을 찾고 있다면 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
나는 여기에 hexes와 함께 "재미를 위해 코딩하는 나의 자유 시간"에 앉아있다. 그리고 이렇게됩니다 ... 말로 어떻게 생겼는지 말씀 드리겠습니다.
이것은 내가 어떻게 작업 할 것인지에 대한 아이디어입니다.