gpt4 book ai didi

java - 使用 MinMax 和 Alpha-Beta 修剪找到最佳着法

转载 作者:塔克拉玛干 更新时间:2023-11-03 05:09:21 26 4
gpt4 key购买 nike

我正在为游戏开发 AI,我想将 MinMax 算法与 Alpha-Beta 修剪结合使用。

我对它的工作原理有一个粗略的了解,但我仍然无法从头开始编写代码,所以过去两天我一直在网上寻找某种伪代码。

我的问题是,我在网上找到的每个伪代码似乎都是基于寻找最佳着法的值,而我需要返回最佳着法本身而不是数字。

我当前的代码基于此伪代码 ( source )

minimax(level, player, alpha, beta){  // player may be "computer" or "opponent"
if (gameover || level == 0)
return score
children = all valid moves for this "player"
if (player is computer, i.e., max's turn){
// Find max and store in alpha
for each child {
score = minimax(level - 1, opponent, alpha, beta)
if (score > alpha) alpha = score
if (alpha >= beta) break; // beta cut-off
}
return alpha
} else (player is opponent, i.e., min's turn)
// Find min and store in beta
for each child {
score = minimax(level - 1, computer, alpha, beta)
if (score < beta) beta = score
if (alpha >= beta) break; // alpha cut-off
}
return beta
}
}

// Initial call with alpha=-inf and beta=inf
minimax(2, computer, -inf, +inf)

如您所见,此代码返回一个数字,我猜这是使一切正常工作所必需的(因为在递归过程中使用了返回的数字)。

所以我想我可以使用一个外部变量来存储最佳着法,这就是我如何更改以前的代码:

minimax(level, player, alpha, beta){  // player may be "computer" or "opponent"
if (gameover || level == 0)
return score
children = all valid moves for this "player"
if (player is computer, i.e., max's turn){
// Find max and store in alpha
for each child {
score = minimax(level - 1, opponent, alpha, beta)
if (score > alpha) {
alpha = score
bestMove = current child // ROW THAT I ADDED TO UPDATE THE BEST MOVE
}
if (alpha >= beta) break; // beta cut-off
}
return alpha
} else (player is opponent, i.e., min's turn)
// Find min and store in beta
for each child {
score = minimax(level - 1, computer, alpha, beta)
if (score < beta) beta = score
if (alpha >= beta) break; // alpha cut-off
}
return beta
}
}

// Initial call with alpha=-inf and beta=inf
minimax(2, computer, -inf, +inf)

现在,这对我来说是有意义的,因为我们只需要在轮到玩家时更新最佳着法并且该着法比之前的好。

所以,虽然我认为这个是正确的(即使我不是 100% 确定),source还有一个 java 实现来更新 bestMove即使在 score < beta案例,我不明白为什么。

尝试使用该实现导致我的代码选择对方玩家的最佳着法,这似乎不正确(假设我是黑人玩家,我正在寻找我认为最好的着法可以做到,所以我期待“黑色”的举动而不是“白色”的举动)。

我不知道我的伪代码(第二个)是否是使用 MinMaxalpha-beta 修剪 找到最佳着法的正确方法,或者我是否需要即使在 score < beta 情况下也能更新最佳着法。

如果您愿意,请随时提出任何新的和更好的伪代码,我不受任何约束,如果它比我的更好,我不介意重写一些代码。

编辑:

由于我看不懂回复,我想也许这个问题没有问我想知道什么,所以我想在这里写得更好。

假设我只想为一个玩家获得最佳着法,并且这个玩家,最大化器,每次我需要时都被传递给 MinMax 函数一个新的着法(因此 minmax(2, black, a, b) 返回黑人玩家的最佳着法,而 minmax(2, white, a ,b) 返回白人玩家的最佳着法),您将如何更改第一个伪代码(或 java 实现)在源代码中)将这个给定的最佳移动存储在某个地方?

编辑 2:

让我们看看我们能否让它以这种方式工作。

这是我的实现,你能告诉我它是否正确吗?

//PlayerType is an enum with just White and Black values, opponent() returns the opposite player type
protected int minMax(int alpha, int beta, int maxDepth, PlayerType player) {
if (!canContinue()) {
return 0;
}
ArrayList<Move> moves = sortMoves(generateLegalMoves(player));
Iterator<Move> movesIterator = moves.iterator();
int value = 0;
boolean isMaximizer = (player.equals(playerType)); // playerType is the player used by the AI
if (maxDepth == 0 || board.isGameOver()) {
value = evaluateBoard();
return value;
}
while (movesIterator.hasNext()) {
Move currentMove = movesIterator.next();
board.applyMove(currentMove);
value = minMax(alpha, beta, maxDepth - 1, player.opponent());
board.undoLastMove();
if (isMaximizer) {
if (value > alpha) {
selectedMove = currentMove;
alpha = value;
}
} else {
if (value < beta) {
beta = value;
}
}
if (alpha >= beta) {
break;
}
}
return (isMaximizer) ? alpha : beta;
}

