Je travaille sur un projet pour essayer de créer un réseau neuronal qui va apprendre à jouer aux checkers en utilisant NEAT. Dans mon jeu de dames, j'utilise la récursivité pour trouver tous les mouvements disponibles qu'un morceau spécifique peut faire. En cours d'exécution du programme normalement, cela fonctionne très bien.Java StackOverflowError causée par la récursivité lors de l'exécution du programme pendant de longues périodes de temps
Le problème est lorsque je lance la partie du programme qui essaie de former le réseau de neurones. Dans mon programme d'entraînement, je cours d'innombrables jeux de dames (10000+) pour essayer d'évoluer mon réseau de neurones. La formation fonctionne bien pour le premier millier de jeux, mais je suis alors frappé par une erreur de stackoverflow causée par la partie récursive du programme qui vérifie les mouvements disponibles. Cela n'a aucun sens pour moi car la méthode fonctionne bien pour le premier millier de jeux, mais elle finit toujours par tomber en panne avec une erreur de stackoverflow.
EDIT: Voici l'aperçu général de la méthode récursive que j'ai découpé un grand nombre des instructions if. Aussi, je m'excuse pour la longueur de ceci, j'aurais probablement pu mettre en application de manière plus lisible et efficace.
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);
}
}
}
EDIT # 2: Je pense que cela doit faire quelque chose avec une fuite de mémoire. J'utilisais l'outil Intellij Debug et l'Intellij Memory Analyzer l'a montré. Pourquoi le garbage collector ne détruirait-il pas les arraylists et les objets LegalMove après que j'aie fini de les utiliser?
Postez le code récursion – Aaron
Est-ce votre code qui fait les appels récursifs? Si oui, avez-vous envisagé d'essayer une approche différente - non récursive? – Obicere
Pouvez-vous poster du code pertinent? Pas tout, seulement les parties clés de la récursivité. – degs