C# A*寻路开发:如何从循环内if语句终止for循环
关于外层for循环终止的问题解答
你当前代码里写在else分支的break完全可以终止外层的i循环。
break关键字的作用是跳出它直接所属的最内层循环或switch结构,你的终止判断逻辑写在最外层for (int i = 0; i < Player1.instance.movement; i++)的循环体层级,没有嵌套在内层的x、y遍历循环里,因此触发时会直接结束外层的步数循环,不需要额外做特殊处理。如果你需要调整终止触发条件,比如判断条件不成立时终止,只需要调整if/else的分支逻辑即可,break本身的跳出效果不会变。
当前代码存在的逻辑问题
- 邻域遍历判断条件错误:
if (x != y && y != x)属于重复判断,实际效果等价于x != y,会把斜向相邻的格子也纳入计算。如果是四方向(上下左右)寻路,正确判断条件应为if (Mathf.Abs(x) + Mathf.Abs(y) == 1),仅保留上下左右四个正方向邻格;如果需要支持八方向斜向移动,可调整为允许斜向的判断逻辑,同时记得给斜向移动设置更高的移动代价。 - 代价值未按迭代重置:你在循环外初始化了
originCostFunc = Mathf.Infinity、minX = 0、minY = 0,但每一轮外层i循环(每走一步选下一个格子)开始前没有重置这几个值,会导致后续迭代选邻格时一直和第一步的最小代价比对,选出的路径完全不符合预期。 - 缺省异常终止逻辑:当前只判断了走到目标点的终止情况,没有判断走到地图边界、障碍物、不可通行格子时的终止逻辑,运行时很容易出现空引用报错。
修正后的参考代码
public void GetNeighbors(Tile originTile) { Tile originalTile = originTile; nextTile.Clear(); for (int i = 0; i < Player1.instance.movement; i++) { // 每一步选邻格前重置最小代价和偏移量 int minX = 0; int minY = 0; float originCostFunc = Mathf.Infinity; // 遍历邻格 for (int x = -1; x <= 1; x++) { for (int y = -1; y <= 1; y++) { // 四方向移动判断,排除自身和斜向格 if (Mathf.Abs(x) + Mathf.Abs(y) != 1) continue; // 先判断目标邻格是否存在、是否可通行,避免空引用 Tile checkTile = GridManagerHandPlaced.instance.GetTileAtPosition( new Vector2(originTile.transform.position.x + x, originTile.transform.position.y + y) ); if (checkTile == null || !checkTile.walkable) continue; // 计算代价 float costX = Mathf.Abs((originTile.transform.position.x + x) - originalTile.transform.position.x); float costY = Mathf.Abs((originTile.transform.position.y + y) - originalTile.transform.position.y); float distanceX = Mathf.Abs(targetPos.transform.position.x - (originTile.transform.position.x + x)); float distanceY = Mathf.Abs(targetPos.transform.position.y - (originTile.transform.position.y + y)); float costFunc = costX + costY + distanceX + distanceY; if (costFunc <= originCostFunc) { originCostFunc = costFunc; minX = x; minY = y; } } } // 选出当前步的最优格子 Tile currentNextTile = GridManagerHandPlaced.instance.GetTileAtPosition( new Vector2(originTile.transform.position.x + minX, originTile.transform.position.y + minY) ); nextTile.Add(currentNextTile); // 找到目标点,直接终止外层循环 if (currentNextTile == targetPos) { break; } // 没找到目标就更新起点,继续下一轮迭代 originTile = currentNextTile; } DisplayPath(); }
内容的提问来源于stack exchange,提问作者Hunter McCoid
相关产品推荐
相关产品推荐

