首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >垂直六角形网格:获取围绕特定坐标的x个瓷砖环

垂直六角形网格:获取围绕特定坐标的x个瓷砖环
EN

Stack Overflow用户
提问于 2016-04-24 20:49:33
回答 1查看 988关注 0票数 3

问题

我要做的是从一个指定的点获取x个环数,并将这些环存储在一个List<List<HexCoordinate>>中,其中内部列表是该环中所有十六进制的列表,而HexCoordinate是下面定义的一个结构。

理想情况下,我希望能够指定坐标,以及我想搜索出多少个环,并让算法为我抓取瓷砖。

图片与尝试

我有一个垂直的(平顶)十六进制网格,看起来像这样

在代码中,每个块都由一个简单的HexCoordinate结构GitHub表示。

代码语言:javascript
复制
public struct HexCoordinate : IEquatable<HexCoordinate>
{
    public int X { get; private set; }
    public int Y { get; private set; }

    public HexCoordinate(int x, int y)
    {
        X = x;
        Y = y;
    }

    public HexCoordinate North() => this + new HexCoordinate(0, -1);
    public HexCoordinate South() => this + new HexCoordinate(0, 1);

    public HexCoordinate West() => this + new HexCoordinate(-1, 0);
    public HexCoordinate East() => this + new HexCoordinate(1, 0);

    public HexCoordinate NorthWest() => this + new HexCoordinate(-1, -1);
    public HexCoordinate NorthEast() => this + new HexCoordinate(1, -1);

    public HexCoordinate SouthWest() => this + new HexCoordinate(-1, 1);
    public HexCoordinate SouthEast() => this + new HexCoordinate(1, 1);

    public bool Equals(HexCoordinate other)
    {
        return X == other.X &&
               Y == other.Y;
    }
    public static HexCoordinate operator +(HexCoordinate one, HexCoordinate two)
    {
        return new HexCoordinate(one.X + two.X, one.Y + two.Y);
    }
}

特别是对于我的例子,我有一个我画出来的图像,试图自己解决这个问题。

我已经尝试过的

因为我需要展示我已经尝试过的东西,这就是我迄今所尝试过的。

代码语言:javascript
复制
public const int MAX_RINGS = 3;
public List<List<HexCoordinate> GetsRingsWithinHex(HexCoordinate coordinate, int maxRings = MAX_RINGS)
{
    // Attempt One Pseudocode
    // reference: http://gamedev.stackexchange.com/questions/51264/get-ring-of-tiles-in-hexagon-grid
    // int ring = 1
    //   Travel around the ring by traversing N,SE,S,SW,NW,N,NE multiplied by the ring number
    //   ring++
    //      Travel Around ring again
    //      cont until desired ring...

    var hexRings = new List<List<HexCoordinate>>();

    // Add in the current hex to the list
    var currentHex = new List<HexCoordinate>(); 
    currentHex.add(coordinate);
    hexRings.Add(currentHex);

    // Now go through and add the other rings
    while (hexRings.Count <= maxRings)
    {
        var ring = new List<HexCoordinate>();
        HexCoordinate tempCoordinate = coordinate;
        int currentRingNumber = hexRings.Count;

        // We start off by going north to the correct ring, and then adding it to our list
        for (int i = 0; i < currentRingNumber; i++)
        {
            tempCoordinate = tempCoordinate.North();
        }
        ring.add(tempCoordinate);

        // After that, we proceed to go clockwise around the ring until we come back to the start
        for (int i = 0; i < currentRingNumber; i++)
        {
            tempCoordinate = tempCoordinate.SouthEast();

            // If the ring is an odd number, you need to re-align the coordinates back to where whey should be
            if (IntExtensions.IsOdd(i)) tempCoordinate = tempCoordinate.North();

            ring.add(tempCoordinate);
        }

        // The rightmost segment is east because we can go straight down the required number of times
        for (int i = 0; i < currentRingNumber; i++)
        {
            tempCoordinate = tempCoordinate.South();
            ring.add(tempCoordinate);
        }

        // We utilize Current Ring - 1 because we only want this to run on rings that are greater than 1
        for (int i = 0; i < currentRingNumber - 1; i++)
        {
            tempCoordinate = tempCoordinate.SouthWest();
            ring.add(tempCoordinate);
        }

        // Coming into this statement, we are now at the bottom 3 coordinates.
        // Since our grid is laid out vertically, we can assume that these three hexes will be directly west of eachother
        // So we only have to go west twice to make our way to the next north segment 
        for (int i = 0; i < 2; i++)
        {
            tempCoordinate = tempCoordinate.West();
            ring.add(tempCoordinate);
        }

        // We utilize Current Ring - 1 because we only want this to run on rings that are greater than 1
        for (int i = 0; i < currentRingNumber - 1; i++)
        {
            tempCoordinate = tempCoordinate.NorthWest();
            ring.add(tempCoordinate);
        }

        // The left most segment is easy because we can just go straight up
        for (int i = 0; i < currentRingNumber; i++)
        {
            tempCoordinate = tempCoordinate.North();
            ring.add(tempCoordinate);
        }

        // We utilize Current Ring - 1 because we only want this to run on rings that are greater than 1
        for (int i = 0; i < currentRingNumber - 1; i++)
        {
            tempCoordinate = tempCoordinate.NorthEast();

            // If the ring is an even number, you need to re-align the coordinates back to where whey should be
            if (IntExtensions.IsEven(i)) tempCoordinate = tempCoordinate.South();

            ring.add(tempCoordinate);
        }

        // Finally, we add the ring to our system rings and loop until we no longer fit the criteria
        hexRings.Add(ring);
    }

    return hexRings;
}

