Hafızada bir hextile / hex ızgarasını nasıl temsil ederim?


119

Settlers of Catan gibi hextile ızgaralı bir tahta oyunu inşa ettiğimi varsayalım :

İmgur.com tarafından barındırılmaktadır

Her tepe ve kenarın bir niteliği (yukarıda bir yol ve yerleşim yeri) olabileceğini unutmayın.

Bu panoyu temsil eden bir veri yapısını nasıl oluşturabilirim? Her bir döşemenin komşularına, kenarlarına ve köşelerine erişme modelleri nelerdir?


ayrıca bir hilbert eğrisi de kullanabilirsiniz, bunlar, düzlemdeki bitişiklik doğrusal bir kodlamada korunacak şekilde dosyalama eğrilerini aralıklandırırlar. uzaysal indekslemeyi ve bunların nasıl kullanıldığını kontrol edin! v ilginç
pbordeaux

Yanıtlar:


156

Amit Patel, bu konuda harika bir sayfa yayınladı. O kadar kapsamlı ve harika ki, bu sorunun kesin cevabı olması gerekiyor: Altıgen Izgaralar

cubez


27
Teşekkürler :) Bu sayfa kenarları ve köşeleri kapsamıyor, ancak bunları www-cs-students.stanford.edu/~amitp/game-programming/grids adresindeki gridler makalemin Parçalar Arası İlişkiler bölümünde ele alıyorum (diyagramlar kare ızgaralar için ancak tablo eksenel altıgen ızgaralar için de formülleri içerir)
amitp

18

Böyle bir ızgara iki boyutlu bir dizide gösterilebilir:

Eğer

   2
7     3
   1   
6     4
   5

onaltılık ızgarada komşuları olan bir numara, o zaman bunu bir 2D dizisine şu şekilde koyabilirsiniz:

2 3
7 1 4
  6 5

Açıktır ki, bu ızgarada komşuluk, yalnızca yatay veya dikey olarak bitişik olmakla değil, aynı zamanda bir köşegen kullanılarak da belirlenir.

Yine de isterseniz bir grafik de kullanabilirsiniz.


Güzel. Ya kenarlar ve köşeler için veriler?
ücretli bir inek

1
Muhtemelen onları ayrı saklardım. Öncelikle döşemelere veya kenarlara / köşelere bakmanıza bakılmaksızın, verilerin diğer yarısının depolanması zor veya gereksizdir.
Joey

Amit Patel'in "ücretli inek" cevabındaki makalesine bakın.
aredridel

11

Bu makale bir İzomerik / Altıgen ızgara oyununun nasıl kurulacağını anlatıyor. Forcing Isometric and Hexagonal Maps onto a Rectangular GridBölüme ve hareket bölümüne bir göz atmanızı tavsiye ederim . Aradığınız şeyden farklı olsa da, istediğinizi nasıl yapacağınızı formüle etmenize yardımcı olabilir.


2

Büyülerle çok uğraştım. Bu gibi durumlarda, altıgen kenarları için 6 noktanın her birini takip edersiniz. Bu, onu oldukça kolay bir şekilde çizmenizi sağlar.

Hex'leri temsil eden tek bir nesne dizisine sahip olursunuz. Bu onaltılık nesnelerin her biri, başka bir "taraf" dizisine işaret eden 6 "işaretleyiciye" (veya başka bir dizinin bir dizinine) sahiptir. "Köşeler" için de aynı şey. Elbette köşelerin bitişik altıgenlere 3 işaretçisi olacaktı ve kenarlarda 2 tane olacaktı.

Yani, bir altıgen şunun gibi bir şey olabilir: X, Y, Nokta (6), Köşeler (6), Kenarlar (6)

Sonra bir Hex dizisi, köşe dizisi ve yan diziniz var.

O zaman bir altılık veya her neyse, köşeleri / kenarları bulmak oldukça basittir.

İşaretçi dediğimde, aynı kolaylıkla tepe veya yan dizideki öğeye işaret eden bir tamsayı veya her neyse olabilir. Ve elbette diziler liste veya her neyse olabilir.


0
   2
7     3
   1   
