【问题标题】:Best Way to Store a Triangular/Hexagonal Grid in Python在 Python 中存储三角形/六边形网格的最佳方法
【发布时间】:2012-07-07 07:23:32
【问题描述】:

我正在用六边形瓷砖制作游戏,并决定使用三角形/六边形网格。我发现this 问题帮助我生成坐标,并稍微修改了代码以将所有坐标作为键存储在字典中,值为“。” (地板)或“X”(墙)并包含一个函数,该函数打印出地图的字符串表示形式,其中每个非空白字符代表一个六角形瓷砖。这是新代码:

deltas = [[1,0,-1],[0,1,-1],[-1,1,0],[-1,0,1],[0,-1,1],[1,-1,0]]
class HexGrid():
    def __init__(self, radius):
        self.radius = radius
        self.tiles = {(0, 0, 0): "X"}
        for r in range(radius):
            a = 0
            b = -r
            c = +r
            for j in range(6):
                num_of_hexas_in_edge = r
                for i in range(num_of_hexas_in_edge):
                    a = a+deltas[j][0]
                    b = b+deltas[j][1]
                    c = c+deltas[j][2]           
                    self.tiles[a,b,c] = "X"

    def show(self):
        l = []
        for y in range(20):
            l.append([])
            for x in range(60):
                l[y].append(".")
        for (a,b,c), tile in self.tiles.iteritems():
            l[self.radius-1-b][a-c+(2*(self.radius-1))] = self.tiles[a,b,c]
        mapString = ""
        for y in range(len(l)):
            for x in range(len(l[y])):
                mapString += l[y][x]
            mapString += "\n"
        print(mapString)

使用此代码,我可以生成半径内的所有坐标,如下所示:

import hexgrid
hg = hexgrid.HexGrid(radius)

并像这样访问坐标:

hg.tiles[a,b,c]

目前这似乎工作得很好,但我确信以这种方式存储地图肯定有一些缺点。如果有任何缺点,您能否指出它们,并提出更好的存储地图的方法?非常感谢您的宝贵时间。

【问题讨论】:

  • 什么是a、b和c?这是 3D 的吗?

标签: python dictionary hexagonal-tiles


【解决方案1】:

使用数组进行存储可能会节省一些 CPU 时间,但差异可能可以忽略不计。

但是,您错过了管理此类地图的一种非常简单的方法。将其视为行和列,只是单元格的形状略有不同。

+--+--+--+--+--+--+--+
 \/ \/ \/ \/ \/ \/ \/    Even row

  /\ /\ /\ /\ /\ /\ /\   Odd row
 +--+--+--+--+--+--+--+

或者对于六边形:

  __    __    __    __
 /  \__/  \__/  \__/  \__ Even row
 \__/  \__/ A\__/  \__/   Odd  row
 /  \__/ F\__/ B\__/  \__ Even row
 \__/  \__/ X\__/  \__/   Odd  row
 /  \__/ E\__/ C\__/  \__ Even row
 \__/  \__/ D\__/  \__/   Odd  row
 /  \__/  \__/  \__/  \__ Even row
 \__/  \__/  \__/  \__/   Odd  row

然后您可以将数据存储为常规二维数组。奇数行向右偏移 0.5,您需要计算X 的邻接步骤:上:A = (0,-2),右上:B = (1,-1),右下:C = (1,1),下:D = (0,2), 下左:E = (0,1),左上:F = (0,-1)

如果你对浪费一点内存没意见,你也可以每隔一列留空,这样邻接关系就会变得简单一些:(0,-2), (1,-1), (1,-1), (0,-2), (-1,-1), (-1,1)

【讨论】:

  • 感谢您的回答。我最喜欢在二维数组中存储六边形网格的方法是here 中描述的倾斜轴方法。这是我之前使用的。但是,我真的很喜欢我现在使用的坐标系,并且想坚持下去,所以我不会接受你的回答。不过,非常感谢您的帮助!对此,我真的非常感激! (制作这些 ascii 图一定很烦人!)
  • @RylandAlmanza:链接现在是this。维基似乎已经重组了! :-) 干杯...
