【发布时间】:2018-03-14 22:50:40
【问题描述】:
我已经在我的国际象棋 AI 中实现了 minimax 算法,但我知道它不能正常工作,因为它只是一遍又一遍地来回移动 1 个棋子。
getPieces(true) 返回当前棋盘状态下的所有白棋子
getPieces(false) 返回当前棋盘状态下的所有黑色棋子
ChessPiece.getAllPotentialMoves() 非常不言自明,获取特定棋子的所有可能移动
PieceMovements.move() 将棋子(p) 移动到位置(m -> 表示移动)
PieceMovements.undo() 撤消上一个动作
searchDepth 是一个变量,在第一次调用 miniMax 时作为深度值传入,换句话说,就是你想向下搜索多远。原因...
if(depth == searchDepth) {
piece = p;
move = m;
}
... 是记录这首曲子并进行移动。我在搜索树的顶层记录了这个值。 piece 和 move 代表实际的棋子,并且 move 算法认为是最有效的。
当调用 miniMax 时,它看起来像这样:miniMax(searchDepth, false)。 错误,因为 AI,黑色,是最小化者。
这是我的方法
public int miniMax(int depth, boolean maxi) {
if(maxi) {
if(depth == 0) return evaluateBoard();
int max = -9999; //negative infinity
for(ChessPiece p : getPieces(maxi)) for(Vector2 m : p.getAllPotentialMoves()) {
PieceMovements.move(board, p, (int)m.x, (int)m.y);
max = Math.max(max, miniMax(depth-1, !maxi));
PieceMovements.undo();
if(depth == searchDepth) {
piece = p;
move = m;
}
}
return max;
} else {
if(depth == 0) return -evaluateBoard();
int min = 9999; //positive infinity
for(ChessPiece p : getPieces(maxi)) for(Vector2 m : p.getAllPotentialMoves()) {
PieceMovements.move(board, p, (int)m.x, (int)m.y);
min = Math.min(min, miniMax(depth-1, !maxi));
PieceMovements.undo();
if(depth == searchDepth) {
piece = p;
move = m;
}
}
return min;
}
}
还有我的评估函数,目前它只取每件的相对值并将它们相加:
public int evaluateBoard() {
int total = 0;
for(ChessPiece[] row : board)
for(ChessPiece piece : row)
if(piece != null)
switch(piece.getPiece()) {
case WPAWN:
case BPAWN:
total += RelativePieceValues.PAWN;
//a pawn about to be promoted takes on more value
if(piece.getPosition().y == 1 || piece.getPosition().y == 6)
total += 50; //50 + 10 = 60
break;
case WKNIGHT:
case BKNIGHT:
total += RelativePieceValues.KNIGHT;
break;
case WBISHOP:
case BBISHOP:
total += RelativePieceValues.BISHOP;
break;
case WROOK:
case BROOK:
total += RelativePieceValues.ROOK;
break;
case WQUEEN:
case BQUEEN:
total += RelativePieceValues.QUEEN;
break;
case WKING:
case BKING:
total += RelativePieceValues.KING;
break;
}
return total;
}
和RelativePieceValues 类:
public class RelativePieceValues{
//piece value constants
public static final int PAWN = 10;
public static final int KNIGHT = 30;
public static final int BISHOP = 30;
public static final int ROOK = 50;
public static final int QUEEN = 90;
public static final int KING = 900;
}
如果您有任何问题,请提出。感谢您的任何回复,我已经坚持了一段时间。我想知道我的 mini max 算法或评估函数是否真的有问题,或者我的程序中可能还有其他你看不到的问题。 谢谢。
【问题讨论】:
-
在任何时候你都不会使用你的极小极大的结果来决定采取哪一步。您似乎只是将您在递归堆栈顶部看到的每一个可能的移动分配给一个实例变量,这意味着您使用的移动始终是最后一个考虑的移动。
-
那么我将在算法中的哪个位置决定最佳的移动是什么?
-
板子评估也很简单。如果搜索找不到要捕获的部分,它如何确定一个位置是否优于另一个位置?来回移动可能是对当前位置感到满意的结果(对相持规则一无所知)。
-
那我该如何改进评估功能呢?有什么推荐的吗?
-
我也知道有negamax。如果使用 negamax,评估函数只考虑一侧(白色或黑色)的部分。当使用带有 minimax 算法的评估函数时,我是否必须使用棋盘上的所有棋子(包括白色和黑色)来计算棋盘值?