I am working on an A* Pathfinding method that uses a custom class instead of nodes, but am having issues with my loops. The first for loop using int i is able to go up to 3 (Player1.instance.movement = 3), but I need to use an if statement inside of that loop to check if the target position has already been found. I am wondering if it is possible to break my for loop when my If statement is false. public void GetNeighbors(Tile originTile) { Tile originalTile = originTile;
nextTile.Clear();
int minX = 0;
int minY = 0;
var originCostFunc = Mathf.Infinity;
for (int i = 0; i < Player1.instance.movement; i )
{
for (int x = -1; x <= 1; x )
{
for (int y = -1; y <= 1; y )
{
if (x != y && y != x)
{
var costX = Mathf.Abs((originTile.transform.position.x x) - originalTile.transform.position.x);
var costY = Mathf.Abs((originTile.transform.position.y y) - originalTile.transform.position.y);
var distanceX = Mathf.Abs(targetPos.transform.position.x - (originTile.transform.position.x x));
var distanceY = Mathf.Abs(targetPos.transform.position.y - (originTile.transform.position.y y));
var costFunc = costX costY distanceX distanceY;
if (costFunc <= originCostFunc)
{
originCostFunc = costFunc;
minX = x;
minY = y;
Debug.Log($"x: {x}, y: {y}");
}
}
}
}
nextTile.Add(GridManagerHandPlaced.instance.GetTileAtPosition(new Vector2(originTile.transform.position.x minX, originTile.transform.position.y minY)));
if (nextTile[i] != targetPos)
{
originTile = nextTile[i];
}
else
{
break;
}
}
DisplayPath();
}
CodePudding user response:
You can break loop several times by condition.
bool breakLoop = false;
for (int i = 0; i < length; i )
{
for (int j = 0; j < length; j )
{
for (int k = 0; k < length; k )
{
breakLoop = nextTile == target;
if (breakLoop)
break;
}
if (breakLoop)
break;
}
if (breakLoop)
break;
}
Or move search logic to separated method and return a value from any number of nested loops
string path = FindPath();
Display(path);
string FindPath()
{
for (int i = 0; i < length; i )
{
for (int j = 0; j < length; j )
{
for (int k = 0; k < length; k )
{
if (nextTile == target)
return nextTile;
}
}
}
return null;
}
Never use goto operator.
CodePudding user response:
This is one of the few valid cases where I'd use goto
. In-fact, this is the example given in the docs for when it should be used.
void CheckMatrices(Dictionary<string, int[][]> matrixLookup, int target)
{
foreach (var (key, matrix) in matrixLookup)
{
for (int row = 0; row < matrix.Length; row )
{
for (int col = 0; col < matrix[row].Length; col )
{
if (matrix[row][col] == target)
{
goto Found;
}
}
}
Console.WriteLine($"Not found {target} in matrix {key}.");
continue;
Found:
Console.WriteLine($"Found {target} in matrix {key}.");
}
}
Note the syntax for the label is simply myLabel:
and you can place it anywhere in procedurally executable code.
CodePudding user response:
For sake of covering other ways of handling this situation, here is the boolean solution.
bool breakLoops = false;
for (int i = 0; i < length1; i )
{
for (int ii = 0; ii < length2; ii )
{
for (int iii = 0; iii < length3; iii )
{
if (breakingCondition)
{
breakLoops = true;
break;
}
}
if (breakLoops) break;
}
if (breakLoops) break;
}
Simple and straightforward, but requires a break condition check at the end of each loop that you want to break out of.