gpt4 book ai didi

c# - 垂直六角网格 : Get x rings of tiles surrounding a specific coordinate

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:23:57 25 4
gpt4 key购买 nike

问题

我想做的是从指定点获取 x 个环,并将这些环存储在 List<List<HexCoordinate>> 中其中内部列表是该环中所有六边形的列表,HexCoordinate 是下面定义的结构

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

图像和尝试

我有一个垂直(平顶)六角网格,看起来像这样 Overall Hex Grid

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

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);
}
}

特别是对于我的例子,我画了一张图片来尝试自己解决这个问题 Close Up Example

我尝试过的

因为我需要展示我已经尝试过的东西,所以这就是我到目前为止尝试过的东西

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

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 ...从下面我的控制台中的输出可以看出(应该手动编辑的内容)

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

谁能帮助我找到正确的方向,或者提供一个算法让我得到六角环?我个人在这个问题上已经被困了大约一天半了,但我似乎无法弄清楚这个问题。

最佳答案

好吧,我想我可能已经找到了解决问题的方法。我已经测试了多达 4 个环,它为我提供了相应环中所有正确的六角形。

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;
}

关于c# - 垂直六角网格 : Get x rings of tiles surrounding a specific coordinate,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36828748/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com