我正在研究一个项目,尝试创建一个神经网络,它将学习如何使用NEAT玩跳棋。在我的跳棋游戏中,我使用递归来查找特定棋子可以制作的所有可用棋步。通常运行程序,效果很好。长时间运行程序时递归导致的Java StackOverflowError
问题是当我运行试图训练神经网络的程序部分时。在我的训练计划中,我运行无数跳棋游戏(10000+)来尝试发展我的神经网络。训练对于上千场比赛非常有用,但后来我遇到了一个由检查可用动作的程序的递归部分引起的stackoverflow错误。这对我来说没有任何意义,因为这种方法对于前1000场比赛来说工作得很好,但最终总是会因为一个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调试工具,Intellij Memory Analyzer显示了这一点。
为什么垃圾收集器在我完成使用它们之后不会破坏arraylist和LegalMove对象?
后递归码 – Aaron
是你的代码,即拍即递归调用?如果是这样,你有没有考虑尝试一种不同的非递归方法? – Obicere
你能发布一些相关的代码吗?不是全部,只是递归的关键部分。 – degs