J'ai un jeu de simulation de ville et essaie de trouver un moyen de vérifier le flux de notre système d'alimentation. Les bases: La carte de la ville est basée sur des tuiles (30 par 30 tuiles = 900 tuiles). Maintenant, je commence à une centrale électrique et je fais une vérification de voisin récursive (en haut, à gauche, à droite, en bas) pour vérifier s'il y a quelque chose qui va transporter l'énergie. S'il y a quelque chose, je commence aussi à vérifier ces tuiles pour les voisins. Pour éviter doubles contrôles et/ou des appels récursifs infinis, je remplis un ArrayList avec des tuiles traitées et vérifier si une nouvelle tuile a déjà été traité et ajouté à la liste de tableaux ...récursive + 900 éléments + voisin check = causes stackoverflow
récursive commencé:
public void updatePowerEnvironment(int id, ArrayList<Integer> elements) {
Log.w("GT", "update env for id: " + id);
int newId = id - GameMap.mMapSize;
if (newId >= 0 && GameMap.mMapCells.get(newId).mPowerEnabled
&& !elements.contains(newId)) {
elements.add(newId);
updatePowerEnvironment(newId, elements);
}
newId = id + GameMap.mMapSize;
if (newId < GameMap.mMapCells.size() && GameMap.mMapCells.get(newId).mPowerEnabled
&& !elements.contains(newId)) {
elements.add(newId);
updatePowerEnvironment(newId, elements);
}
newId = id - 1;
if (newId >= 0 && GameMap.mMapCells.get(newId).mPowerEnabled
&& !elements.contains(newId)) {
elements.add(newId);
updatePowerEnvironment(newId, elements);
}
newId = id + 1;
if (newId < GameMap.mMapCells.size()
&& GameMap.mMapCells.get(newId).mPowerEnabled
&& !elements.contains(newId)) {
elements.add(newId);
updatePowerEnvironment(newId, elements);
}
}
Si je peux faire confiance à la sortie du journal, aucune case n'a été essayée pour être traitée deux fois. Cela signifie que je n'ai pas d'erreurs dans les appels récursifs. Ce qui signifie aussi que la pile est simplement trop petite.
Est-ce que quelqu'un a une idée sur la façon d'éviter la limite de la pile?
[Mise à jour et mon code à la suite de Erics réponse]
public void updatePowerEnvironment(int id, ArrayList<Integer> elements) {
Stack<Integer> toProcess = new Stack<Integer>();
toProcess.push(id);
int mapSize = GameMap.mMapCells.size();
while (!toProcess.empty()) {
id = toProcess.pop();
Log.e("GT", "id to process: " + id);
if (elements.contains(id)) {
continue;
}
int[] neighborIds = computeNeighbors(id);
for (int neighbor : neighborIds) {
if (neighbor < 0 || neighbor >= mapSize) {
continue;
}
if (!GameMap.mMapCells.get(neighbor).mPowerEnabled) {
continue;
}
toProcess.push(neighbor);
}
elements.add(id);
}
}
private int[] computeNeighbors(int id) {
return new int[] {id + GameMap.mMapSize, id - GameMap.mMapSize, id + 1, id - 1};
}
Je ne vois pas de cas de base ici ... – NullUserException
@NullUserException: Le cas de base est "s'il n'y avait pas de tuiles alimentées non traitées dans n'importe quelle direction alors ne rien faire". Vous ne le voyez pas car il n'y a pas de code requis pour implémenter "ne rien faire". –
FWIW, vous pouvez définir explicitement la taille de la pile d'un thread lors de sa création (voir les constructeurs Thread). Comme d'autres l'ont noté, ce n'est pas la bonne solution, mais je pensais que je le mentionnerais pour être complet. – fadden