【发布时间】:2025-12-12 08:00:01
【问题描述】:
我目前正在将国际象棋 AI 应用到我的国际象棋游戏中。现在我正在努力如何处理 AI 的游戏状态。
因为我觉得自己像 AI,需要来自棋盘或游戏类的最新属性(在我的情况下,我发送了一个游戏类)。但我想知道,这是错误的方式。为什么?
每当我使用 minmax 计算 AI 的移动时,我都会尝试将移动放在棋盘上,但问题是这不应该在棋盘上。因为第二个玩家基本上是在使用棋盘。我觉得它会崩溃,因为每当 AI 尝试一个动作时,它都会尝试在棋盘上进行更新,从而导致崩溃。
所以我认为我必须创建游戏/棋盘的假/模拟副本(包含所需的属性、可用动作列表、棋子颜色、玩家等)并将其发送给 AI。但是最好的方法是什么?
我当前的 minimax 算法的代码设置 相关使用的其他代码:https://hastebin.com/niqaderule.java:
public class MiniMax implements MoveStrategy {
private final BoardEvaluator boardEvaluator;
private int searchDepth;
public MiniMax(BoardEvaluator boardEvaluator, int searchDepth) {
this.boardEvaluator = boardEvaluator;
this.searchDepth = searchDepth;
}
@Override
public String toString() {
return "MiniMax{" +
"boardEvaluator=" + boardEvaluator +
'}';
}
@Override
public Move execute(ChessGame game) {
long startTime = System.currentTimeMillis();
Move calculatedBestMove = null;
int highestSeenValue = Integer.MIN_VALUE;
int lowestSeenValue = Integer.MAX_VALUE;
int currentValue;
System.out.println("computer thinks" + " depth= " + this.searchDepth);
var numberOfAllMoves = game.getBoard().getAllAvailableMoves(PieceColor.BLACK);
for(Move move : game.getBoard().getAllAvailableMoves(PieceColor.BLACK)){
game.getBoard().movePiece(move.getSelectedPiece(), move);
currentValue = calculateValue(game);
if(game.getCurrentTurn() == game.getPlayers().get(0) && currentValue >= highestSeenValue)
{
highestSeenValue = currentValue;
calculatedBestMove = move;
}
else if(game.getCurrentTurn() == game.getPlayers().get(1) && currentValue <= lowestSeenValue){
lowestSeenValue = currentValue;
calculatedBestMove = move;
}
}
long CalculationTime = System.currentTimeMillis() - startTime;
return calculatedBestMove;
}
public int calculateValue(ChessGame game){
if(game.getCurrentTurn() == game.getPlayers().get(0)){
return min(game, -1);
}
return max(game, -1);
}
public int min(ChessGame game, int depth){
if(depth == 0 || game.getGameStatus() == GameStatus.BLACK_CHECK_MATE || game.getGameStatus() == GameStatus.WHITE_CHECK_MATE){
return this.boardEvaluator.evaluate(game, depth);
}
int lowestValue = Integer.MAX_VALUE;
for(Move move: game.getBoard().getAllAvailableMoves(PieceColor.BLACK)){
game.getBoard().movePiece(move.getSelectedPiece(), move);
int currentValue = max(game, depth -1);
if(currentValue <= lowestValue)
{
lowestValue = currentValue;
}
}
return lowestValue;
}
public int max(ChessGame game, int depth){
if(depth == 0 || game.getGameStatus() == GameStatus.BLACK_CHECK_MATE || game.getGameStatus() == GameStatus.WHITE_CHECK_MATE){
return this.boardEvaluator.evaluate(game, depth);
}
int highestSeenValue = Integer.MIN_VALUE;
for(Move move: game.getBoard().getAllAvailableMoves(PieceColor.BLACK)){
game.getBoard().movePiece(move.getSelectedPiece(), move);
int currentValue = min(game, depth -1);
if(currentValue <= highestSeenValue)
{
highestSeenValue = currentValue;
}
}
return highestSeenValue;
}
}
【问题讨论】:
-
看看Board representation。你需要评估函数来告诉你当前位置的得分和一组可用的动作。
-
为了清楚起见,每次你得到一组动作时,你都会传递一个具有新状态的棋盘副本。它应该是一个递归函数调用,一旦达到所需的深度就会退出。评分功能由您决定。
-
作为复制棋盘的替代方法,您可以设计一个
takeBack方法来撤消移动,将状态完全恢复到移动之前的状态(包括关于易位、过路俘虏、晋升等的状态)。这可能比复制状态更便宜。
标签: java algorithm artificial-intelligence chess minimax