Reputation: 3391
I use a nested for loop to create a grid of hexagons. This creates a square grid:
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);
}
}
I've drawn the start and end values for z & x on the image.
What I'd like is to have the grid itself also shaped hexagonally:
I think figured out the limits for x:
int greaterThan = Mathf.RoundToInt(gridSize/ 3) - 1;
int lessThan = width - greaterThan;
And that (I think) x should only be at it's min and max (0 & 6 in the examples) when z = gridSize / 2 rounded up, though I may well be wrong!
I tried putting a bunch if IFs in the loops but it quickly started to get overly complicated, I figure there must be a more 'mathsy' way to do it, but sadly I'm not mathsy!
Any idea how I can write a loop to form the required pattern?
Upvotes: 3
Views: 1405
Reputation: 23788
If @AsfK's solution is not good enough, I'll give it a try as well:
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);
}
}
With such code PrintHex(4)
results in
* * * *
* * * * *
* * * * * *
* * * * * * *
* * * * * *
* * * * *
* * * *
And if you uncomment the position v1
line instead of the one that prints "* "
, you'll get
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
similarly 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
which looks like the x
indices you want. Basing on your data I'm not really sure whether you need v1
or v2
variant. The v2
looks more consistent to me but it really depends on how your CreateCell(x, z);
treats the x = 0
case.
P.S. obviously you can inline PrintHexLine
call but it means having two different z
variables that you should not mess up with and I think it is cleaner to move that in a separate method.
Upvotes: 2
Reputation: 3391
Thanks to a hint from AsfK I solved it like this
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++;
}
}
}
Would be great if anyone can think of a more elegant solution!
Upvotes: 1
Reputation: 3476
According your excepted picture the center is the long row (gridSize = 7).
floor(7/2) = 3
(/2 because the long row is in the center)
Now, gridSize - 3 = 4
==> 4 items in your first row
Then each iterate add one till you have 7 items in one row.
Then do a minus...
it's the code (draw "*", not added spaces before and after..)
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--;
}
Upvotes: 1