【解决方案2】:

我也做了一些研究,发现了一种更简单的方法。你不必变得像你一样复杂!表格可以是简单的数组数组,没有任何特殊规则。

您想使用六角根坐标系。请参阅此处的理论:https://en.wikipedia.org/wiki/Root_system。还有https://www.redblobgames.com/grids/hexagons/

单元格(0,0)位于结构的中心,那么它有六个邻居:如众所周知的正交表(1,0),(0,1),(-1,0) , (0,-1) 以及 (1,1) , (-1-1)。其他小区也有类似的六个邻居,不需要取模!

这里有一些 Ascii 艺术以便更好地理解:

   _____       _____      ____      __
  / -2,2\_____/ 0,1 \____/2,0 \____/  \__ 
  \_____/-1,1 \_____/ 1,0\____/3,-1\__/   
  /-2,1 \_____/0,0  \____/2,-1\____/  \__     
  \_____/-1,0 \_____/1,-1\____/3,-2\__/   
  /-2,0 \_____/ 0,-1\____/2,-2\____/  \__ 
  \_____/     \_____/    \____/    \__/   

您可以计算每个单元格中心在平面中的位置(以及在屏幕中的位置),因为它遵循矢量几何规则。向量的坐标是 60° 而不是 90°:a=(0,1) 但 b=(0,87,0.5),只需将这些坐标相乘和相加!

您可能想要使用 python 库Hexy

【讨论】:

    【解决方案3】:

    不要使用 hg.tiles[a,b,c]。

    通过这种方式使图块成为一个三维列表 hg.tiles = [[[z for z in range(10)] for y in range(10)] for x in range(10)] 现在您可以使用hg.tiles[a][b][c] 访问磁贴

    PS:a = a+deltas[j][0] 应该是 a += deltas[j][0] 以此类推其他作业

    【讨论】:

    • 两者都没有实质性改变。
    • 这种方法有什么好处?是不是更快了?我会接受这个答案,但我想在接受答案之前知道为什么它是正确答案。
    • 我怀疑他的方法更快,它基本上是 3 次查找而不是创建 1 个哈希。您必须进行基准测试才能确定这一点。
    【解决方案4】:

    也许存储十六进制的最佳方式是在 python 列表或元组中;然后挑战变成如何从您的列表中检索特定的十六进制。在 python 中,一个很好的方法是构建一个十六进制坐标字典作为键,列表索引(或十六进制对象)作为值。假设您的十六进制列表不需要更改,则列表可以在完成后转换为元组。如果您将十六进制对象作为值保存在字典中,则可以完全放弃保存列表;字典直接将十六进制坐标映射到对象。

    您的代码已经生成了一系列十六进制坐标,只需将它们保存在一个列表中并同时构建您的参考字典。此外,如果您正在编写一个类来管理您的游戏板,则存储和检索的所有细节都可以隐藏在该类中。

    一些代码:

    radius = 4
    deltas = [[1,0,-1],[0,1,-1],[-1,1,0],[-1,0,1],[0,-1,1],[1,-1,0]]
    
    hexes = []
    indices = {}
    index = 0
    
    for r in range(radius):
        print("radius %d" % r)
        x = 0
        y = -r
        z = +r
    
        hexes.append((x,y,z))
        indices[(x,y,z)] = index   # Or store objects here
        index += 1
        print(x,y,z)
    
        for j in range(6):
            if j==5:
                num_of_hexes_in_edge = r-1
            else:
                num_of_hexes_in_edge = r
            for i in range(num_of_hexes_in_edge):
                x = x+deltas[j][0]
                y = y+deltas[j][1]
                z = z+deltas[j][2]
    
                hexes.append((x,y,z))
                indices[(x,y,z)] = index   # Or store objects here
                index += 1
                print(x,y,z)
    
    hexes = tuple(hexes)
    print(hexes)
    print(indices)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-07-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多