如果需要的话,这是我的IntExtensions

代码语言:javascript
复制
public static class IntExtensions
{
    public static bool IsBetween(this int num, int low, int high)
    {
        return num >= low && num <= high;
    }

    public static bool IsOdd(this int value)
    {
        return value % 2 != 0;
    }

    public static bool IsEven(this int value)
    {
        return value % 2 == 0;
    }
}

我目前的问题是,这个算法适用于第一环和第二环,但一旦到达第三环(如果我超过3),沿底部和角的坐标开始被1.从下面控制台中的输出可以看出(应该手工编辑的输出)

代码语言:javascript
复制
Ring 0 - System 5, 5

Ring 1 - System 5, 4
Ring 1 - System 6, 5
Ring 1 - System 6, 6
Ring 1 - System 5, 6
Ring 1 - System 4, 6
Ring 1 - System 4, 5

Ring 2 - System 5, 3
Ring 2 - System 6, 4
Ring 2 - System 7, 4
Ring 2 - System 7, 5
Ring 2 - System 7, 6
Ring 2 - System 6, 7
Ring 2 - System 5, 7
Ring 2 - System 4, 7
Ring 2 - System 3, 6
Ring 2 - System 3, 5
Ring 2 - System 3, 4
Ring 2 - System 4, 4

Ring 3 - System 5, 2
Ring 3 - System 6, 3
Ring 3 - System 7, 3
Ring 3 - System 8, 4
Ring 3 - System 8, 5
Ring 3 - System 8, 6
Ring 3 - System 8, 7
Ring 3 - System 7, 8 //(Should be 7, 7)
Ring 3 - System 6, 9 //(Should be 6, 8)
Ring 3 - System 5, 9 //(Should be 5, 8)
Ring 3 - System 4, 9 //(Should be 4, 8)
Ring 3 - System 3, 8 //(Should be 3, 7)
Ring 3 - System 2, 7 
Ring 3 - System 2, 6
Ring 3 - System 2, 5
Ring 3 - System 2, 4
Ring 3 - System 3, 4 //(Should be 3, 3)
Ring 3 - System 4, 3

有没有人能帮我找到正确的方向,或者给我一种算法,让我可以得到六边形的环?我个人在这个问题上已经被困了大约一天半了,我似乎无法解决这个问题。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-04-25 09:01:29

好吧,我想我可能已经想出了解决问题的办法。我已经测试了多达4个环,它给了我所有正确的六边形在相应的戒指。

