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; } }
问题原因及修复方案
核心问题分析
- 未初始化变量报错:C#中未初始化的变量直接使用会触发编译错误,若循环内未进入
if (CurrentEvaluation1 > PositionEvaluation)分支,FirstDepth和SecondDepth会处于未赋值状态。 - 初始值无法更新:外层foreach循环内的
FirstDepth = moveToPlay; SecondDepth = moveToPlay;会在每次迭代时重置变量,覆盖循环内的赋值结果,导致变量始终保留初始随机值。
修复步骤
- 移除循环内的重置代码:删除外层foreach循环里的
FirstDepth = moveToPlay; SecondDepth = moveToPlay;两行,避免每次迭代重置变量。 - 优化评估初始值:将
PositionEvaluation初始值设为int.MinValue,确保第一个合法评估值能触发赋值逻辑。 - 保留变量初始化:保持
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
相关产品推荐
相关产品推荐