编辑 3:

基于@Codor 的回答/评论的新实现

private class MoveValue {
public Move move;
public int value;

public MoveValue() {
move = null;
value = 0;
}

public MoveValue(Move move, int value) {
this.move = move;
this.value = value;
}

@Override
public String toString() {
return "MoveValue{" + "move=" + move + ", value=" + value + '}';
}

}

protected MoveValue minMax(int alpha, int beta, int maxDepth, PlayerType player) {
if (!canContinue()) {
return new MoveValue();
}
ArrayList<Move> moves = sortMoves(generateLegalMoves(player));
Iterator<Move> movesIterator = moves.iterator();
MoveValue moveValue = new MoveValue();
boolean isMaximizer = (player.equals(playerType));
if (maxDepth == 0 || board.isGameOver()) {
moveValue.value = evaluateBoard();
return moveValue;
}
while (movesIterator.hasNext()) {
Move currentMove = movesIterator.next();
board.applyMove(currentMove);
moveValue = minMax(alpha, beta, maxDepth - 1, player.opponent());
board.undoLastMove();
if (isMaximizer) {
if (moveValue.value > alpha) {
selectedMove = currentMove;
alpha = moveValue.value;
}
} else {
if (moveValue.value < beta) {
beta = moveValue.value;
selectedMove = currentMove;
}
}
if (alpha >= beta) {
break;
}
}
return (isMaximizer) ? new MoveValue(selectedMove, alpha) : new MoveValue(selectedMove, beta);
}

我不知道我做对了还是做错了什么,但我又回到了我发布问题时遇到的问题:

调用 minMax(Integer.MIN_VALUE, Integer.MAX_VALUE, 1, PlayerType.Black)返回一个只能由白人玩家完成的 Action ,这不是我需要的。

我需要给定玩家的最佳着法,而不是整个棋盘的最佳着法。

最佳答案

经过一些研究并浪费了大量时间来解决这个问题,我想出了这个似乎可行的解决方案。

private class MoveValue {

public double returnValue;
public Move returnMove;

public MoveValue() {
returnValue = 0;
}

public MoveValue(double returnValue) {
this.returnValue = returnValue;
}

public MoveValue(double returnValue, Move returnMove) {
this.returnValue = returnValue;
this.returnMove = returnMove;
}

}


protected MoveValue minMax(double alpha, double beta, int maxDepth, MarbleType player) {
if (!canContinue()) {
return new MoveValue();
}
ArrayList<Move> moves = sortMoves(generateLegalMoves(player));
Iterator<Move> movesIterator = moves.iterator();
double value = 0;
boolean isMaximizer = (player.equals(playerType));
if (maxDepth == 0 || board.isGameOver()) {
value = evaluateBoard();
return new MoveValue(value);
}
MoveValue returnMove;
MoveValue bestMove = null;
if (isMaximizer) {
while (movesIterator.hasNext()) {
Move currentMove = movesIterator.next();
board.applyMove(currentMove);
returnMove = minMax(alpha, beta, maxDepth - 1, player.opponent());
board.undoLastMove();
if ((bestMove == null) || (bestMove.returnValue < returnMove.returnValue)) {
bestMove = returnMove;
bestMove.returnMove = currentMove;
}
if (returnMove.returnValue > alpha) {
alpha = returnMove.returnValue;
bestMove = returnMove;
}
if (beta <= alpha) {
bestMove.returnValue = beta;
bestMove.returnMove = null;
return bestMove; // pruning
}
}
return bestMove;
} else {
while (movesIterator.hasNext()) {
Move currentMove = movesIterator.next();
board.applyMove(currentMove);
returnMove = minMax(alpha, beta, maxDepth - 1, player.opponent());
board.undoLastMove();
if ((bestMove == null) || (bestMove.returnValue > returnMove.returnValue)) {
bestMove = returnMove;
bestMove.returnMove = currentMove;
}
if (returnMove.returnValue < beta) {
beta = returnMove.returnValue;
bestMove = returnMove;
}
if (beta <= alpha) {
bestMove.returnValue = alpha;
bestMove.returnMove = null;
return bestMove; // pruning
}
}
return bestMove;
}
}

关于java - 使用 MinMax 和 Alpha-Beta 修剪找到最佳着法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27527090/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com