Я пытаюсь реализовать NegaMax для игры в шашки.Сейчас я просто тестирую его с глубиной 0, то есть текущий игрок просто оценивает все свои ходы, независимо от того, что другой игрок может сделать дальше.Он отлично работает примерно половину игры (правильно вычисляет баллы), а затем частично начинает выплевывать бессмысленные ответы.
Например, у белых может остаться 1 фигура, а у черных - 5, но он оценит ходы белых как 7, например, когда все они должны быть отрицательными, потому что они проигрывают.Черные могут выиграть на следующем ходу, но они оценят выигрышный ход как -4, хотя это должно быть 1000.
Я понимаю, что это последовательно выводит мусор, но почему это сработает в первый раз?несколько ходов и затем начинаешь портить?
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)
{
return BoardScore(color, board);
}
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));
}
Я выделил состояние доски, которое ему не нравится, на доске 6x6:
. . .
. w B
W . .
. . .
. w .
. . W
w = white, b = black, capital letter = king
Похоже, что это не проблема времени или количества ходов, просто не нравятся конкретные состояния доски.Хотя я не вижу ничего особенного в этом состоянии.
В этом состоянии все 4 хода черных оцениваются как -13.Если вы посмотрите, как я набрал очки, там написано 2 очка на человека, 3 очка на короля, отрицательно, если они принадлежат другому игроку.Похоже, что он рассматривает все фигуры как белые ... это единственный способ получить 13.
Я нашел другую подсказку.В методе подсчета досок я получил его, чтобы напечатать то, что он видит ... вот что он говорит мне:
2: White
4: White
6: White
13: White
17: White
Где квадраты доски пронумерованы так:
00 01 02
03 04 05
06 07 08
09 10 11
12 13 14
15 16 17
Iдумаю, это действительно говорит о том, что черный кусок белый ... теперь, чтобы выяснить, что вызывает это.
Итак ... теперь я знаю, что цвет неправильный, но только дляBoardScore
функция.Моя обычная процедура показа никогда не уловила этого, иначе я бы понял проблему несколько часов назад.Я думаю, что это может быть в функции ApplyMove
, что цвет переключается ..
public Board ApplyMove(Move m)
{
if (m.IsJump)
{
bool indented = m.Start % Width < _rowWidth;
int offset = indented ? 1 : 0;
int enemy = (m.Start + m.End) / 2 + offset;
this[m.Color, enemy] = Tile.Empty;
}
this[m.Color, m.End] = this[m.Color, m.Start];
this[m.Color, m.Start] = Tile.Empty;
var checker = this[m.Color, m.End] as Checker;
if (m.IsCrowned) checker.Class = Class.King;
return this;
}
Но это тоже не имеет большого смысла ... кусок просто скопирован изНачальная позиция до конечной позиции.Необходимо выяснить, что такое m.Color
... возможно, это даст больше подсказок!Я чувствую себя детективом.