我最近一直在作为副项目开发一个井字游戏的人工智能。我已经成功创建了一个工作原型,这个游戏随机生成电脑的移动,使得用户大约90%的时间都能赢。然而,我正在尝试通过极小化极大算法(minimax algorithm)使电脑变得不可战胜。在使用极小化极大算法时,我需要获取棋盘的继任者,这是我遇到的难题。
这是我目前的函数:
public static ArrayList<board> successors(board aBoard) { board orig = aBoard; ArrayList<board> succ = new ArrayList<board>(); for(int i = 0; i < 9; i++) { int row = i / 3; int col = i % 3; if(!orig.gameBoard[row][col].filled) { System.out.println(row); System.out.println(col); System.out.println("Row: " + row + " Column: " + col); board newBoard = orig; //newBoard.gameBoard[row][col].filled = true; //newBoard.gameBoard[row][col].index = 2; succ.add(newBoard); } } System.out.println("Number of successors: " + succ.size()); int emptyIndex = 0; for(int i = 0; i < succ.size(); i++) { //find the empty index // System.out.println(emptyIndex / 3); // System.out.println(emptyIndex % 3); // System.out.println(succ.get(i).gameBoard[emptyIndex / 3][emptyIndex % 3].index + "\n"); while(succ.get(i).gameBoard[emptyIndex / 3][emptyIndex % 3].index != 0) { emptyIndex++; //System.out.println(emptyIndex + " is a good index"); } System.out.println("Empty Index " + emptyIndex); System.out.println("i: " + i); succ.get(i).gameBoard[emptyIndex / 3][emptyIndex % 3].index = 2; succ.get(i).gameBoard[emptyIndex / 3][emptyIndex % 3].filled = true; } return succ;}
它确实最初能正确获取继任者的数量,只是输出有误。例如,我最初的第一步移动如下:
https://i.sstatic.net/Bd47q.jpg
但结果应该包括电脑可以做出的所有可能移动。相反,它输出了这个:
https://i.sstatic.net/gIK2G.jpg
我做错了什么?我已经尝试解决这个问题两天了。
回答:
board newBoard = orig;
newBoard 将指向 orig,因此对 newBoard 所做的所有更改也将对 orig 进行更改,反之亦然。当 AI 在 newBoard 上移动时,移动也会在原始棋盘上进行,因为它们都指向同一个对象。
你需要创建一个与原始棋盘相同的新的棋盘对象,然后在添加到数组列表之前对其进行更改。在复制棋盘状态时,要注意不要复制类和数组等引用,而应使用新的实例。