6     4
   5

Ayrıca haritanızın satırlarını 'düzleştirmeyi' deneyebilirsiniz. Bu örnek için şöyle olacaktır:

  2
7 1 3
6 5 4

Bazen tek satırda satırlara sahip olmak daha kullanışlıdır: P


1
Bu, bazı karışık komşu kontrol kodlarına sahip olabilir, çünkü örneğin, 1 ve 6 komşu, ancak 3 ve 5 değil, yine de aynı göreceli konumlara sahipler.
Bernhard Barker

0

Aşağıdakine benzer bir şey öneririm (Delphi tarzı bildirimler kullanacağım):

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;

Her altıgen altı köşeye ve altı köşeye sahiptir. Her kenar, bitişik iki altıgenini izler ve her köşe, bitişik üç altıgenini izler (haritanın kenarlarındaki altıgenler özel bir durum olacaktır).

Elbette farklı bir şekilde yapabileceğiniz birçok şey var. Diziler yerine işaretçileri kullanabilir, kayıtlar yerine nesneleri kullanabilir ve diğer cevaplayıcıların önerdiği gibi hex'lerinizi iki boyutlu bir dizide saklayabilirsiniz.

Umarım, bu size yaklaşmanın bir yolu hakkında bazı fikirler verebilir.


0

Bir sınıf projesi için Settlers of Catan AI uyguladık ve köşelere ve kenarlara sabit zamanlı rastgele erişime sahip bir Pano oluşturmak için bu yanıttan (hatalıydı) kodu değiştirdik . Bu eğlenceli bir sorundu, ancak yönetim kurulu çok zaman aldı, bu nedenle hala basit bir uygulama arayan birileri varsa, işte Python kodumuz:

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

Bu cevap berbat. Hiçbir şeyi açıklamadan tonlarca kod yapıştırdınız (kodu kimin yazdığı hariç). Burada sorun olmasa bile, kodun kendisi korkunç. Hiçbir belge dizisi yok, neredeyse hiç yorum yok ve dahil edilen birkaç yorum anlaşılmaz (Mantık, bunun getEdgesOfVertex ve sonra her kenar için getVertexEnds, == vertex olan üçünü çıkararak olduğunu düşünmekten).
Carl Smith

0

Ben burada büyülerle "eğlence için kodlama" boş zamanımda oturuyorum. Ve şöyle devam ediyor ... Size neye benzediğini kelimelerle anlatacağım.

  1. Altıgen: Altı komşu altıgeni vardır. Komşu her altıgen karo için referans sağlayabilir. Size nelerden oluştuğunu söyleyebilir (su, kaya, toz). Kendini başkalarına bağlayabilir ve bunun tersi de geçerlidir. Hatta çevreleyen diğerlerini otomatik olarak bağlayarak daha büyük bir alan yaratabilir ve veya tüm alanların komşuları tarafından adreslenebilmesini sağlayabilir.
  2. Bir bina, üç yola ve üç Hex Karosuna başvurur. Size kim olduklarını söyleyebilirler.
  3. Bir yol, komşu karolar tarafından işaretlendiklerinde iki altıgen ve diğer yolları referans alır. Hangi karoların olduğunu ve hangi yollara veya binalara bağlandıklarını söyleyebilirler.

Bu sadece bunun üzerinde nasıl çalışacağım hakkında bir fikir.


0

2B bir dizi oluşturabilir ve ardından geçerli konumları şu şekilde düşünebilirsiniz:

  • Çift sayılı satırlarda (0,2,4, ...): tek sayılı hücreler.
  • Tek sayılı satırlarda (1,3,5, ...): çift sayılı hücreler.

Her hücre için komşuları:

  • Aynı sütun, 2 sıra yukarı
  • Aynı sütun, 2 satır aşağı
  • 1 sola + 1 yukarı
  • 1 sol + 1 aşağı
  • 1 sağ + 1 yukarı
  • 1 sağ + 1 aşağı

Resim: Onaltılık Izgara

X işaretleri altıgenlerdir. birbirine çapraz olan x komşulardır. | dikey komşuları birbirine bağlar.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.