我正在研究一个项目,尝试创建一个神经网络,学习如何使用NEAT玩跳棋。在我的跳棋游戏中,我使用递归来查找特定部分可以进行的所有可用移动。正常运行程序,效果很好。
问题是当我运行试图训练神经网络的程序部分时。在我的训练计划中,我运行了无数的跳棋游戏(10000+)来尝试进化我的神经网络。训练对于前几千场比赛来说非常有用,但随后我遇到了一个stackoverflow错误,该错误是由检查可用移动的程序的递归部分引起的。这对我来说没有意义,因为这个方法在前几千个左右的游戏中运行良好,但它最终会因堆栈溢出错误而崩溃。
编辑:这是递归方法的主要概述我删除了很多if语句。另外,我为此长度道歉,我可能已经以更具可读性和效率的方式实现了。
private void checkAvailableTilesRecursion(GameBoardTile oldTile, LegalMove newMove) {
ArrayList<LegalMove> recursiveCheck = new ArrayList<>();
// Find available pieces if piece is king
if (!edgePiece) {
// Code to get the different tiles adjacent to this tile
if (legalMoveCheckerPiece.getIsKing()) {
// Up right
// If the tile up right is clear
LegalMove move = new LegalMove(newMove.getNewTile(), board.getTile()[newMove.returnNewY() - 2][newMove.returnNewX() + 2], newMove, null, upRight, MoveDirections.UP_RIGHT);
newMove.setMoveAfter(move);
availableLegalMoves.add(move); // defined elsewhere
recursiveCheck.add(move);
}
// Up left
// If the tile up left is clear
LegalMove move = new LegalMove(newMove.getNewTile(), board.getTile()[newMove.returnNewY() - 2][newMove.returnNewX() - 2], newMove, null, upLeft, MoveDirections.UP_LEFT);
newMove.setMoveAfter(move);
availableLegalMoves.add(move); // defined elsewhere
recursiveCheckRecursive.add(move);
}
// Down right
// If tile down right is clear
LegalMove move = new LegalMove(newMove.getNewTile(), board.getTile()[newMove.returnNewY() + 2][newMove.returnNewX() + 2], newMove, null, downRight, MoveDirections.DOWN_RIGHT);
newMove.setMoveAfter(move);
availableLegalMoves.add(move); // defined elsewhere
recursiveCheckRecursive.add(move);
}
//Down left
// If tile down left is clear
LegalMove move = new LegalMove(newMove.getNewTile(), board.getTile()[newMove.returnNewY() + 2][newMove.returnNewX() - 2], newMove, null, downLeft, MoveDirections.DOWN_LEFT);
newMove.setMoveAfter(move);
availableLegalMoves.add(move); // defined elsewhere
recursiveCheckRecursive.add(move);
}
} else {
// Find available tiles for normal pieces
if (legalMoveCheckerPiece.getColor() == PieceColors.BLUE) {
// Up right
// If tile up right is clear
LegalMove move = new LegalMove(newMove.getNewTile(), board.getTile()[newMove.returnNewY() - 2][newMove.returnNewX() + 2], newMove, null, upRight, MoveDirections.UP_RIGHT);
newMove.setMoveAfter(move);
availableLegalMoves.add(move);
recursiveCheckRecursive.add(move);
}
// Up left
// If tile up left is clear
LegalMove move = new LegalMove(newMove.getNewTile(), board.getTile()[newMove.returnNewY() - 2][newMove.returnNewX() - 2], newMove, null, upLeft, MoveDirections.UP_LEFT);
newMove.setMoveAfter(move);
availableLegalMoves.add(move);
recursiveCheckRecursive.add(move);
}
} else {
// Red Team
// Down right
// If tile down right is clear
LegalMove move = new LegalMove(newMove.getNewTile(), board.getTile()[newMove.returnNewY() + 2][newMove.returnNewX() + 2], newMove, null, downRight, MoveDirections.DOWN_RIGHT);
newMove.setMoveAfter(move);
availableLegalMoves.add(move);
recursiveCheckRecursive.add(move);
}
//Down left
// If tile down left is clear
LegalMove move = new LegalMove(newMove.getNewTile(), board.getTile()[newMove.returnNewY() + 2][newMove.returnNewX() - 2], newMove, null, downLeft, MoveDirections.DOWN_LEFT);
newMove.setMoveAfter(move);
availableLegalMoves.add(move);
recursiveCheckRecursive.add(move);
}
}
}
}
if (recursiveCheckRecursive.size() > 0) {
for (LegalMove moveToCheck : recursiveCheckRecursive) {
checkAvailableTilesRecursion(newMove.getNewTile(), moveToCheck);
}
}
}
编辑#2:我认为这必须对内存泄漏做些什么。我使用的是Intellij Debug工具,Intellij Memory Analyzer显示了这一点。
为什么垃圾收集器在使用完毕后会破坏arraylists和LegalMove对象?
答案 0 :(得分:1)
线程堆栈在JVM中受到限制,可以通过-Xss
选项进行配置。另一种提供堆栈大小的方法是在手动创建Thread
时指定它{。}}。
如果这些替代选项不可行,您可以考虑使用in the constructor而不是递归实现,以便独立于任何限制。
答案 1 :(得分:0)
没有任何代码,很难给出具体的答案。但是,有几个随意的建议是:
(从队长明显的类型建议开始)如果你还没有使用-Xss选项给它更多的堆栈内存。
通过尝试确保大多数堆栈内存中的引用和堆上的大多数对象对象,尝试限制它占用的堆栈空间量,方法是限制方法范围内的局部变量。
将其重写为迭代而不是递归;)