以六边形模式逐步遍历二维数组

3

我使用嵌套的for循环来创建六边形的网格。这将创建一个正方形的网格:

for (int z = 0; z < gridSize; z++)
{
    for (int x = 0; x < gridSize; x++)
    {
            // creates verts for a hexagon shape which later form a mesh
            // x and z form the basis of the Vector3 position of the center 
            // of each hexagon
            CreateCell(x, z); 
    }
}

enter image description here

我已经在图像上绘制了z和x的起始和结束值。
我希望的是将网格本身也呈六边形形状:

enter image description here

我想已经找到了x的限制:

int greaterThan = Mathf.RoundToInt(gridSize/ 3) - 1;
int lessThan = width - greaterThan;

我认为x只有在z等于gridSize的一半向上取整时(例如示例中的0和6),才应该达到最小值和最大值,但我可能是错的!

我尝试在循环中放置了许多if语句,但很快就变得过于复杂了,我认为必须有更“数学”的方法来解决它,但可惜我不太懂数学!

你有什么办法可以编写一个循环以形成所需的模式吗?

3个回答

2
如果@AsfK的解决方案不够好,我也会尝试一下:

如果@AsfK的解决方案不够好,我也会尝试一下:

    private static void PrintHexLine(int z, int size)
    {
        if (z >= size)
        {
            z = 2 * size - 2 - z;
        }
        int start = size - z - 1;
        int end = start + size + z;
        for (int x = 0; x < start; x++)
        {
            Console.Write(" ");
        }
        for (int x = start; x < end; x++)
        {
            Console.Write("* ");
            //Console.Write((x - start / 2) + " "); // position v1
            //Console.Write((x - (start + 1) / 2) + " "); // position v2

        }
        Console.WriteLine();
    }

    public static void PrintHex(int size)
    {
        for (int z = 0; z < 2 * size - 1; z++)
        {
            PrintHexLine(z, size);
        }
    }

使用这样的代码PrintHex(4)会产生以下结果:

   * * * *
  * * * * *
 * * * * * *
* * * * * * *
 * * * * * *
  * * * * *
   * * * *

如果您取消注释position v1这一行,而不是打印"* "的那一行,您将得到:
   2 3 4 5
  1 2 3 4 5
 1 2 3 4 5 6
0 1 2 3 4 5 6
 1 2 3 4 5 6
  1 2 3 4 5
   2 3 4 5

同样地,position v2
   1 2 3 4
  1 2 3 4 5
 0 1 2 3 4 5
0 1 2 3 4 5 6
 0 1 2 3 4 5
  1 2 3 4 5
   1 2 3 4

这看起来像是您想要的 x 索引。根据您的数据,我不确定您需要 v1 还是 v2 变量。对我来说,v2 更加一致,但这确实取决于您的 CreateCell(x, z); 如何处理 x = 0 的情况。

P.S. 显然,您可以内联调用 PrintHexLine,但这意味着您应该不要弄混两个不同的 z 变量,而且我认为将其移动到一个单独的方法中更加清晰。


1
根据您期望的图片,中心是长行(gridSize = 7)。
现在,floor(7/2)= 3(/2因为长行在中心)。
然后,gridSize-3 = 4 ==> 第一行有4个项目。
然后每次迭代都加一个,直到一行中有7个项目。
然后进行减法......
这是代码(绘制“*”,不要在前后添加空格...)。
int gridSize = 7;
int center = 7/2;
int delta = 1;
for (int r = 0; r < gridSize; r++) {
    for (int c = gridSize - center; c < gridSize + delta; c++){
        System.out.print("*");
        // location of c = c - delta (position)
    }
    System.out.println();
    if (r < center)
        delta++;
    else
        delta--;
}

如果您使用sin(x)和cos(x)的圆算法,则沿着六边形周长的每个点相隔60度。下面和左侧的六边形中心为210度,右下方的六边形中心为150度。 - EddingtonsMonkey
@EddingtonsMonkey,看起来真的很酷,但这不是我的强项 :) 很高兴能看到你的完整答案! - AsfK
@AsfK - 你的代码产生了一些非常奇怪的结果,所以我不能接受它作为答案,但它确实让我朝着正确的方向前进,跟踪行大小并在中点之前/之后递增或递减。感谢你的帮助。 - Absinthe

1
感谢AsfK的提示,我这样解决了。
int xL, xU, xMid, zM2;
xL = Mathf.FloorToInt(width / 3) - 1;
xU = (width - xL) + 1;
xMid = Mathf.FloorToInt(width / 2);

for (int z = 0; z < height; z++)
{
    for (int x = xL; x < xU; x++)
    {
        CreateCell(x, z);
    }

    zM2 = z % 2;

    if(z < xMid)
    {
        if (zM2 == 0)
        {
            xL--;
        }
        if (z > 0 && zM2 == 1)
        {
            xU++;
        }
    } else
    {
        if (zM2 == 1)
        {
            xL++;
        }
        if (zM2 == 0)
        {
            xU--;
        }
        if (z == width - 1)
        {
            xL--;
            xU++;
        }
    }
}

如果有更优雅的解决方案,那就太棒了!


Absinthe,看一下我的解决方案,如果这不是你需要的,请告诉我。也许我能修复它。 - SergGr

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接