C# 垂直六边形网格:获得围绕特定坐标的x个瓷砖环
问题 我想做的是从一个指定点得到x个环,并将这些环存储在C# 垂直六边形网格:获得围绕特定坐标的x个瓷砖环,c#,algorithm,hexagonal-tiles,C#,Algorithm,Hexagonal Tiles,问题 我想做的是从一个指定点得到x个环,并将这些环存储在列表中,其中内部列表是该环中所有六角的列表,六角坐标是下面定义的结构 理想情况下,我希望能够指定坐标,以及我希望搜索多少个环,并让算法为我抓取瓷砖 图像和尝试 我有一个垂直(平顶)六边形网格,看起来像这样 在代码中,每个磁贴都由一个简单的六边形坐标结构表示 有谁能帮我找到正确的方向,或者给我一个算法,让我得到六角环?我个人在这个问题上已经有一天半的时间了,我似乎无法解决这个问题。好吧,所以我想我可能已经找到了解决问题的办法。我已经测试了它
列表中,其中内部列表是该环中所有六角的列表,六角坐标是下面定义的结构
理想情况下,我希望能够指定坐标,以及我希望搜索多少个环,并让算法为我抓取瓷砖
图像和尝试
我有一个垂直(平顶)六边形网格,看起来像这样
在代码中,每个磁贴都由一个简单的六边形坐标结构表示
有谁能帮我找到正确的方向,或者给我一个算法,让我得到六角环?我个人在这个问题上已经有一天半的时间了,我似乎无法解决这个问题。好吧,所以我想我可能已经找到了解决问题的办法。我已经测试了它多达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;
}
public List GetsRingsSurroundingHex(十六进制坐标,int-maxRings)
{
//想法参考:http://gamedev.stackexchange.com/questions/51264/get-ring-of-tiles-in-hexagon-grid
//整数环=1
//通过穿过N、SE、S、SW、NW、N、NE乘以环编号,绕环移动
//戒指++
//再绕着环走一圈
//继续,直到所需的环。。。
var hexRings=新列表();
//将当前十六进制添加到列表中
var currentHex=新列表();
当前十六进制添加(坐标);
六角环。添加(当前六角);
//现在通过并添加其他环
虽然(hexRings.Count我想到的第一个想法是:为什么不为网格使用不同的编号方案?双分辨率。第一列的Hexes以2步中的0开始,第二列的Hexes以2步中的1开始。因此,您的Hexes位于具有双分辨率的规则方形网格上。然后,您可以使用bresenham circ快速确定一个六边形是否与半径为2*的圆相交的le算法。我的维基百科bresenham C例程的F#port看起来不太好:)但从我目前的探索来看,我很想认为我上面描述的方法基本上是可行的。这里,你预期的ring3导致了我的“双分辨率”方法。未渲染六边形,而是渲染圆;)您需要考虑x
和y
坐标的LSB,并相应地更正位置。您不需要圆而是六边形,因此Bresenham不可用。相反,您正在搜索距离原点1,2,3,4…个单元格的所有六边形,因此A*
会更好。请特别查看cell2scr
和SCR2单元格
用于我所指的x,y
坐标校正的LSB(它是方形网格,但问题是相同的).顺便说一句,很好sketch@BitTickler我得到的印象是OP需要所有六边形层,直到距离N
而不仅仅是一层。因此,从起点到N值的简单填充将简单快速地获得所需的所有内容。我的意思是基于网格的A*而不是图形方法!!!@killerrin您只需要填充…参见
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;
}
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;
}
}
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
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;
}