Java项目中的国际象棋AI实现



我目前正在我的国际象棋游戏中实现国际象棋AI。现在我目前正在为如何处理AI的游戏状态而苦恼。

因为我觉得AI,需要来自棋盘或游戏类的最新属性(在我的情况下,我发送了一个游戏类(。但我想知道,这是错误的方式。为什么?

每当我使用 minmax 计算 AI 的移动时,我都会尝试将移动放在板上,但问题是这不应该在板上。因为第二个玩家基本上都在使用棋盘。我觉得它会崩溃,因为每当AI尝试移动时,它都会尝试在板上更新,从而导致崩溃。

所以我认为我必须创建一个游戏/棋盘的假/模拟副本(包含所需的属性、可用动作列表、棋子颜色、玩家等(并将其发送给 AI。但是最好的方法是什么?

我当前最小最大值算法的代码设置 相关性 使用的其他代码: 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;
}
}

有两种常见的方法可以做到这一点:

  1. 在进行移动之前(递归调用之前(创建电路板表示的深层副本,然后将电路板副本发送到 minimax 函数。

  2. 在电路板上进行移动,将其发送到 minimax 函数,然后收回移动以恢复原始电路板状态。

最近我开始用各种AI机器人做类似的项目,我采取的方法是使用Apache commons-lang3的SerializationUtils。确保板状态类实现可序列化接口,然后可以执行以下操作:

final Board state = SerializationUtils.clone(currentState)

您可以在此处找到更多信息:https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/SerializationUtils.html

最新更新