我正在尝试编写一个永远不会在Tic Tac Toe丢失的AI,我想使用minimax算法来实现这一目标。但是,当我尝试运行程序时,出现堆栈溢出,我似乎无法找到错误。你能看看我告诉我我做错了什么吗?它在我认为的递归中并没有那么深,因为它应该只经历所有可能的游戏结果,最多可以达到8个动作(因为玩家是第一个玩,而不是AI)。可能是我做错了什么,但我找不到任何东西。
编辑:这是完整的代码,机制函数是主要部分: EDIT2:修复了构造函数
Exception in thread "main" java.lang.StackOverflowError
at Packet.Logic$TicTacToe.mechanics(Logic.java:54)
at Packet.Logic$TicTacToe.mechanics(Logic.java:84)
at Packet.Logic$TicTacToe.mechanics(Logic.java:87)
at Packet.Logic$TicTacToe.mechanics(Logic.java:84)
at Packet.Logic$TicTacToe.mechanics(Logic.java:87)
at Packet.Logic$TicTacToe.mechanics(Logic.java:84)
at Packet.Logic$TicTacToe.mechanics(Logic.java:87)
此外,这是我得到的确切错误:
at Packet.Logic$TicTacToe.mechanics(Logic.java:84)
at Packet.Logic$TicTacToe.mechanics(Logic.java:87)
在这部分之后,这些部分出现了很多次(至少50次)
if (win(newBoard,this.playerHuman)){
第54行:
scores.add(this.mechanics(possibleBoard, this.playerHuman));
第84行:
scores.add(this.mechanics(possibleBoard, this.playerAI));
第87行:
{{1}}
答案 0 :(得分:0)
存在一些问题,但是您可以通过以下方式调试此问题:
在您的班级中添加int debugLen = debug.length();
debug.append("\nSetting ").append(availableSpotNumber).append(" to ").append(player);
possibleBoard[availableSpotNumber] = player;
try {
if (player == this.playerAI) {
scores.add(this.mechanics(possibleBoard, this.playerHuman));
} else {
scores.add(this.mechanics(possibleBoard, this.playerAI));
}
moves.add(availableSpotNumber);
} catch (StackOverflowError error) {
throw new StackOverflowError(debug.toString());
}
debug.setLength(debugLen);
possibleBoard[availableSpotNumber] = this.emptySpace;
字段,然后像这样更改主循环:
Setting 0 to 1
Setting 0 to 2
Setting 0 to 1
Setting 0 to 2
etc..
然后你会看到发生了什么,这将为你提供接下来要解决的问题的线索。例如,当前版本正在执行此操作,用于初始人工移动1:
{{1}}
但是,如果你太懒,你可以找到固定版本here。
答案 1 :(得分:0)
这可能是也可能不是代码问题,因为Java不是一个功能齐全的语言,它来递归,你可能希望看到这个答案:Does Java 8 have tail call optimization?
基本上,允许无限深度递归的语言必须具有尾递归优化。使用尾调用优化,如果返回值是具有不同参数的完全相同的函数的结果,则将替换堆栈而不是添加到堆栈的新调用。
如果某种语言没有尾调用优化,那么即使递归调用具有正确的终止条件,您也会受到堆栈大小的限制,即使递归调用具有正确的终止条件(注意:我还没有对其进行分析)代码深入,所以显然在递归逻辑本身可能存在问题)。如果要调整堆栈大小,请使用-Xss
Java运行时参数。通常,增加堆栈大小是一种很好的启发式方法(尽管不是一种万无一失的方法),可以检查错误是使用语言还是使用算法。