【发布时间】:2018-02-02 18:45:39
【问题描述】:
我有一个使用 Minimax 算法的井字游戏。我想通过添加 alpha-beta 修剪来改善这一点。然而,alpha-beta 方法似乎不能有效地计算移动。它只是将它的棋子放在下一个可用空间中,无论它是否是最佳移动。 minimax 方法没有这个问题。我确定这是我一直忽略的简单事情,所以请原谅我。我使用this 教程进行极小值修剪,使用this 教程进行 alpha-beta 修剪。
这是 Minimax 类。它包括 alpha-beta 方法:
public class Minimax {
private Token playerToken;
private EndStates endStates;
private Token opponentToken;
public Minimax(Token playerToken, EndStates endStates) {
this.playerToken = playerToken;
this.endStates = endStates;
opponentToken = makeOpponentToken();
}
public Token makeOpponentToken() {
if (playerToken == Token.O) {
return Token.X;
}
else {
return Token.O;
}
}
public Token getOpponentToken() {
return opponentToken;
}
public int evaluate(Cell[] board) {
//rows across
if (endStates.checkWinByRow(board, playerToken) || endStates.checkWinByColumn(board, playerToken) || endStates.checkWinByDiagonal(board, playerToken)) {
return 10;
}
else if (endStates.checkWinByRow(board, opponentToken) || endStates.checkWinByColumn(board, opponentToken) || endStates.checkWinByDiagonal(board, opponentToken)) {
return -10;
}
return 0;
}
public boolean hasCellsLeft(Cell[] board) {
for (int i=0; i<board.length; i++) {
if (board[i].getToken() == Token.EMPTY) {
return true;
}
}
return false;
}
int MAX = 1000;
int MIN = -1000;
public int alphaBeta(Cell[] board, int depth, boolean isMax, int alpha, int beta) {
int score = evaluate(board);
if (score == 10) {
return score;
}
if (score == -10) {
return score;
}
if (hasCellsLeft(board) == false) {
return 0;
}
if (isMax) {
int best = MIN;
for (int i=0; i<board.length; i++) {
if (board[i].getToken() == Token.EMPTY) {
board[i].setToken(playerToken);
int val = alphaBeta(board,depth+1, !isMax, alpha, beta);
best = Math.max(best, val);
alpha = Math.max(alpha, best);
board[i].resetMarker();
}
if (best <= alpha) {
break;
}
}
return best;
}
else {
int best = MAX;
for (int i=0; i<board.length; i++) {
if (board[i].getToken() == Token.EMPTY) {
board[i].setToken(playerToken);
int val = alphaBeta(board, depth+1, isMax, alpha, beta);
best = Math.min(best, val);
beta = Math.min(beta, best);
board[i].resetMarker();
}
if (beta <= alpha) {
break;
}
}
return best;
}
}
public int minimax(Cell[] board, int depth, boolean isMax) {
int score = evaluate(board);
int best;
if (score == 10) {
return score;
}
if (score == -10) {
return score;
}
if (hasCellsLeft(board) == false) {
return 0;
}
if (isMax) {
best = -1000;
for (int i=0; i<board.length; i++) {
if (board[i].getToken() == Token.EMPTY) {
board[i].setToken(playerToken);
best = Math.max(best, minimax(board, depth+1, !isMax));
board[i].resetMarker();
}
}
return best;
}
else {
best = 1000;
for (int i=0; i<board.length; i++) {
if (board[i].getToken() == Token.EMPTY) {
board[i].setToken(opponentToken);
best = Math.min(best, minimax(board, depth+1, !isMax));
board[i].resetMarker();
}
}
return best;
}
}
public int findBestMove(Cell[] board) {
int bestValue = -1000;
int bestMove = -1;
for (int i=0; i<board.length; i++) {
if (board[i].getToken() == Token.EMPTY) {
board[i].setToken(playerToken);
//int moveValue = minimax(board, 0, false);
int moveValue = alphaBeta(board, 0, true, -1000, 1000);
board[i].resetMarker();
if (moveValue > bestValue) {
bestMove = i;
bestValue = moveValue;
}
}
}
return bestMove;
}
}
board 是一个 9 的数组,其中包含 Token.Empty 的枚举值,但可以分别替换为 Token.X 或 Token.O。
这是调用使用算法的类:
public class ComputerPlayer(Token token, Algorithm minimax ) {
private Token playerToken;
private Algorithm minimax;
public ComputerPlayer(Token playerToken, Algorithm minimax) {
this.playerToken = playerToken;
this.minimax = minimax;
}
public Token getPlayerToken() {
return playerToken;
}
public void makeMove(Cell[] board) {
int chosenCell;
chosenCell = minimax.findBestMove(board);
board[chosenCell].setToken(playerToken);
System.out.println("Player " + playerToken + " has chosen cell " + (chosenCell+1));
}
}
【问题讨论】:
-
欢迎来到 StackOverflow。请阅读并遵循帮助文档中的发布指南。 Minimal, complete, verifiable example 适用于此。在您发布 MCVE 代码并准确描述问题之前,我们无法有效地帮助您。我们应该能够将您发布的代码粘贴到文本文件中并重现您描述的问题。
标签: java algorithm tic-tac-toe minimax alpha-beta-pruning