Mam grę symulacyjną miasta i próbuję znaleźć sposób na sprawdzenie przepływu naszego systemu zasilania. Podstawy: Mapa miasta oparta jest na kafelkach (30 na 30 kafelków = 900 kafelków). Teraz zaczynam od elektrowni i wykonuję kontrolę rekursywnego sąsiada (góra, lewo, prawo, dół), aby sprawdzić, czy jest coś, co przeniesie moc. Jeśli coś jest, zaczynam sprawdzać te kafelki również dla sąsiadów. Aby uniknąć podwójnych kontroli i/lub nieskończone wywołań rekurencyjnych, ja wypełnić ArrayList z przetworzonych płytek i sprawdzić, czy nowa dachówka zostało już przetworzone i dodane do ArrayList ...rekurencyjne + 900 elementów + sprawdzenie sąsiada = powoduje stackoverflow
Rekursywnie początek:
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);
}
}
Jeśli mogę zaufać wynikowi dziennika, żaden kafelek nie został przetworzony dwukrotnie. Oznacza to, że nie mam błędów w wywołaniach rekursywnych. Co oznacza także, że stos jest po prostu za mały.
Czy ktoś ma pomysł, jak uniknąć ograniczenia stosu?
[Update i mój kod w wyniku ERIC Odpowiedź]
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};
}
Nie widzę tu przypadku podstawowego ... – NullUserException
@NullUserException: Podstawowym przykładem jest "jeśli nie ma nieprzetworzonych płytek zasilanych w dowolnym kierunku, a następnie nie rób nic". Nie widzisz tego, ponieważ nie ma kodu wymagającego implementacji "nie rób nic". –
FWIW, możesz ustawić rozmiar stosu wątku jawnie podczas jego tworzenia (zobacz konstruktory wątków). Jak inni zauważyli, to nie jest właściwe rozwiązanie, ale pomyślałem, że wspomnę o tym dla kompletności. – fadden