I've been trying to develop an algorithm to show which tiles you can move to on a square board based on these parameters:
-You move your characters around the board each turn to any tile within their movement speed.
-Each horizontal/vertical movement is worth 1 tile.
-Each diagonal is worth 1.5 (rounded down- so the first diagonal is worth 1, and the second is worth 2, and back to 1, etc.).
-You cannot move a character onto a tile that has another character on it, so you must go around.
NOTE: I don't currently check to see if a tile is occupied, I want to take this one step at a time, and the first step is getting a correct result of which tiles the character can go to.
I have a 3d array the size of the board. The third dimension has two layers, the first one is initialized as all 99 except the character you are moving (the origin), which is set to 0. This dimension contains the distance to the origin from each tile. The other layer contains the number of diagonals it took to get to that tile.
Basically I have a recursive function that checks each adjacent tile for the lowest distance to the origin, and sets the current tile to that lowest distance number +1 (or +2 if it is the second diagonal). It moves out from the origin recursively, using the tiles it already filled in to generate a map of all of the potential tiles that it can move to.
`
const int edgeOfBoard = 15;
static int[,,] movementCount = new int[edgeOfBoard, edgeOfBoard, 2]; //movement speed/diagonals tracking matrix
static void Main()
{
int movementSpeed = 4; //number of tiles character can move
int x = 7; //x starting position
int y = 7; //y starting position
for(int i = 0; i < edgeOfBoard; i++) //fill movementCount with 99
{
for(int j = 0; j < edgeOfBoard; j++)
{
movementCount[i, j, 0] = 99;
}
}
movementCount[x, y, 0] = 0; //set origin (character's location) as 0 movements from itself
pathfinder(movementSpeed, x, y, 0); //run pathfinder algorithm
print(); //print result
}
private static void print() //print result
{
for(int y = 0; y < edgeOfBoard; y++) //print movement to get to a given tile
{
for(int x = 0; x < edgeOfBoard; x++)
{
if(movementCount[x, y, 0] == 99) //replace 99s with " " to make it easier to read
{
Console.Write("| ");
}else
{
Console.Write("|" + movementCount[x, y, 0]);
}
}
Console.WriteLine("|");
}
Console.WriteLine();
for(int y = 0; y < edgeOfBoard; y++) //print diagonals needed to get to a given tile
{
for(int x = 0; x < edgeOfBoard; x++)
{
if(movementCount[x, y, 1] == 0)
{
Console.Write("| ");
}else
{
Console.Write("|" + movementCount[x, y, 1]);
}
}
Console.WriteLine("|");
}
}
internal static void pathfinder(int movementSpeed, int x, int y, int depth)
{
if (depth <= movementSpeed) //cuts off when limit is reached
{
for (int Y = -1; Y <= 1; Y++) //checks all adjacent tiles
{
for (int X = -1; X <= 1; X++)
{
//Console.WriteLine("y = " + y + ", Y = " + Y + ", x = " + x + ", X = " + X + ", mvC[] = " + movementCount[x + X, y + Y, 0]);
//Checks if current adjacent tile subject is in bounds and is not the origin of the search
if (y + Y >= 0 && y + Y <= edgeOfBoard && x + X >= 0 && x + X <= edgeOfBoard && !(Y == 0 && X == 0) && (movementCount[x + X, y + Y, 0] == 99))
{
int[] lowestAdjacent = findLowestAdjacent(x + X, y + Y); //find the lowest adjacent tile
if (lowestAdjacent[0] + 1 <= movementSpeed) //if it is within the movement speed, add it to the matrix
{
movementCount[x + X, y + Y, 0] = lowestAdjacent[0] + 1; //update movement speed for subject tile
movementCount[x + X, y + Y, 1] = lowestAdjacent[1]; //update number of diagonals needed for subject tile
//print();
}
}
}
}
for (int Y = -1; Y <= 1; Y++) //mmove into already checked tiles to recursively check their adjacent tiles
{
for (int X = -1; X <= 1; X++)
{
if (y + Y >= 0 && y + Y <= 15 && x + X >= 0 && x + X <= 15 && !(Y == 0 && X == 0) && (movementCount[x + X, y + Y, 0] != 99) && (movementCount[x + X, y + Y, 0] < movementSpeed))
{
pathfinder(movementSpeed, x + X, y + Y, depth + 1);
}
}
}
}
}
private static int[] findLowestAdjacent(int x, int y) //finds lowest number of movements to get to subject tile (x, y)
{
int[] lowestRtrn = { 99, 0 }; //movement, diagonals
int lowest = 99;
for (int Y = -1; Y <= 1; Y++) //checks each adjacent tile
{
for (int X = -1; X <= 1; X++)
{
if (y + Y >= 0 && y + Y <= edgeOfBoard && x + X >= 0 && x + X <= edgeOfBoard) //ensures it is within bounds
{
int diag = isDiagonalMovement(x, y, x + X, y + Y) ? diagonalMovementIncrease(movementCount[x + X, y + Y, 1] + 1) : 0; //checks whether or not it should be diagonally increased
if ((movementCount[x + X, y + Y, 0] + diag) < lowest) //adds to result if lower than current
{
lowest = movementCount[x + X, y + Y, 0] + diag;
lowestRtrn[1] = movementCount[x + X, y + Y, 1] + (isDiagonalMovement(x, y, x + X, y + Y) ? 1 : 0);
}
}
}
}
lowestRtrn[0] = lowest;
return lowestRtrn;
}
private static int diagonalMovementIncrease(int diagonalMovements) //checks if diagonal is second diagonal (+2 instead of +1)
{
return diagonalMovements % 2 == 0 ? 1 : 0;
}
private static bool isDiagonalMovement(int x, int y, int X, int Y) //checks if (x, y) is diagonal from (X, Y)
{
if (
(x + 1 == X && y + 1 == Y) ||
(x - 1 == X && y + 1 == Y) ||
(x + 1 == X && y - 1 == Y) ||
(x - 1 == X && y - 1 == Y)
)
{
return true;
}
else
{
return false;
}
}`
This is the result when printed with a movement speed of 4, starting at 7, 7 on a 15x15 grid (simply for testing purposes, edgeOfBoard = 15) (99s replaced with " " on the top grid to make it easier to read)
The top grid is the first layer of the third dimension- the amount of tiles it takes to get to that tile. The bottom grid is the number of diagonals it takes to get to that tile.
The upper left and bottom right quadrants work properly, but the upper right and bottom left do not, which is really stumping me. Can you help me either come up with a new algorithm or fix this one?