Java 什么';这个极小极大算法怎么了?
所以我试图学习游戏算法,并编写了这个简单的井字游戏。游戏本身运行得非常好,我创建了一个虚拟的“AI”,开始玩随机移动,但现在我正在研究一个极大极小算法,使我的程序无与伦比。问题是,我花了几个小时试图使这个算法工作,但我无法让它工作/找到一个好地方来解释如何正确地实现它。我做错了什么?谢谢:)Java 什么';这个极小极大算法怎么了?,java,tic-tac-toe,minimax,Java,Tic Tac Toe,Minimax,所以我试图学习游戏算法,并编写了这个简单的井字游戏。游戏本身运行得非常好,我创建了一个虚拟的“AI”,开始玩随机移动,但现在我正在研究一个极大极小算法,使我的程序无与伦比。问题是,我花了几个小时试图使这个算法工作,但我无法让它工作/找到一个好地方来解释如何正确地实现它。我做错了什么?谢谢:) public static int minimax(String[]newBoard,String player)抛出异常{ 如果(isGameOver(newBoard).equals(player)){
public static int minimax(String[]newBoard,String player)抛出异常{
如果(isGameOver(newBoard).equals(player)){return-10;}//玩家获胜
else if(isGameOver(newBoard).equals(computer)){return 10;}//计算机获胜
ArrayList AvailableSpot=空点(新板);
if(availableSpots.size()==0){return 0;}//tie
int index=0,maxScore=-100;
//int[]moveScores=新int[availableSpots.size()];
对于(int i=0;i最大分数){
maxScore=温度;
指数=i;
}
}
收益指数;
}
}
以下是完整的代码供参考:
TicTacToeAI.java
package TicTacToeAI;
import java.util.Scanner;
import java.util.ArrayList;
import TicTacToeAI.randomPlayer;
public class TicTacToeAI {
public static String[] board = {" ", " ", " "," ", " ", " "," ", " ", " "};
/* ^^ we make the array with spaces here because
* 1. initializing it with a for loop kinda sounds stupid, this isn't hard
* 2. makes formatting easier
*/
public static Scanner in = new Scanner(System.in);
public static String computer = "", player = "";
public static void main (String [] args) throws Exception {
// welcome
System.out.println("Welcome to Tic Tac Toe!");
player = choosePieces();
computer = opposite(player);
String turn = "X";
while (isGameOver(board).equals("N")) {
System.out.println(turn + " to move:");
if (turn.equals(computer)) {
board[randomPlayer.makeRandomMove(board)] = computer;
printBoard();
} else {
System.out.println("It's your turn!");
printBoard();
makeMove(player);
}
System.out.println("MINIMAX RETURNS " + minimax(board, turn)); // ------------------------------ DEBUG ------------------
turn = opposite(turn);
}
// the game is now over. print the final board
printBoard();
String result = isGameOver(board);
if (result.equalsIgnoreCase(computer)) {
System.out.println("Computer (" + computer + ") wins! Hooray!");
} else if (result.equalsIgnoreCase("T")) {
System.out.println("It's a tie!");
} else {
System.out.println("Human (" + player + ") wins! Congratulations!");
}
}
public static void printBoard() {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
System.out.print(board[i*3 + j] + "|");
}
System.out.print("\n");
}
System.out.print("\n"); // for spaced out formatting
}
public static String choosePieces() {
System.out.println("Would you like to play as X or O? (X is first)");
String piece = in.nextLine();
while (!(piece.equalsIgnoreCase("X") || piece.equalsIgnoreCase("O"))) {
System.out.println("Invalid input! Please enter X or O:");
piece = in.nextLine();
}
return piece.toUpperCase();
}
public static String opposite(String piece) {
if (piece.equalsIgnoreCase("X")) { return "O"; }
return "X";
}
public static String isGameOver(String[] b) { // b for board
/* String because we can transmit both wether or not the game is over
* (empty as long as game isn't over), who's the winner (by making it equal to the winner's piece),
* AND wether or not it is a tie ("T" for tie) */
for (int i = 0; i < 3; i++) {
// check horizontally
if (b[3*i].equals(b[3*i + 1]) && b[3*i].equals(b[3*i + 2]) && !b[3*i].equals(" ")) {
return b[3*i];
}
// check vertically
if (b[i].equals(board[i+3]) && b[i].equals(b[i+6]) && !b[i].equals(" ")) {
return b[i];
}
}
// check diagonally
if (b[0].equals(b[4]) && b[4].equals(b[8]) && !b[0].equals(" ")) {
return b[0];
}
if (b[2].equals(b[4]) && b[2].equals(b[6]) && !b[2].equals(" ")) {
return b[2];
}
// check for tie
for (int i = 0; i < b.length; i++) {
if (b[i] == " ") { return "N"; } // not a tie, game isn't over
}
return "T"; // a tie (no winner found, and no spots left)
}
public static void makeMove(String piece) {
System.out.println("Please enter a move location (1-9):");
int location = in.nextInt() - 1;
/* make sure location is valid
* NOTE: This will not cause an index out of bounds error as if it is,
* the first two conditionals will catch it ;)
*/
while (location < 0 || location > 8 || !board[location].equals(" ")) {
System.out.println("Invalid move location! Please enter a valid move location 1-9:");
location = in.nextInt() - 1;
}
board[location] = piece;
}
public static String[] makeNewMove(String piece, int location) throws Exception {
// same as above method but without output or verification. for computer's use only
String[] newBoard = board.clone();
try {
newBoard[location] = piece;
} catch (Exception e) {
System.out.println("Invalid computer input.");
}
return newBoard;
}
public static ArrayList<Integer> emptySpots(String[] board) {
// returns arraylist with index values of empty (" ") spots
ArrayList<Integer> emptySpots = new ArrayList<Integer>();
for (int i = 0; i < board.length; i++) {
if (board[i].equals(" ")) { emptySpots.add(i); }
}
return emptySpots;
}
public static int getBestMove() {
return 0; //minimax algorithm to be implemented here
}
public static int minimax(String[] newBoard, String player) throws Exception {
if (isGameOver(newBoard).equals(player)) { return -10; } // player wins
else if (isGameOver(newBoard).equals(computer)) { return 10; } // computer wins
ArrayList<Integer> availableSpots = emptySpots(newBoard);
if (availableSpots.size() == 0) { return 0; } // tie
int index = 0, maxScore = -100;
//int[] moveScores = new int[availableSpots.size()];
for (int i = 0; i < availableSpots.size(); i++) {
int temp = minimax(makeNewMove(opposite(player), availableSpots.get(i)), opposite(player));
if (temp > maxScore) {
maxScore = temp;
index = i;
}
}
return index;
}
}
package TicTacToeAI;
import java.util.Random;
import java.util.ArrayList;
public class randomPlayer {
public static int makeRandomMove(String[] board) {
Random rand = new Random();
ArrayList<Integer> availableSpots = new ArrayList<Integer>();
for (int i = 0; i < board.length; i++) {
if (!(board[i].equalsIgnoreCase("X") || board[i].equalsIgnoreCase("O"))) {
availableSpots.add(i);
}
}
return availableSpots.get(rand.nextInt(availableSpots.size()));
}
}
package-TicTacToeAI;
导入java.util.Scanner;
导入java.util.ArrayList;
导入TicTacToeAI.random播放器;
公共类Tictatcoaei{
公共静态字符串[]board={“”、“”、“”、“”、“”、“”、“”、“”、“”、“”、“”、“”};
/*^^我们在此处使用空格创建数组,因为
*1.用for循环初始化它听起来有点愚蠢,这并不难
*2.使格式化更容易
*/
公共静态扫描仪in=新扫描仪(System.in);
公共静态字符串计算机=”,播放器=”;
公共静态void main(字符串[]args)引发异常{
//欢迎光临
System.out.println(“欢迎来到Tic-Tac-Toe!”);
player=选择片段();
电脑=对方(玩家);
字符串turn=“X”;
while(isGameOver(board).equals(“N”)){
System.out.println(转动+”移动:);
if(圈数等于(计算机)){
棋盘[randomPlayer.makeRandomMove(棋盘)]=计算机;
印制板();
}否则{
System.out.println(“轮到你了!”);
印制板();
makeMove(玩家);
}
System.out.println(“MINIMAX返回”+MINIMAX(线路板,转弯));//------------------------------------调试------------------
转弯=反向(转弯);
}
//游戏现在结束了。打印最后的棋盘
印制板();
字符串结果=isGameOver(板);
if(结果等信号情况(计算机)){
System.out.println(“计算机(“+Computer+”)获胜!万岁!”);
}else if(result.equalsIgnoreCase(“T”)){
System.out.println(“打成平局了!”);
}否则{
System.out.println(“人类(“+player+”)获胜!祝贺你!”;
}
}
公共静态无效打印板(){
对于(int i=0;i<3;i++){
对于(int j=0;j<3;j++){
系统输出打印(板[i*3+j]+“|”);
}
系统输出打印(“\n”);
}
System.out.print(“\n”);//用于间隔格式
}
公共静态字符串选择器片段(){
System.out.println(“你想扮演X还是O?(X是第一个)”;
弦段=in.nextLine();
而(!(件号等信号情况(“X”)| |件号等信号情况(“O”)){
System.out.println(“输入无效!请输入X或O:”);
工件=in.nextLine();
}
返回件.toUpperCase();
}
公共静态对弦(弦段){
if(piece.equalsIgnoreCase(“X”){返回“O”}
返回“X”;
}
公共静态字符串isGameOver(字符串[]b){//b用于线路板
/*字符串,因为我们可以同时传输游戏是否结束
*(只要游戏还没结束就清空),谁是赢家(通过使其与赢家的棋子相等),
*不管是不是领带(“T”代表领带)*/
对于(int i=0;i<3;i++){
//水平检查
如果(b[3*i].equals(b[3*i+1])&&b[3*i].equals(b[3*i+2])&&&b[3*i].equals(“”){
返回b[3*i];
}
//垂直检查
如果(b[i].equals(board[i+3])&&b[i].equals(b[i+6])&&&b[i].equals(“”){
返回b[i];
}
}
//对角检查
如果(b[0].等于(b[4])&&b[4].等于(b[8])&&&!b[0].等于(“”){
返回b[0];
}
如果(b[2]。等于(b[4])&&b[2]。等于(b[6])&&&!b[2]。等于(“”){
返回b[2];
}
//检查领带
for(int i=0;i8 | |!线路板[位置]。等于(“”){
System.out.println(“移动位置无效!请输入有效的移动位置1-9:”);
location=in.nextInt()-1;
}
板[位置]=件;
}
公共静态字符串[]makeNewMove(字符串片段,int位置)引发异常{
//与上述方法相同,但无输出或验证。仅供计算机使用
字符串[]newBoard=board.clone();
试一试{
新板【位置】=件;
}捕获(例外e){
System.out.println(“无效的计算机输入”);
}
返回新板;
}
公共静态ArrayList空点(字符串[]板){
//返回索引值为空(“”)的arraylist
ArrayList emptySpots=新的ArrayList();
对于(int i=0;ipackage TicTacToeAI;
import java.util.Random;
import java.util.ArrayList;
public class randomPlayer {
public static int makeRandomMove(String[] board) {
Random rand = new Random();
ArrayList<Integer> availableSpots = new ArrayList<Integer>();
for (int i = 0; i < board.length; i++) {
if (!(board[i].equalsIgnoreCase("X") || board[i].equalsIgnoreCase("O"))) {
availableSpots.add(i);
}
}
return availableSpots.get(rand.nextInt(availableSpots.size()));
}
}
for (int i = 0; i < availableSpots.size(); ++i) {
int currSpot = availableSpots.get(i);
board[currSpot] = currentPlayer;
int temp = minimax(board, opposite(currentPlayer));
board[currSpot] = " ";
//the rest of the loop code
}