TicTacToe minimax 算法没有选择最佳着法
TicTacToe minimax algorithm not picking best move
我一直在为我的井字游戏编写极小极大算法,但它似乎没有选择正确的着法。有可能战胜计算机,所以我一定在这里搞混了。我认为算法本身看起来不错,所以我很确定问题在于我如何获得最佳着法。有人有什么建议吗?
极小极大法
private int minimax(Board board, boolean maximizingPlayer, char symbol){
//System.out.println(symbol);
Board copyBoard = new Board(board.getCells());
char winner = copyBoard.checkWin();
if(winner!='-' || copyBoard.checkDraw()){
return score(winner);
}
if(maximizingPlayer){
int bestValue = Integer.MIN_VALUE;
for(Board b : simulatePossibleMoves(copyBoard,mySymbol)){
int value = minimax(b,false,switchSymbol(mySymbol));
if(bestValue < value){
bestValue = value;
bestMove = b.getLastMove();
}
}
return bestValue;
}
else{
int bestValue = Integer.MAX_VALUE;
for(Board b: simulatePossibleMoves(copyBoard, switchSymbol(mySymbol))){
int value = minimax(b,true,mySymbol);
if(bestValue > value){
bestValue = value;
bestMove = b.getLastMove();
}
}
return bestValue;
}
}
评分方法
private int score(char winner){
if(winner == mySymbol)
return 10;
else if(winner == switchSymbol(mySymbol))
return -10;
return 0;
}
编辑:
游戏示例(人类是X,AI是O)
O 左上角
x 中心
O中左
X 左下
O 中上
X 右上角(人类获胜)
编辑 2:
更多代码,不确定错误是否在此处,不妨包含它。
private ArrayList<Integer> getPossibleMoves(Board board){
ArrayList<Integer> moves = new ArrayList<>();
for(int i = 0; i < board.getCells().length; i++)
if(!board.isCellTaken(i))
moves.add(i);
return moves;
}
private ArrayList<Board> simulatePossibleMoves(Board board, char symbol){
ArrayList<Board> possibleBoards = new ArrayList<>();
for(Integer move : getPossibleMoves(board)){
Board temp = new Board(board.getCells());
temp.setCell(move, symbol);
possibleBoards.add(temp);
}
return possibleBoards;
}
private char switchSymbol(char s){
if(s=='X')
return 'O';
return 'X';
}
事实证明,我一直在尝试通过在 minimax 方法本身中选择最佳值来错误地使用该算法。通过创建另一个调用 minimax 方法的方法,我能够以这种方式找到最佳着法。以下代码对我有用。
public int getMiniMaxMove(Board board){
int score = -1;
int bestMove = -1;
for(int i : getPossibleMoves(board)){
Board copyBoard = new Board(board.getCells());
copyBoard.setCell(i, mySymbol);
int moveScore = minimax(copyBoard,false,mySymbol);
if(moveScore >= score){
score = moveScore;
bestMove = i;
}
}
return bestMove;
}
private int minimax(Board board, boolean maximizingPlayer, char symbol){
Board copyBoard = new Board(board.getCells());
char winner = copyBoard.checkWin();
if(winner!='-' || copyBoard.checkDraw()){
return score(winner);
}
if(maximizingPlayer){
int bestValue = Integer.MIN_VALUE;
for(Board b : simulatePossibleMoves(copyBoard,mySymbol)){
int value = minimax(b,false,switchSymbol(mySymbol));
if(bestValue < value){
bestValue = value;
}
}
return bestValue;
}
else{
int bestValue = Integer.MAX_VALUE;
for(Board b: simulatePossibleMoves(copyBoard, switchSymbol(mySymbol))){
int value = minimax(b,true,mySymbol);
if(bestValue > value){
bestValue = value;
}
}
return bestValue;
}
}
我一直在为我的井字游戏编写极小极大算法,但它似乎没有选择正确的着法。有可能战胜计算机,所以我一定在这里搞混了。我认为算法本身看起来不错,所以我很确定问题在于我如何获得最佳着法。有人有什么建议吗?
极小极大法
private int minimax(Board board, boolean maximizingPlayer, char symbol){
//System.out.println(symbol);
Board copyBoard = new Board(board.getCells());
char winner = copyBoard.checkWin();
if(winner!='-' || copyBoard.checkDraw()){
return score(winner);
}
if(maximizingPlayer){
int bestValue = Integer.MIN_VALUE;
for(Board b : simulatePossibleMoves(copyBoard,mySymbol)){
int value = minimax(b,false,switchSymbol(mySymbol));
if(bestValue < value){
bestValue = value;
bestMove = b.getLastMove();
}
}
return bestValue;
}
else{
int bestValue = Integer.MAX_VALUE;
for(Board b: simulatePossibleMoves(copyBoard, switchSymbol(mySymbol))){
int value = minimax(b,true,mySymbol);
if(bestValue > value){
bestValue = value;
bestMove = b.getLastMove();
}
}
return bestValue;
}
}
评分方法
private int score(char winner){
if(winner == mySymbol)
return 10;
else if(winner == switchSymbol(mySymbol))
return -10;
return 0;
}
编辑:
游戏示例(人类是X,AI是O)
O 左上角
x 中心
O中左
X 左下
O 中上
X 右上角(人类获胜)
编辑 2:
更多代码,不确定错误是否在此处,不妨包含它。
private ArrayList<Integer> getPossibleMoves(Board board){
ArrayList<Integer> moves = new ArrayList<>();
for(int i = 0; i < board.getCells().length; i++)
if(!board.isCellTaken(i))
moves.add(i);
return moves;
}
private ArrayList<Board> simulatePossibleMoves(Board board, char symbol){
ArrayList<Board> possibleBoards = new ArrayList<>();
for(Integer move : getPossibleMoves(board)){
Board temp = new Board(board.getCells());
temp.setCell(move, symbol);
possibleBoards.add(temp);
}
return possibleBoards;
}
private char switchSymbol(char s){
if(s=='X')
return 'O';
return 'X';
}
事实证明,我一直在尝试通过在 minimax 方法本身中选择最佳值来错误地使用该算法。通过创建另一个调用 minimax 方法的方法,我能够以这种方式找到最佳着法。以下代码对我有用。
public int getMiniMaxMove(Board board){
int score = -1;
int bestMove = -1;
for(int i : getPossibleMoves(board)){
Board copyBoard = new Board(board.getCells());
copyBoard.setCell(i, mySymbol);
int moveScore = minimax(copyBoard,false,mySymbol);
if(moveScore >= score){
score = moveScore;
bestMove = i;
}
}
return bestMove;
}
private int minimax(Board board, boolean maximizingPlayer, char symbol){
Board copyBoard = new Board(board.getCells());
char winner = copyBoard.checkWin();
if(winner!='-' || copyBoard.checkDraw()){
return score(winner);
}
if(maximizingPlayer){
int bestValue = Integer.MIN_VALUE;
for(Board b : simulatePossibleMoves(copyBoard,mySymbol)){
int value = minimax(b,false,switchSymbol(mySymbol));
if(bestValue < value){
bestValue = value;
}
}
return bestValue;
}
else{
int bestValue = Integer.MAX_VALUE;
for(Board b: simulatePossibleMoves(copyBoard, switchSymbol(mySymbol))){
int value = minimax(b,true,mySymbol);
if(bestValue > value){
bestValue = value;
}
}
return bestValue;
}
}