我现在为我的坏英语道歉,我是意大利人。我正在用C#编写一个象棋游戏的完整实现,Player vs Player和Player vs Computer,现在我有一些难以实现的NegaMax算法。 对于谁是有兴趣,这里是我的github仓库:https://github.com/crybot/ChessEngine_NOGUI/tree/master/Chess%20Engine%20-%20NOGUIPerft测试结果 - 找不到Bug?
我试图让这个项目作为OO越好,所以,如果你认为我的设计是不正确,请告诉我:)
这里我的问题:
我实现对称地为所有玩家的工作很简单的评价函数:
public static float Evaluate(PieceColor playerColor, Game game)
{
float score = 0;
score += 1 * (game.board.GetNumberOfPieces(PieceType.Pawn, playerColor)
- game.board.GetNumberOfPieces(PieceType.Pawn, playerColor.GetOpposite()));
score += 3 * (game.board.GetNumberOfPieces(PieceType.Bishop, playerColor)
- game.board.GetNumberOfPieces(PieceType.Bishop, playerColor.GetOpposite()));
score += 3 * (game.board.GetNumberOfPieces(PieceType.Knight, playerColor)
- game.board.GetNumberOfPieces(PieceType.Knight, playerColor.GetOpposite()));
score += 5 * (game.board.GetNumberOfPieces(PieceType.Rook, playerColor)
- game.board.GetNumberOfPieces(PieceType.Rook, playerColor.GetOpposite()));
score += 9 * (game.board.GetNumberOfPieces(PieceType.Queen, playerColor)
- game.board.GetNumberOfPieces(PieceType.Queen, playerColor.GetOpposite()));
score += 0.1f * (game.GetPlayer(playerColor).GetMoves(game).Count);
return score;
}
,这里是我的NegaMax功能,至极接受的游戏参数(包括博ard,players,ecc.ecc),由enum提供的playerColor和深度搜索;
我第一次扫描的EnginePlayer的所有可能的行动,然后我从NegaMax功能的比分,但东西是不工作...
private float NegaMax(Game game, PieceColor playerColor, int depth)
{
if (depth == 0)
return EvaluateMove(playerColor, game);
float max = float.MinValue;
float score;
foreach (Move move in game.GetPlayer(playerColor.GetOpposite()).GetMoves(game))
{
game.board.SimulateMove(move);
score = Math.Max(max, -NegaMax(game, playerColor.GetOpposite(), depth - 1));
game.board.CancelMove(move);
if (score > max)
max = score;
}
return max;
}
public Move ThinkMove(Game game, PieceColor playerColor, int depth)
{
Move bestMove = new NullMove();
float bestScore = float.MinValue;
float temp = 0;
foreach (Move move in GetMoves(game))
{
game.board.SimulateMove(move);
temp = NegaMax(game, playerColor, depth);
game.board.CancelMove(move);
if (temp > bestScore)
{
if (Judge.IsLegal(move, game))
{
bestMove = move;
bestScore = temp;
}
}
}
if (bestMove is NullMove)
throw new NotImplementedException();
return bestMove;
}
我觉得这一切......我希望你会发现我做错了什么:) 谢谢。
编辑: 我实现了一个Perft,它显示了移动生成器的非修正。它帮助我们找到了一些相对容易发现的错误,但最后一些结果仍然是错误的。 下面是结果:
Perft Depth: 1
Nodes: 20 Captures: 0 Checks: 0 Castles: 0 Mates: 0 EnPassant: 0
Perft Depth: 2
Nodes: 400 Captures: 0 Checks: 0 Castles: 0 Mates: 0 EnPassant: 0
Perft Depth: 3
Nodes: 8902 Captures: 34 Checks: 12 Castles: 0 Mates: 0 EnPassant: 0
Perft Depth: 4
Nodes: 197281 Captures: 1610 Checks: 473 Castles: 0 Mates: 8 EnPassant: 0
这里是正确的结果:https://chessprogramming.wikispaces.com/Perft+Results分析
正如你所看到的,在深度4,我得到正确的节点,但不正确的捕获和检查值(当队友是正确)。
由于这些结果我试图通过将每移动所分析的节点在深度4到bug隔离,得到这些结果:
Move Nodes
a2a3 8457
a2a4 9329
b2b3 9345
b2b4 9332
c2c3 9272
c2c4 9744
d2d3 11959
d2d4 12435
e2e3 13134
e2e4 13160
f2f3 8457
f2f4 8929
g2g3 9345
g2g4 9328
h2h3 8457
h2h4 9329
b1a3 8885
b1c3 9755
g1f3 9748
g1h3 8881
Total Nodes: 197281
和与这些结果,从更清晰的获得比较:
Sharper v0.17 by Albert Bertilsson
divide 4
b1c3 9755
b1a3 8885
g1h3 8881
g1f3 9748
a2a3 8457
a2a4 9329
b2b3 9345
b2b4 9332
c2c3 9272
c2c4 9744
d2d3 11959
d2d4 12435
e2e3 13134
e2e4 13160
f2f3 8457
f2f4 8929
g2g3 9345
g2g4 9328
h2h3 8457
h2h4 9329
Nodes: 197281
Moves: 20
但即使这里的值是正确的...... 所以我尝试了深度5个perft得到这些结果:
Move Nodes
a2a3 181046
a2a4 217813
b2b3 215255
b2b4 216110
c2c3 222861
c2c4 240044
d2d3 328511
d2d4 361753
e2e3 402988
e2e4 405348
f2f3 178891
f2f4 198437
g2g3 217210
g2g4 214017
h2h3 181044
h2h4 218810
b1a3 198572
b1c3 234656
g1f3 233491
g1h3 198502
Total Nodes: 4865359
,然后进行比较,以更清晰的结果:
Sharper v0.17 by Albert Bertilsson
divide 5
b1c3 234656
b1a3 198572
g1h3 198502
g1f3 233491
a2a3 181046
a2a4 217832
b2b3 215255
b2b4 216145
c2c3 222861
c2c4 240082
d2d3 328511
d2d4 361790
e2e3 402988
e2e4 405385
f2f3 178889
f2f4 198473
g2g3 217210
g2g4 214048
h2h3 181044
h2h4 218829
Nodes: 4865609
Moves: 20
所以我意识到,这个问题是由兵卒的双重推动产生的移动造成的......但我真的不能找到bug ... 有没有人有同样的问题? 或类似的东西,或只是一个提示找到该错误...
感谢所有:)
什么不工作?引擎不是'聪明的',或者它根本不搜索? – 2012-07-06 15:32:24
起初它似乎在工作,但随后它试图通过将他的主教从g8移动到a3来在第二步中自我杀死。也有深度2有时会导致非法移动。 – Crybot 2012-07-06 15:36:44
你测试了你的移动发生器吗? – 2012-07-06 15:37:19