मैं मेमोरी में हेक्सटाइल / हेक्स ग्रिड का प्रतिनिधित्व कैसे करूं?


119

मैं एक hextile ग्रिड के साथ एक बोर्ड खेल के निर्माण कर रहा हूँ, जैसे कहो द सेटेलर्स ऑफ कटान :

Imgur.com द्वारा होस्ट किया गया

ध्यान दें कि प्रत्येक शीर्ष और किनारे में एक विशेषता (ऊपर एक सड़क और निपटान) हो सकती है।

मैं एक डेटा संरचना कैसे बनाऊंगा जो इस बोर्ड का प्रतिनिधित्व करती है? प्रत्येक टाइल के पड़ोसियों, किनारों और कोने तक पहुंचने के लिए पैटर्न क्या हैं?


आप एक हिल्बर्ट वक्र का भी उपयोग कर सकते हैं, वे फाइलिंग कर्व्स को इस तरह फैला रहे हैं कि विमान में आसन्न एक रैखिक एन्कोडिंग में संरक्षित है। स्थानिक अनुक्रमण की जाँच करें और ये कैसे उपयोग किए जाते हैं! वी दिलचस्प
pbordeaux

जवाबों:


156

अमित पटेल ने इस विषय पर एक अद्भुत पृष्ठ पोस्ट किया है । यह इतना व्यापक और अद्भुत है कि इस प्रश्न का निश्चित उत्तर होना चाहिए: हेक्सागोनल ग्रिड

Cubez


27
धन्यवाद :) वह पृष्ठ किनारों और रेखाओं को कवर नहीं करता है, लेकिन मैं उन्हें www-cs-students.stanford.edu/~amitp/game-programming/grids (चित्र) पर अपने ग्रिड लेख के भागों अनुभाग के बीच संबंधों में शामिल करता हूं वर्ग ग्रिड के लिए लेकिन तालिका में अक्षीय हेक्स ग्रिड के लिए सूत्र भी शामिल हैं)
amitp

18

इस तरह के ग्रिड को द्वि-आयामी सरणी में दर्शाया जा सकता है:

अगर

   2
7     3
   1   
6     4
   5

हेक्स ग्रिड में अपने पड़ोसियों के साथ नंबर एक है, तो आप इसे 2 डी सरणी में डाल सकते हैं:

2 3
7 1 4
  6 5

स्पष्ट रूप से पड़ोसी-नेस इस ग्रिड में न केवल क्षैतिज या लंबवत आसन्न होने पर, बल्कि एक विकर्ण का उपयोग करके निर्धारित किया जाता है।

आप एक ग्राफ का उपयोग कर सकते हैं, यदि आप चाहें, तो।


ठंडा। किनारों और कोने के डेटा के बारे में क्या?
एक भुगतान किया बेवकूफ

1
मैं शायद उन्हें अलग से स्टोर करूँगा। भले ही आप मुख्य रूप से टाइलों या किनारों / कोणों को देखते हों, लेकिन डेटा का आधा हिस्सा स्टोर करने के लिए या तो दर्दनाक या निरर्थक है।
जॉय

अमित पटेल का लेख "एक भुगतान किया बेवकूफ" उत्तर में देखें।
14

11

यह लेख एक आइसोमेरिक / हेक्सागोनल ग्रिड गेम स्थापित करने के तरीके के माध्यम से जाता है। मेरा सुझाव है कि आप Forcing Isometric and Hexagonal Maps onto a Rectangular Gridअनुभाग और आंदोलन अनुभाग पर एक नज़र डालें । यद्यपि यह इससे अलग है कि आप जो खोज रहे हैं वह आपको यह बनाने में मदद कर सकता है कि आप क्या चाहते हैं।


2

मैंने हेक्स के साथ बहुत कुछ निपटाया है। इस तरह के मामलों में, आप हेक्स की सीमाओं के लिए 6 बिंदुओं में से प्रत्येक को ट्रैक करते हैं। इससे आप इसे आसानी से खींच सकते हैं।

आपके पास ऑब्जेक्ट्स का एक एकल सरणी होगा जो हेक्स का प्रतिनिधित्व करता है। इन हेक्स ऑब्जेक्ट्स में से प्रत्येक में 6 "पॉइंटर्स" (या किसी अन्य सरणी के लिए एक इंडेक्स) है जो "पक्षों" के अन्य सरणी की ओर इशारा करता है। "कोने" के लिए एक ही बात। बेशक कोने में 3 बिंदु समीपवर्ती हेक्स होंगे, और पक्ष 2 होंगे।

तो, एक हेक्स कुछ इस तरह हो सकता है: एक्स, वाई, प्वाइंट (6), कार्यक्षेत्र (6), साइड्स (6)

