You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#国际象棋机器人国王移动逻辑触发栈溢出异常求助

解决国际象棋国王移动逻辑的栈溢出及非法移动过滤问题

栈溢出原因分析

从调用栈可以明确看出,canKingMove方法内部调用了GetLegalMovesForPiece,而GetLegalMovesForPiece又反过来调用了canKingMove,形成无限递归。比如计算敌方国王的合法移动时,会再次进入canKingMove,循环往复直到栈空间耗尽。

核心修复方案

1. 打破无限递归

重构逻辑拆分职责:让GetLegalMovesForPiece只返回棋子的基础移动范围(比如国王的8个相邻格子、车的直线移动等),不涉及全局合法性检查(比如是否被将军)。全局合法性检查统一在canKingMove这类上层方法中处理,彻底避免递归调用。

2. 正确实现三种非法移动过滤

针对你提到的三种非法情况,逐一处理:

  • 移动后处于被将军状态:模拟国王移动到目标位置,生成临时棋盘,检查该位置是否在敌方任何棋子的攻击范围内。
  • 移动路径被友方阻挡:国王每次仅移动一格,只需检查目标位置是否有友方棋子,有则直接排除该移动。
  • 拟捕获的敌方棋子有防守:本质是目标位置处于敌方攻击范围,属于“移动后被将军”的子情况,无需单独处理,通过第一种情况的检查即可覆盖。

修改后的代码示例

List<Move> canKingMove(List<Move> baseMoves, List<boardPosition> board, boardPosition kingPos)
{
    var legalMoves = new List<Move>();
    var kingColor = kingPos.OccupiedBy.IsWhite;
    
    foreach (var move in baseMoves)
    {
        // 检查目标位置是否有友方棋子(情况2)
        var targetPos = board.First(p => p.x == move.x && p.y == move.y);
        if (!targetPos.isEmpty && targetPos.OccupiedBy.IsWhite == kingColor)
        {
            continue;
        }

        // 模拟国王移动,生成临时棋盘(需确保boardPosition实现深拷贝)
        var tempBoard = board.Select(p => new boardPosition(p)).ToList();
        var currentKingIndex = tempBoard.FindIndex(p => p.x == kingPos.x && p.y == kingPos.y);
        var targetIndex = tempBoard.FindIndex(p => p.x == move.x && p.y == move.y);
        
        // 执行模拟移动
        tempBoard[currentKingIndex].isEmpty = true;
        tempBoard[currentKingIndex].OccupiedBy = null;
        tempBoard[targetIndex].isEmpty = false;
        tempBoard[targetIndex].OccupiedBy = kingPos.OccupiedBy;

        // 检查移动后国王是否被将军(情况1)
        bool isInCheck = false;
        var enemyPositions = tempBoard.Where(p => !p.isEmpty && p.OccupiedBy.IsWhite != kingColor).ToList();
        foreach (var enemyPos in enemyPositions)
        {
            // 调用仅返回基础移动的方法,避免递归
            var enemyAttackMoves = GetBaseMovesForPiece(pieceToString(enemyPos), tempBoard);
            if (enemyAttackMoves.Any(m => m.x == move.x && m.y == move.y))
            {
                isInCheck = true;
                break;
            }
        }

        if (!isInCheck)
        {
            legalMoves.Add(move);
        }
    }

    return legalMoves;
}

// 新增:获取棋子的基础移动范围(无全局合法性检查,不调用canKingMove)
List<Move> GetBaseMovesForPiece(string pieceType, List<boardPosition> board)
{
    // 实现各棋子的基础移动逻辑:
    // 国王返回8个相邻格子、车返回直线上所有可达格子等
}

关键说明

  • 新增GetBaseMovesForPiece方法拆分职责,彻底切断递归链。
  • 模拟移动时对棋盘进行深拷贝,避免修改原棋盘的真实状态。
  • 原代码直接操作传入的moves列表会导致索引错误(删除元素后列表长度变化),改用新建legalMoves列表存储合法移动更安全。

内容的提问来源于stack exchange,提问作者george tavadze

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 01:57:40