代码语言:javascript
复制
public List<List<HexCoordinate>> GetsRingsSurroundingHex(HexCoordinate coordinate, int maxRings)
    {
        // idea reference: http://gamedev.stackexchange.com/questions/51264/get-ring-of-tiles-in-hexagon-grid
        // int ring = 1
        //   Travel around the ring by traversing N,SE,S,SW,NW,N,NE multiplied by the ring number
        //   ring++
        //      Travel Around ring again
        //      cont until desired ring...

        var hexRings = new List<List<HexCoordinate>>();

        // Add in the current hex to the list
        var currentHex = new List<HexCoordinate>();
        currentHex.Add(coordinate);
        hexRings.Add(currentHex);

        // Now go through and add the other rings
        while (hexRings.Count <= maxRings)
        {
            var ring = new List<HexCoordinate>();
            HexCoordinate tempCoordinate = coordinate;
            int currentRingNumber = hexRings.Count;

            // We start off by going north to the correct ring, and then adding it to our list
            for (int i = 0; i < currentRingNumber; i++)
            {
                tempCoordinate = tempCoordinate.North();
            }
            ring.Add(tempCoordinate);

            // After that, we proceed to go clockwise around the ring until we come back to the start
            for (int i = 0; i < currentRingNumber; i++)
            {
                tempCoordinate = tempCoordinate.SouthEast();

                // If the ring is an odd number, you need to re-align the coordinates back to where whey should be
                if (IntExtensions.IsOdd(i)) tempCoordinate = tempCoordinate.North();

                ring.Add(tempCoordinate);
            }

            // The rightmost segment is east because we can go straight down the required number of times
            for (int i = 0; i < currentRingNumber; i++)
            {
                tempCoordinate = tempCoordinate.South();
                ring.Add(tempCoordinate);
            }

            // We utilize Current Ring - 1 because we only want this to run on rings that are greater than 1
            for (int i = 0; i < currentRingNumber - 1; i++)
            {
                if (currentRingNumber.IsEven())
                {
                    if (i.IsEven())
                        tempCoordinate = tempCoordinate.SouthWest();
                    else
                        tempCoordinate = tempCoordinate.West();
                }
                else
                {
                    if (i.IsEven())
                        tempCoordinate = tempCoordinate.West();
                    else
                        tempCoordinate = tempCoordinate.SouthWest();
                }

                ring.Add(tempCoordinate);
            }

            // Coming into this statement, we are now at the bottom 3 coordinates.
            // Since our grid is laid out vertically, we can assume that these three hexes will be directly west of each other
            // So we only have to go west twice to make our way to the next north segment 
            for (int i = 0; i < 2; i++)
            {
                tempCoordinate = tempCoordinate.West();
                ring.Add(tempCoordinate);
            }

            // We utilize Current Ring - 1 because we only want this to run on rings that are greater than 1
            for (int i = 0; i < currentRingNumber - 1; i++)
            {
                if (i.IsEven())
                    tempCoordinate = tempCoordinate.NorthWest();
                else
                    tempCoordinate = tempCoordinate.West();

                ring.Add(tempCoordinate);
            }

            // The left most segment is easy because we can just go straight up
            for (int i = 0; i < currentRingNumber; i++)
            {
                tempCoordinate = tempCoordinate.North();
                ring.Add(tempCoordinate);
            }

            // We utilize Current Ring - 1 because we only want this to run on rings that are greater than 1
            for (int i = 0; i < currentRingNumber - 1; i++)
            {
                if (currentRingNumber.IsEven())
                {
                    if (i.IsEven())
                        tempCoordinate = tempCoordinate.East();
                    else
                        tempCoordinate = tempCoordinate.NorthEast();
                }
                else
                {
                    if (i.IsEven())
                        tempCoordinate = tempCoordinate.NorthEast();
                    else
                        tempCoordinate = tempCoordinate.East();
                }

                ring.Add(tempCoordinate);
            }

            // Finally, we add the ring to our system rings and loop until we no longer fit the criteria
            hexRings.Add(ring);
        }

        return hexRings;
    }
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36828748

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档