我已经在我的国际象棋AI中实现了minimax算法,我知道它不能正常工作,因为它只是一遍又一遍地来回移动。
getPieces(true)返回当前电路板状态下的所有白色部分
getPieces(false)返回当前电路板状态下的所有黑色部分
ChessPiece.getAllPotentialMoves()非常自我解释,获取特定作品的所有可能动作
PieceMovements.move()将一块(p)移动到位置(m - >代表一个移动)
PieceMovements.undo()取消之前的动作
searchDepth是第一次调用miniMax时首先作为深度值传递的变量,换句话说,它是您想要向下搜索的距离。原因......
if(depth == searchDepth) {
piece = p;
move = m;
}
...是记录片段并移动制作。我将此值记录在搜索树的顶层。片段和移动代表实际片段并且移动算法认为是最有效的。
调用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;
}
如果您有任何疑问,请询问。谢谢你的任何回复,我已经坚持了一段时间。我想知道我的迷你max算法或我的评估函数是否确实有问题,或者我的程序中可能还有其他错误,你看不到。 感谢。
答案 0 :(得分:0)
如答案中所指出,您没有使用minimax函数的结果。以下是我使用Python开发的工作版本,希望您可以将其翻译为java :)
这是使用alpha-beta修剪来提高性能。
具有minimax函数的初始调用:
best_move, evaluation = minimax(board, 5, -math.inf, math.inf, True)
Minimax函数本身。 board.is_human_turn在棋盘类中用于确定玩家是谁。然后我们得到该玩家(该位置的子级)的所有可能动作。
然后,它检查我们是否达到最大深度,或者该位置是否超过游戏深度(绘制或检查队友)。
对于每个玩家(分别最大化和最小化),它遍及所有子代。它会制作板副本(不要与原始板一起更改),并在板上移动(一个子级)。然后,它会计算所有节点中的评估,并随评估一起返回最佳移动。
def minimax(board, depth, alpha, beta, maximizing_player):
board.is_human_turn = not maximizing_player
children = board.get_all_possible_moves()
if depth == 0 or board.is_draw or board.is_check_mate:
return None, evaluate(board)
best_move = random.choice(children)
if maximizing_player:
max_eval = -math.inf
for child in children:
board_copy = copy.deepcopy(board)
board_copy.move(child)
current_eval = minimax(board_copy, depth - 1, alpha, beta, False)[1]
if current_eval > max_eval:
max_eval = current_eval
best_move = child
alpha = max(alpha, current_eval)
if beta <= alpha:
break
return best_move, max_eval
else:
min_eval = math.inf
for child in children:
board_copy = copy.deepcopy(board)
board_copy.move(child)
current_eval = minimax(board_copy, depth - 1, alpha, beta, True)[1]
if current_eval < min_eval:
min_eval = current_eval
best_move = child
beta = min(beta, current_eval)
if beta <= alpha:
break
return best_move, min_eval
我的评估功能目前非常简单,仅考虑件值及其在板上的位置。例如,一个骑士最初价值320,然后根据其位置来加减。有关更多信息,请参见以下链接:https://www.chessprogramming.org/Simplified_Evaluation_Function。
您还可以实施一本开场白,这样您就可以在每个游戏中都有一个良好的开端,而不必花费时间计算排名。
希望这会有所帮助!