java - Java Minimax tic-tac-toe 游戏未按预期工作
问题描述
因此,我一直在研究创建一个简单的井字游戏,其中人类玩家与由 minimax 算法运行的 AI 进行游戏。在过去的几天里,我一直在试图找出这两个错误,但我似乎一辈子都做不到。一方面,人工智能似乎有点可预测并且不是很好。其次,它似乎唯一可行的方法是如果人工智能先行,如果我让人类玩家先行,人工智能就会继续填补下一个可用位置。任何帮助将不胜感激。
这是我的代码:
import java.util.Scanner;
public class Game
{
static String player = "X";
static String opponent = "O";
int row;
int col;
public Game(int x, int y)
{
row = x;
col = y;
}
public static void main(String[] args)
{
Scanner input = new Scanner(System.in);
String [][] board = new String [3][3];
fillBoard(board);
while(true) //Infinite loop only for testing, will change back
{
getBestMove(board);
printBoard(board);
playerTurn(board, input);
printBoard(board);
//System.out.println("Best move: " + bestMove.row + " " + bestMove.col);
}
//input.close();
}
static int checkState(String [][] board)
{
for (int row = 0; row<3; row++) //Rows
{
if (board[row][0] == board[row][1] &&
board[row][1] == board[row][2])
{
if (board[row][0]==player)
return -10;
else if (board[row][0]==opponent)
return +10;
}
}
for (int col = 0; col<3; col++) //Columns
{
if (board[0][col]==board[1][col] &&
board[1][col]==board[2][col])
{
if (board[0][col]==player)
return -10;
else if (board[0][col]==opponent)
return +10;
}
}
if (board[0][0]==board[1][1] && board[1][1]==board[2][2]) //Diagonal
{
if (board[0][0]==player)
return -10;
else if (board[0][0]==opponent)
return +10;
}
else if (board[0][2]==board[1][1] && board[1][1]==board[2][0]) //Diagonal
{
if (board[0][2]==player)
return -10;
else if (board[0][2]==opponent)
return +10;
}
return 0;
}
public static void getBestMove(String[][] board)
{
int bestValue = -1000;
Game bestMove = new Game(-1,-1);
for(int i = 0; i < 3; i++)
{
for(int j = 0; j < 3; j++)
{
if(board[i][j] == "-")
{
board[i][j] = player;
int currentValue = minimax(board, 0, false);
board[i][j] = "-";
if(currentValue > bestValue)
{
bestMove.row = i;
bestMove.col = j;
bestValue = currentValue;
}
}
}
}
board[bestMove.row][bestMove.col]= opponent;
}
public static int minimax(String [][] board, int depth, boolean isMaximizer)
{
if(checkState(board) != 0)
return checkState(board);
if(checkRemainingPlays(board) == false)
return 0;
if(isMaximizer)
{
int highest = -1000;
for(int i = 0; i < 3; i++)
{
for(int j = 0; j < 3; j++)
{
if(board[i][j] == "-")
{
board[i][j] = player;
highest = Math.max(highest, minimax(board, depth + 1, !isMaximizer));
board[i][j] = "-";
}
}
}
return highest;
}
else
{
int lowest = 1000;
for(int i = 0; i < 3; i++)
{
for(int j = 0; j < 3; j++)
{
if(board[i][j] == "-")
{
board[i][j] = opponent;
lowest = Math.min(lowest, minimax(board, depth + 1, !isMaximizer));
board[i][j] = "-";
}
}
}
return lowest;
}
}
public static void playerTurn(String [][] board , Scanner input)
{
input = new Scanner(System.in);
System.out.println("Player 1: ");
System.out.println("Please enter the index of desired spot (I) ");
int desiredIndexI = input.nextInt();
System.out.println("Please enter the index of desired spot (J) ");
int desiredIndexJ = input.nextInt();
while(board[desiredIndexI][desiredIndexJ] != "-")
{
System.out.println("Please enter the index of desired spot (I) ");
desiredIndexI = input.nextInt();
System.out.println("Please enter the index of desired spot (J) ");
desiredIndexJ = input.nextInt();
}
board[desiredIndexI][desiredIndexJ] = player;
}
public static boolean checkRemainingPlays(String [][] board)
{
for(int i = 0; i < board.length; i++)
{
for(int j = 0; j < board[i].length; j++)
{
if (board[i][j] == "-")
return true;
}
}
return false;
}
public static void printBoard(String [][] board)
{
for(int i = 0; i < board.length; i++)
{
if(i <= 2 && i > 0)
System.out.println("----------");
for(int j = 0; j < board[i].length; j++)
{
if(j < 2)
System.out.print(board[i][j] + " | ");
if(j == 2)
System.out.println(board[i][j]);
}
}
}
public static void fillBoard(String [][] board)
{
for(int i = 0; i < board.length; i++)
{
for(int j = 0; j < board[i].length; j++)
{
board[i][j] = "-";
}
}
}
}
解决方案
首先,我想从好消息开始。使用 minimax 算法解决井字游戏是对人工智能初学者的一次很好的培训。问题并不容易,它很好地教导了人工智能规划是什么。使用Java实现游戏加上求解器也是一个不错的选择,因为该语言无处不在,支持面向对象的编程并且执行速度合理。
现在我想介绍关键方面。第一个问题是,人工智能相关问题与正常的计算任务有很大不同。如果源代码是关于将 AWT Java GUI 绘制到屏幕上,或者关于如何向类发送参数,我相信这个问题可以很容易地回答。在大多数情况下,人工智能主题不会因为编程问题而失败,这意味着如何使用某种编程语言,而是因为底层算法。
描述和解决人工智能问题的讨论空间不在编程领域,而是在古腾堡星系。这意味着,围绕人工智能玩井字游戏和 Minimax 算法,至少有 1000 篇论文、书籍和 powerpoint 演示文稿可用。新手的任务不是编写 Java 源代码,而是阅读和引用这些源代码。这有助于其他人了解问题并提供详细的反馈。
我知道,这个道德指导并没有回答最初的问题,但目的是解释为什么我按下了“将问题迁移到https://ai.stackexchange.com/ ”按钮。在这个论坛中,问题将很快得到答案。
推荐阅读
- mongodb - 如何检查集合的字段是否包含单个值或值数组
- java - 如何在java中同步异步操作
- antlr - 语义谓词影响范围
- intellij-idea - 有没有办法在 Intellij Scene Builder 中包含 JavaFX controlsFX?
- html - 在伪元素在 chrome 和 firefox 上出现不同之前
- swift - 带有 if 条件的 Swift 映射函数
- java - Spring hibernate CrudRepository 根据唯一约束更新保存方法
- java - 有扩展网址吗?
- php - 从另一个驱动器上的文档根目录连接到 XAMPP MySQL 数据库
- javascript - 如何在 Vue 中的组件之间共享一些代码