Unity国际象棋开发皇后穿过友方棋子移动的逻辑修复问题
国际象棋皇后移动阻挡逻辑修复方案
问题根源
你用normalized.Equals判断方向失效的核心原因是浮点数精度误差,Unity的Vector2是浮点类型,归一化计算后会存在微小的精度偏差,直接调用Equals方法会因为这些微小偏差返回false,而国际象棋的棋盘坐标全是整数,完全可以用整数方向判断规避这个问题。
除此之外你的原有逻辑还有三个明显问题:
- 遍历
legalMoves的过程中直接修改legalMoves的值,会导致迭代器异常或者遍历遗漏元素 - 边生成trail边删除trail的逻辑效率极低,反复调用
GameObject.FindGameObjectsWithTag会带来不必要的性能开销 - 每次遇到阻挡点就全量遍历所有移动点的逻辑,时间复杂度很高,逻辑也容易出错
修复方案
我们可以先把所有移动点按整数最简方向分组,同一方向的点按距离棋子的远近排序,再依次校验阻挡,逻辑清晰且完全规避浮点精度问题。
实现代码
首先写一个求最大公约数的工具方法,用来计算最简整数方向:
// 计算最大公约数,用来约分方向向量 private int GCD(int a, int b) { a = Mathf.Abs(a); b = Mathf.Abs(b); while (b != 0) { int temp = b; b = a % b; a = temp; } return a == 0 ? 1 : a; }
然后是主逻辑:
// 替换为你当前棋子的整数棋盘坐标 Vector2Int piecePos = 你的棋子当前棋盘坐标; List<Vector2> finalLegalMoves = new List<Vector2>(); // 用来按方向分组存储移动点 Dictionary<(int dirX, int dirY), List<Vector2>> dirGroups = new Dictionary<(int dirX, int dirY), List<Vector2>>(); // 第一步:预处理所有移动点,按方向分组 foreach (var move in legalMoves) { // 先筛掉棋盘外的点 if (move.x < 0 || move.x > 7 || move.y < 0 || move.y > 7) continue; int dx = (int)move.x - piecePos.x; int dy = (int)move.y - piecePos.y; // 跳过棋子自身的位置 if (dx == 0 && dy == 0) continue; // 计算最简整数方向 int gcd = GCD(dx, dy); var dirKey = (dx / gcd, dy / gcd); if (!dirGroups.ContainsKey(dirKey)) { dirGroups[dirKey] = new List<Vector2>(); } dirGroups[dirKey].Add(move); } // 第二步:逐个方向校验阻挡 foreach (var group in dirGroups) { // 同一方向的点按距离棋子从近到远排序 var sortedMoves = group.Value.OrderBy(move => Mathf.Pow(move.x - piecePos.x, 2) + Mathf.Pow(move.y - piecePos.y, 2) ).ToList(); bool isBlocked = false; foreach (var move in sortedMoves) { if (isBlocked) continue; var currentPiece = board[(int)move.x, (int)move.y].getPiece(); if (currentPiece == null) { // 空位,保留移动点 finalLegalMoves.Add(move); } else { // 有棋子,判断是否是敌方,是敌方可以吃所以保留 if (currentPiece.isEnemy) { finalLegalMoves.Add(move); } // 不管是友方还是敌方,后面的点全部被阻挡 isBlocked = true; } } } // 第三步:统一生成移动轨迹,不需要边删边加 foreach (var move in finalLegalMoves) { Instantiate(trail, move, Quaternion.identity); } // 更新合法移动点数组 legalMoves = finalLegalMoves.ToArray();
方案优势
- 用整数方向判断,完全规避浮点数精度问题,方向识别准确率100%
- 先预处理再校验的逻辑结构清晰,不会出现遍历过程中修改集合的异常
- 时间复杂度更低,不需要反复遍历全量移动点和查找游戏对象
- 兼容了吃子规则,遇到敌方棋子可以吃但后面的点仍然被阻挡,完全符合国际象棋的移动规则
内容的提问来源于stack exchange,提问作者Dimitris
相关产品推荐
相关产品推荐

