简体   繁体   中英

How to Break a For Loop From an If Statement Inside the Loop (C#)

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

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.

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM