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

C#中foreach循环内赋值的外部变量未生效问题求助

Chess Challenge国际象棋机器人开发问题排查与解决

问题描述

  • 声明FirstDepth、SecondDepth变量后,在foreach循环内赋值,循环外调用时提示变量未赋值
  • 提前初始化变量后,变量始终保留初始值,无法被循环内的赋值更新

相关代码片段

int PositionEvaluation = 0;
Move FirstDepth;
Move SecondDepth;

foreach (Move move in FirstDepthMoves)
{
    // Try a move
    board.MakeMove(move);
         
    Move[] SecondDepthMoves = board.GetLegalMoves();

    foreach (Move move1 in SecondDepthMoves)
    {
        // Try a second move
        board.MakeMove(move1);
                
        int CurrentEvaluation1 = EvaluatePosition(board, !IsBotWhite);

        // If move be good, then we memorize it
        if (CurrentEvaluation1 > PositionEvaluation)
        {
            // Record this to then play + for seeing its thinking process in Console
            FirstDepth = move;
            SecondDepth = move1;

            PositionEvaluation = CurrentEvaluation1;
        }
           
        board.UndoMove(move1);
    }
        
    board.UndoMove(move);
}

// Here it tells me that it didn't get the value assigned to FirstDepth and SecondDepth from foreach loop
// Idk what to do else about it
Console.WriteLine(FirstDepth);

board.MakeMove(FirstDepth);
Console.WriteLine(EvaluatePosition(board, !IsBotWhite));

Console.WriteLine(SecondDepth);
board.MakeMove(SecondDepth);
Console.WriteLine(EvaluatePosition(board, !IsBotWhite));

board.UndoMove(SecondDepth); 
board.UndoMove(FirstDepth);

完整MyBot代码

using ChessChallenge.API;
using System;

public class MyBot : IChessBot
{
    const PieceType Pawn = (PieceType)1;
    const PieceType Knight = (PieceType)2;
    const PieceType Bishop = (PieceType)3;
    const PieceType Rook = (PieceType)4;
    const PieceType Queen = (PieceType)5;

    public Move Think(Board board, Timer timer)
    {
        bool IsBotWhite = board.IsWhiteToMove;
        Move[] FirstDepthMoves = board.GetLegalMoves();

        Random rng = new();
        Move moveToPlay = FirstDepthMoves[rng.Next(FirstDepthMoves.Length)];
        int PositionEvaluation = 0;

        Move FirstDepth = moveToPlay;
        Move SecondDepth = moveToPlay;

        foreach (Move move in FirstDepthMoves)
        {
            //Try a move
            board.MakeMove(move);

            FirstDepth = moveToPlay;
            SecondDepth = moveToPlay;
            
            Move[] SecondDepthMoves = board.GetLegalMoves();

            foreach (Move move1 in SecondDepthMoves)
            {
                // Try a second move
                board.MakeMove(move1);
                    
                int CurrentEvaluation1 = EvaluatePosition(board, !IsBotWhite);
                // If move be good, then we memorize it
                if (CurrentEvaluation1 > PositionEvaluation)
                {
                    //Record this to then play + for seeing its thinking process in Console
                    FirstDepth = move;
                    SecondDepth = move1;

                    PositionEvaluation = CurrentEvaluation1;
                }
               
                board.UndoMove(move1);
            }
            
            board.UndoMove(move);
        }

        // Here it tells me that It didnt get the value assigned to FirstDepth and SecondDepth from foreach loop
        //Idk what to do else about it
        Console.WriteLine(FirstDepth);
        board.MakeMove(FirstDepth);
        Console.WriteLine(EvaluatePosition(board, !IsBotWhite));
        Console.WriteLine(SecondDepth);
        board.MakeMove(SecondDepth);
        Console.WriteLine(EvaluatePosition(board, !IsBotWhite));
        board.UndoMove(SecondDepth); 
        board.UndoMove(FirstDepth);
        return FirstDepth;
    }
    
    int EvaluatePosition(Board board, bool IsWhite)
    {
        //the E stands for Enemy
        PieceList Pawns = board.GetPieceList(pieceType: Pawn, white: IsWhite);
        PieceList Knights = board.GetPieceList(pieceType: Knight, white: IsWhite);
        PieceList Bishops = board.GetPieceList(pieceType: Bishop, white: IsWhite);
        PieceList Rooks = board.GetPieceList(pieceType: Rook, white: IsWhite);
        PieceList Queens = board.GetPieceList(pieceType: Queen, white: IsWhite);

        bool IsWhiteE = !IsWhite;

        PieceList PawnsE = board.GetPieceList(pieceType: Pawn, white: IsWhiteE);
        PieceList KnightsE = board.GetPieceList(pieceType: Knight, white: IsWhiteE);
        PieceList BishopsE = board.GetPieceList(pieceType: Bishop, white: IsWhiteE);
        PieceList RooksE = board.GetPieceList(pieceType: Rook, white: IsWhiteE);
        PieceList QueensE = board.GetPieceList(pieceType: Queen, white: IsWhiteE);

        int TotalEval = ((Pawns.Count * 1) + (Knights.Count * 3) + (Bishops.Count * 3) + (Rooks.Count * 5) + (Queens.Count * 9)) - ((PawnsE.Count * 1) + (KnightsE.Count * 3) + (BishopsE.Count * 3) + (RooksE.Count * 5) + (QueensE.Count * 9));

        if (board.IsDraw())
        {
            TotalEval = -100;
        }
        else if (board.IsInCheckmate())
        {
            TotalEval = 100;
        }

        if (board.IsInCheck())
        {
            TotalEval = TotalEval +  1;
        } 
        
        return -TotalEval;
    }
}

问题原因及修复方案

核心问题分析

  1. 未初始化变量报错:C#中未初始化的变量直接使用会触发编译错误,若循环内未进入if (CurrentEvaluation1 > PositionEvaluation)分支,FirstDepth和SecondDepth会处于未赋值状态。
  2. 初始值无法更新:外层foreach循环内的FirstDepth = moveToPlay; SecondDepth = moveToPlay;会在每次迭代时重置变量,覆盖循环内的赋值结果,导致变量始终保留初始随机值。

修复步骤

  1. 移除循环内的重置代码:删除外层foreach循环里的FirstDepth = moveToPlay; SecondDepth = moveToPlay;两行,避免每次迭代重置变量。
  2. 优化评估初始值:将PositionEvaluation初始值设为int.MinValue,确保第一个合法评估值能触发赋值逻辑。
  3. 保留变量初始化:保持Move FirstDepth = moveToPlay; Move SecondDepth = moveToPlay;,保证变量始终有合法值。

修复后的核心代码

public Move Think(Board board, Timer timer)
{
    bool IsBotWhite = board.IsWhiteToMove;
    Move[] FirstDepthMoves = board.GetLegalMoves();

    Random rng = new();
    Move moveToPlay = FirstDepthMoves[rng.Next(FirstDepthMoves.Length)];
    // 初始化为极小值,确保第一个有效评估能触发赋值
    int PositionEvaluation = int.MinValue;

    Move FirstDepth = moveToPlay;
    Move SecondDepth = moveToPlay;

    foreach (Move move in FirstDepthMoves)
    {
        board.MakeMove(move);
        
        Move[] SecondDepthMoves = board.GetLegalMoves();

        foreach (Move move1 in SecondDepthMoves)
        {
            board.MakeMove(move1);
                
            int CurrentEvaluation1 = EvaluatePosition(board, !IsBotWhite);
            if (CurrentEvaluation1 > PositionEvaluation)
            {
                FirstDepth = move;
                SecondDepth = move1;
                PositionEvaluation = CurrentEvaluation1;
            }
           
            board.UndoMove(move1);
        }
        
        board.UndoMove(move);
    }

    Console.WriteLine(FirstDepth);
    board.MakeMove(FirstDepth);
    Console.WriteLine(EvaluatePosition(board, !IsBotWhite));
    Console.WriteLine(SecondDepth);
    board.MakeMove(SecondDepth);
    Console.WriteLine(EvaluatePosition(board, !IsBotWhite));
    board.UndoMove(SecondDepth); 
    board.UndoMove(FirstDepth);
    return FirstDepth;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 19:49:58