Я пытаюсь реализовать 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
Я думаю, что это на самом деле говоря, что черный кусок белый ... теперь, чтобы понять, что вызывает это.
Итак ... теперь я знаю, что цвет не так, но только функции 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
... возможно, это даст больше подсказок! Я чувствую себя детективом.
В чем игра? Шашки? Может быть, вы должны это указать, и желательно где-то в начале для лучшего понимания –
Упс .. да, шашки. – mpen
Если повторные вызовы этого метода в конечном итоге дают разные результаты (с тем же вводом), это должно быть связано с внешним состоянием. Мы не можем видеть, как вы строите класс Board (мы не знаем, как вычисляются Board.GetValidMoves (цвет) или Board.GetJumps (цвет)), но мое предположение было бы о том, что его состояние медленно становится поврежденным , –