Java中的miniMax算法
我目前对我正在编程的AI不满意。人工智能应该在一个3x3的棋盘(TicTacToe)中获得每一步的最佳分数 可能的分数是-1(输),0(平)和1(赢) 首先调用方法Java中的miniMax算法,java,recursion,artificial-intelligence,tic-tac-toe,minimax,Java,Recursion,Artificial Intelligence,Tic Tac Toe,Minimax,我目前对我正在编程的AI不满意。人工智能应该在一个3x3的棋盘(TicTacToe)中获得每一步的最佳分数 可能的分数是-1(输),0(平)和1(赢) 首先调用方法makeTurn(),然后调用包含miniMax算法的方法 public void makeTurn(Button[][] currentBoard) { // Calculating best move using miniMax alg
makeTurn()
,然后调用包含miniMax算法的方法
public void makeTurn(Button[][] currentBoard) { // Calculating best move using miniMax algorithm
AIcheck = new Check(currentBoard);
int bestScore = Integer.MIN_VALUE;
int[] bestMove = new int[2];
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (currentBoard[i][j].getText().equals("")) {
currentBoard[i][j].setText("O");
int score = calcScore(currentBoard, 0, false);
System.out.println(score);
currentBoard[i][j].setText("");
if (score > bestScore) {
bestScore = score;
bestMove = new int[]{i, j};
}
}
}
}
Board.getInstance().getField(bestMove[0], bestMove[1]).performClick();
}
public void makeTurn(按钮[][]currentBoard){//使用miniMax算法计算最佳移动
A检查=新检查(电流板);
int bestScore=整数最小值;
int[]bestMove=新int[2];
对于(int i=0;i<3;i++){
对于(int j=0;j<3;j++){
if(currentBoard[i][j].getText().equals(“”){
电流板[i][j].setText(“O”);
int分数=CalcCore(电流板,0,假);
系统输出打印项次(分数);
电流板[i][j].setText(“”);
如果(分数>最佳分数){
最佳分数=分数;
bestMove=newint[]{i,j};
}
}
}
}
Board.getInstance().getField(bestMove[0],bestMove[1]).performClick();
}
private int-calcScore(按钮[][]currentBoard,int-depth,boolean-isMax){//MiniMax算法,通过递归执行计算每个分支的分数
智力得分;
if(AIcheck.checkWin()){
返回(Util.getInstance().getTurnCounter()%2)==0?1:-1;
}else if(AIcheck.checkTie()){
返回0;
}
int bestScore=isMax?Integer.MIN_值:Integer.MAX_值;
对于(int i=0;i<3;i++){
对于(int j=0;j<3;j++){
if(currentBoard[i][j].getText().equals(“”){
if(isMax){
电流板[i][j].setText(“O”);
}否则{
电流板[i][j].setText(“X”);
}
分数=CalcCore(电流板,深度+1,!isMax);
电流板[i][j].setText(“”);
bestScore=isMax?Math.max(bestScore,score):Math.min(bestScore,score);
}
}
}
返回最佳分数;
}
我使用isMax
来确定是否轮到了最大化者,还使用turnCounter%2
来确定轮到了哪个玩家,因为他们轮流
然而人工智能并没有阻止我获胜,它更像是从一个领域转到下一个领域,而不是选择最佳领域。
我怎样才能正确地实现miniMax算法?
非常感谢
例如:
【】【】【】【】【】
【】【】【】【】【】
[十] |[]|[]
[O] |[]|[] 【】【】【】【】【】 [十] |[]|[]
[O] |[]|[] 【】【】【】【】【】 [十] |[]|[X]
[O] |[O]|[] 【】【】【】【】【】 [十] |[]|[X]
[O] |[O]|[X] 【】【】【】【】【】 [十] |[]|[X]
[O] |[O]|[X] [O] |[]|[] [十] |[]|[X]
[O] |[O]|[X] [O] |[X]|[]我赢了,这也表明人工智能似乎刚刚占据了下一个位置(从左到右)
[十] |[]|[X]我认为问题在于
calcScore()中的这一行。
如果电路板为空,则只计算分数,但在调用函数之前,始终将其设置为“0”,因此该if的代码块将永远不会执行
makeTurn()
与此类似,但我想你是在轮次之间清理黑板吧?如果没有,你也需要更新这个
编辑:
在主要功能中:
currentBoard[i][j].setText("O");
int score = calcScore(currentBoard, 0, false);
在calcScore:
// this will always evaluate to false
if (currentBoard[i][j].getText().equals("")) {
你的最佳成绩作业有问题。对于每个空框,请执行以下操作:
int bestScore = isMax ? Integer.MIN_VALUE : Integer.MAX_VALUE;
如果您这样计算,您将始终得到相同的分数,这可能是它只选择下一个空框的原因。在minimax算法中,您需要一种为每个移动分配不同分数值的方法,以便通过比较找到最佳移动。在国际象棋或类似的游戏中,这些分数通常是通过一些试探法得出的。因为你的游戏简单得多,所以这应该更容易。一个简单的解决方案可能是为每个板状态分配不同的分数,您可以简单地选择导致该状态的移动。你可以很容易地做到这一点,因为在你的游戏中,这些状态的数量非常有限。我认为问题在于如何确定谁在
calcScore
中获胜。您使用了Util.getInstance().getTurnCounter()
,但在递归调用中似乎没有更新计数器。您只需使用depth%2
或isMax
即可:
if (AIcheck.checkWin()) {
return isMax ? -1 : 1;
}
这很有帮助,谢谢,但遗憾的是,它没有从整体上解决问题(@M0e“不能解决整个问题”是什么意思?您仍然能够通过此更改获胜吗?是的,但我发现了错误。算法本身是正确的(正如我所认为的那样,因此我感到困惑),但是checkWin()是错误的,也是您提到的。由于没有您的更正,我无法完成此操作,因此我会将您的答案标记为正确。谢谢!但我不是在嵌套的for循环中为bestScore分配另一个值吗?据我所知,算法需要一个回合(此处:将其设置为“O”)然后通过递归调用每个回合的miniMax算法来计算这一步有多好。这样,它会得到最佳回合,如果是,它会撤消它所做的每个回合,并获得以前计算的最佳回合。
int bestScore = isMax ? Integer.MIN_VALUE : Integer.MAX_VALUE;
if (AIcheck.checkWin()) {
return isMax ? -1 : 1;
}