我正在尝试在Java中使用名为Nine Men's Morris的游戏实现Negamax搜索。
如果一名球员连续三件(此处称为磨坊),他会在转牌前移除对手的棋子(“附加”牌)。
此外,在放置完所有初始作品后,还有一个设置片段阶段和移动片段阶段。
我的实现如下:
public int[] negamaxSet(int depth, int alpha, int beta, int color) {
if (depth == 0 || board.isGameOver()) {
return new int[] { color * evaluateBoard(color};
}
int stonesSet = color == -1 ? board.blackStonesSet : board.whiteStonesSet;
// set piece phase
if (stonesSet < Game.initialPieces) {
List<Piece> moves = board.getEmpty();
int bestValue = Integer.MIN_VALUE;
int bestMoveX = -1;
int bestMoveY = -1;
for (Piece piece : moves) {
Piece move = new Piece(color, piece.x, piece.y);
board.setPiece(move);
int value[] = null;
//Player made Mill, move again
if(board.checkMill(move)){
value = negamaxRemove(depth - 1, alpha, beta, color);
}
//normal move, switch turn
else {
value = negamaxSet(depth - 1, -beta, -alpha, -color);
value[0] = -value[0];
}
if (value[0] > bestValue) {
bestValue = value[0];
bestMoveX = move.x;
bestMoveY = move.y;
}
if (value[0] > alpha) {
alpha = value[0];
}
board.revertLastMove();
// if (alpha >= beta)
// break;
}
return new int[] { bestValue, bestMoveX, bestMoveY };
} else {
//move phase
List<Piece> moves = board.getPiecesByColor(color);
int bestValue = Integer.MIN_VALUE;
int bestMoveX = -1;
int bestMoveY = -1;
int bestMoveX2 = -1;
int bestMoveY2 = -1;
for (Piece piece : moves) {
List<Piece> adjPieces = board.getAdjacentEmtpy(piece);
for(Piece adjPiece : adjPieces){
Piece newFrom = new Piece(color, piece.x, piece.y);
Piece newTo = new Piece(color, adjPiece.x, adjPiece.y);
board.movePiece(newFrom, newTo);
int[] value = null;
//Player made Mill, move again
if(board.checkMill(newTo, false)){
value = negamaxRemove(depth - 1, alpha, beta, color);
} else {
value = negamaxSet(depth - 1, -beta, -alpha, -color);
value[0] = -value[0];
}
if (value[0] > bestValue) {
bestValue = value[0];
bestMoveX = newFrom.x;
bestMoveY = newFrom.y;
bestMoveX2 = newTo.x;
bestMoveY2 = newTo.y;
}
if (value[0] > alpha) {
alpha = value[0];
}
board.revertLastMove();
// if (alpha >= beta)
// break;
}
}
return new int[] { bestValue, bestMoveX, bestMoveY, bestMoveX2, bestMoveY2 };
}
}
可能建议不要更改基本的Negamax算法,并在一次操作中封装设置石头和移动石头,以区分算法本身中的两者,但根据我的理解,应该仍然像这样工作。
函数negamaxRemove与negamaxSet基本相同,但没有检查铣削(不可能)并寻找要移除的零件。
使用与调用函数相同的参数调用negamaxRemove并且不切换符号(从而再次最大化)是否正确?
不知何故,AI玩家并没有阻止对手组建一个工厂(但如果可能的话,他自己组建一个)。
算法是否正确,我应该在代码的其他地方查找错误? 或者我误解了Negamax应该如何运作? (我评论了alpha-beta修剪,因此错误地设置alpha或beta不会在这里产生影响)
我真的很感激一些指示!
答案 0 :(得分:0)
I've implemented this game。将您的移动定义从“执行操作,授予另一个移动”更改为“执行多部分操作”。然后,您不必进行2次“移动”,而是最终看起来像from: 3, to: 0, remove: 17
,from: 3, to: 0, remove 19
等移动。对于不移除部分的移动,您只需将移除设置为{{1 }}