这是用于跳棋游戏的。查看修订历史以获取代码的旧版本。
private static Move GetBestMove(Color color, Board board, int depth) { var bestMoves = new List<Move>(); var validMoves = board.GetValidMoves(color); int highestScore = int.MinValue; Board boardAfterMove; int tmpScore; var rand = new Random(); Debug.WriteLine("{0}'s Moves:", color); foreach (var move in validMoves) { boardAfterMove = board.Clone().ApplyMove(move); if(move.IsJump && !move.IsCrowned && boardAfterMove.GetJumps(color).Any()) tmpScore = NegaMax(color, boardAfterMove, depth); else tmpScore = -NegaMax(Board.Opposite(color), boardAfterMove, depth); Debug.WriteLine("{0}: {1}", move, tmpScore); if (tmpScore > highestScore) { bestMoves.Clear(); bestMoves.Add(move); highestScore = tmpScore; } else if (tmpScore == highestScore) { bestMoves.Add(move); } } return bestMoves[rand.Next(bestMoves.Count)]; } private static int NegaMax(Color color, Board board, int depth) { var validMoves = board.GetValidMoves(color); int highestScore = int.MinValue; Board boardAfterMove; if (depth <= 0 || !validMoves.Any()) return BoardScore(color, board); foreach (var move in validMoves) { boardAfterMove = board.Clone().ApplyMove(move); if(move.IsJump && !move.IsCrowned && boardAfterMove.GetJumps(color).Any()) highestScore = Math.Max(highestScore, NegaMax(color, boardAfterMove, depth)); else highestScore = Math.Max(highestScore, -NegaMax(Board.Opposite(color), boardAfterMove, depth - 1)); } return highestScore; } private static int BoardScore(Color color, Board board) { if (!board.GetValidMoves(color).Any()) return -1000; return board.OfType<Checker>().Sum(c => (c.Color == color ? 1 : -1) * (c.Class == Class.Man ? 2 : 3)); }
我尝试使用深度 0,在游戏进行到大约一半时,分数是正确的,然后突然开始出错。其中一个玩家会开始声称他的分数比实际高。为什么它只在游戏进行到一半时才有效?!
回答:
找到bug了: 是什么导致它一段时间后开始计算错误?
新代码:
private static Move GetBestMove(Color color, Board board, int depth){ var bestMoves = new List<Move>(); IEnumerable<Move> validMoves = board.GetValidMoves(color); int highestScore = int.MinValue; Board boardAfterMove; int tmpScore; var rand = new Random(); Debug.WriteLine("{0}'s Moves:", color); foreach (Move move in validMoves) { boardAfterMove = board.Clone().ApplyMove(move); if (move.IsJump && !move.IsCrowned && boardAfterMove.GetJumps(color).Any()) tmpScore = NegaMax(color, boardAfterMove, depth); else tmpScore = -NegaMax(Board.Opposite(color), boardAfterMove, depth); Debug.WriteLine("{0}: {1}", move, tmpScore); if (tmpScore > highestScore) { bestMoves.Clear(); bestMoves.Add(move); highestScore = tmpScore; } else if (tmpScore == highestScore) { bestMoves.Add(move); } } return bestMoves[rand.Next(bestMoves.Count)];}private static int NegaMax(Color color, Board board, int depth){ IEnumerable<Move> validMoves = board.GetValidMoves(color); int highestScore = int.MinValue; Board boardAfterMove; if (depth <= 0 || !validMoves.Any()) return BoardScore(color, board); foreach (Move move in validMoves) { boardAfterMove = board.Clone().ApplyMove(move); if (move.IsJump && !move.IsCrowned && boardAfterMove.GetJumps(color).Any()) highestScore = Math.Max(highestScore, NegaMax(color, boardAfterMove, depth)); else highestScore = Math.Max(highestScore, -NegaMax(Board.Opposite(color), boardAfterMove, depth - 1)); } return highestScore;}private static int BoardScore(Color color, Board board){ if (!board.GetValidMoves(color).Any()) return -1000; return board.OfType<Checker>().Sum(c => (c.Color == color ? 1 : -1) * (c.Class == Class.Man ? 2 : 3));}
我不能 100% 确定它能完美运行。它似乎在深度 0 时有效,并且通常在深度 1 时也有效……除此之外,我不知道计算机在想什么。看起来仍然不够智能。
编辑: 运行这个并以最大速度… NegaMax 代理对抗随机代理。 NegaMax 总是赢。 观察出现“1000”的分数。 他总是在那之后几回合内获胜,所以它似乎最终可以工作了!