फिर आपके पास हेक्स ऐरे, वर्टिस ऐरे, और साइड ऐरे हैं।

फिर हेक्स या जो कुछ भी है उसके लिए शीर्ष / भुजाओं को ढूंढना बहुत सरल है।

जब मैं कहता हूं कि पॉइंटर आसानी से वर्टिकल या साइड ऐरे या जो भी हो, उस एलिमेंट की ओर इशारा करते हुए आसानी से हो सकता है। और बेशक सरणियों की सूची या जो कुछ भी हो सकता है।


0
   2
7     3
   1   
6     4
   5

आप अपने नक्शे की पंक्तियों को 'समतल' करने का प्रयास कर सकते हैं। इस उदाहरण के लिए यह होगा:

  2
7 1 3
6 5 4

इसकी कभी-कभी एक पंक्ति में पंक्तियों के लिए अधिक उपयोगी होता है: पी


1
यह कुछ गन्दा पड़ोसी जाँच कोड हो सकता है, क्योंकि, उदाहरण के लिए, 1 और 6 पड़ोसी हैं, लेकिन 3 और 5 नहीं हैं, फिर भी उनके समान रिश्तेदार स्थान हैं।
बर्नहार्ड बार्कर

0

मैं निम्नलिखित जैसा कुछ सुझाव दूंगा (मैं डेल्फी-शैली घोषणाओं का उपयोग करूंगा):

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

हमने एक क्लास प्रोजेक्ट के लिए केतन एआई के एक सेटलर्स को लागू किया, और इस उत्तर (जो कि छोटी गाड़ी थी) से संशोधित कोड को बोर्ड बनाने के लिए निरंतर समय के साथ-साथ कोने और किनारों तक पहुंच बनाई। यह एक मजेदार समस्या थी, लेकिन बोर्ड को बहुत समय लग गया था, इसलिए अगर किसी को अभी भी एक साधारण कार्यान्वयन की तलाश है तो यहां हमारा पायनियर कोड है:

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, तीनों को बाहर निकाल रहा है जो == वर्टेक्स हैं)।
कार्ल स्मिथ

0

मैं यहाँ "अपने खाली समय में मौज मस्ती के लिए कोडिंग" कर रहा हूँ। और यह इस तरह से चला जाता है ... मैं आपको बताऊंगा कि यह शब्दों में कैसा दिखता है।

  1. षट्कोण: इसमें छह पड़ोसी षट्कोण हैं। यह प्रत्येक पड़ोसी हेक्स टाइल के लिए संदर्भ प्रदान कर सकता है। यह आपको बता सकता है कि इसमें क्या है (पानी, चट्टान, धूल)। यह खुद को दूसरों से जोड़ सकता है और इसके विपरीत। यह अपने आप ही अपने आसपास के अन्य लोगों को एक बड़ा क्षेत्र बनाने के लिए कनेक्ट कर सकता है या यह सुनिश्चित कर सकता है कि सभी क्षेत्रों को इसके पड़ोसियों द्वारा सराहा जा सकता है।
  2. एक इमारत में तीन सड़कों और तीन हेक्स टाइलों का संदर्भ है। वे आपको बता सकते हैं कि वे कौन से हैं।
  3. एक सड़क दो हेक्स और अन्य सड़कों का संदर्भ देती है जब वे पड़ोसी टाइलों से प्रभावित होते हैं। वे बता सकते हैं कि कौन सी टाइलें हैं और वे किन सड़कों या इमारतों से जुड़ती हैं।

यह सिर्फ एक विचार है कि मैं इस पर कैसे काम करूंगा।


0

आप एक 2 डी सरणी बना सकते हैं और तब मान्य पदों पर विचार कर सकते हैं:

  • सम संख्या वाली पंक्तियों पर (0,2,4, ...): विषम संख्या वाली कोशिकाएँ।
  • विषम संख्या वाली पंक्तियों पर (1,3,5, ...): सम संख्या वाली कोशिकाएं।

प्रत्येक सेल के लिए, उसके पड़ोसी होंगे:

  • समान कॉलम, 2 पंक्तियाँ
  • समान कॉलम, 2 पंक्तियाँ नीचे
  • 1 बायां + 1 ऊपर
  • 1 बायां + 1 नीचे
  • 1 राइट + 1 अप
  • 1 राइट + 1 डाउन

चित्रण: हेक्स ग्रिड

एक्स मार्क्स हेक्स हैं। x जो एक दूसरे के लिए विकर्ण हैं, पड़ोसी हैं। | ऊर्ध्वाधर पड़ोसियों को जोड़ता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.