Java Rekursion - StackOverFlow
Guten Tag,
Ich bin momentan dabei, Minesweeper in Java zu programmieren und komme bisher auch gut damit klar. Doch nun, habe ich das Problem, das bei meiner Rekursion der "Stack überflutet"(StackOverFlowError). Dieser erscheint, wenn ich wie bei Minesweeper üblich, versuche wenn keine Bombe an den Block angrenzt, die Blöcke um diesen Block freizulegen. Dies geschieht natürlich mit jedem Block, der freigelegt wird wieder und wieder. Also verständlich, dass ein StackOverFlowError kommt. Allerdings würde ich gerne weiterkommen und ich habe in Google nichts gefunden. Ein Try-Catch-Block hat auch nichts gebracht, dann bin ich in einer endlosen Rekursion gefangen^^.
Das einzige was ich dem Internet entnehmen konnte ist, dass es eine Möglichkeit gibt, dem Stack mehr Speicher zu geben, allerdings weiß ich nicht genau wie das gehen soll, da ich mich mit malloc und calloc bisher nicht auseinander gesetzt habe.
Mit freundlichen Grüßen
4 Antworten
Ich kenne Dein Problem. Ich habe Minesweeper genau wie Du mal vor 20 Jahren programmiert in Turbo Pascal.
Du musst die Felder, die Du schon einmal abgesucht hast, mit einer Markierung versehen und prüfts vor jedem weiteren Aufruf deiner rekursiven Funktion diese Markierung.
Der Stack muss nur so groß genug sein, daß er für ein ganzes Minenfeld mit einer einzigen Mine reicht.
Ohne Code kann ich dir leider nicht helfen^^
Eine StackOverflowException lässt im Allgemeinen auf eine endlose Rekursion bzw. eine zu große Rekursionstiefe schließen.
Mehr kann ich dir leider nicht helfen^^
Ein Try-Catch-Block hat auch nichts gebracht, dann bin ich in einer endlosen Rekursion gefangen^^.
Hast Du überhaupt den Sinn eines Try-Catch Blokes verstanden? Dieser fängt ein Fehler ab, so dass dein Programm nicht abstürzt. Den fehler behebt er natürlich nicht.
Dafür bietet er dir wertvolle Informationen zum Fehler.
MfG. icekeuter

Jo ok, die Rekursion ist glaube ich einfach zu riesig, und ich sehe auch eine Idee wie ich sie verkleinern kann, doch die ist nicht ganz so leicht umzusetzen. Ich rufe halt eine Methode öfters mit den gleichen Parametern auf, die ich nur einmal aufrufen müsste, da das Ergebnis sowieso gespeichert ist/wird. Das Problem: Es liegt noch auf dem Stack und es dauert noch bis es ausgeführt wird... Ansonsten könnte ich es glaube ich mit einem boolean machen. Ich weiß einfach nicht mehr weiter :D
Den Code könnte ich dir natürlich posten, allerdings habe ich so viel rumprobiert, dass inzwischen so viel unnötiges Zeug drin steht, dass du den Überblick wahrscheinlich nicht behältst.
PS: Ach komm wenn du willst kannst dus probieren xD
import java.util.*;
public class Minesweeper{
boolean[][] spielfeld;
int[][] spiel;
public Minesweeper(){
spielfeld = new boolean[11][11];
Random rdm = new Random();
int x = 10;
spiel = new int[11][11];
for(int i = 0; i < 11; i ++){
spiel[0][i] = -2;
spiel[i][0] = -2;
spiel[10][i] = -2;
spiel[i][10] = -2;
}
for(int i = 0; i < x; i++){
int z = rdm.nextInt(9) + 1;
int u = rdm.nextInt(9) + 1;
if(!spielfeld[z][u]){
spielfeld[z][u] = true;
} else {
x++;
}
}
}
public void spielAnzeigen(){
for(int i = 1; i < 10; i++){
for(int j = 1; j < 10; j++){
switch(spiel[i][j]){
case -1: System.out.print("\u25A1 ");
break;
case 1: System.out.print("\u2780 ");
break;
case 2: System.out.print("\u2781 ");
break;
case 3: System.out.print("\u2782 ");
break;
case 4: System.out.print("\u2783 ");
break;
case 5: System.out.print("\u2784 ");
break;
case 6: System.out.print("\u2785 ");
break;
case 7: System.out.print("\u2786 ");
break;
case 8: System.out.print("\u2787 ");
break;
default: System.out.print("\u25A0 ");
break;
}
}
System.out.println();
}
System.out.println();
}
public void feldAufdecken(int x, int y){
int d = 0;
try{
if(spielfeld[x][y]){
verloren();
} else {
if(!spielfeld[x + 1][y] && !spielfeld[x - 1][y] && !spielfeld[x][y + 1] &&
!spielfeld[x][y - 1] && !spielfeld[x + 1][y + 1] && !spielfeld[x - 1][y - 1] &&
!spielfeld[x + 1][y - 1] && !spielfeld[x - 1][y + 1]){
spiel[x + 1][y + 1] = -1;
aufdecken(x, y);
} else {
if(spielfeld[x + 1][y]){
d++;
}
if(spielfeld[x - 1][y]){
d++;
}
if(spielfeld[x][y + 1]){
d++;
}
if(spielfeld[x][y - 1]){
d++;
}
if(spielfeld[x - 1][y - 1]){
d++;
}
if(spielfeld[x - 1][y + 1]){
d++;
}
if(spielfeld[x + 1][y - 1]){
d++;
}
if(spielfeld[x + 1][y + 1]){
d++;
}
spiel[x][y] = d;
}
}
} catch(StackOverflowError e){
System.err.println("ouch!");
}
}
public void aufdecken(int x, int y){
if(spiel[x + 1][y] == 0){
feldAufdecken(x + 1, y);
}
if(spiel[x - 1][y] == 0){
feldAufdecken(x - 1, y);
}
if(spiel[x][y - 1] == 0){
feldAufdecken(x, y - 1);
}
if(spiel[x][y + 1] == 0){
feldAufdecken(x, y + 1);
}
if(spiel[x - 1][y - 1] == 0){
feldAufdecken(x - 1, y - 1);
}
if(spiel[x - 1][y + 1] == 0){
feldAufdecken(x - 1, y + 1);
}
if(spiel[x + 1][y - 1] == 0){
feldAufdecken(x + 1, y - 1);
}
if(spiel[x + 1][y + 1] == 0){
feldAufdecken(x + 1, y + 1);
}
}
Steht noch mehr drin, kann aber nicht mehr Code einfügen. Die Rekursion ist ja drin also^^
"Stack überflutet"
Stapelüberlauf.
Ein Try-Catch-Block hat auch nichts gebracht,
Stapelüberlauf heißt "Platz weg, geht nichts mehr, fertig" da hilft das Try und Catch wenig, du musst den Fehler finden und beheben.
da ich mich mit malloc und calloc bisher nicht auseinander gesetzt habe.
Java unterstützt keine Speicherverwaltung.
dass es eine Möglichkeit gibt, dem Stack mehr Speicher zu geben
Das wird das Problem auch nicht lösen. Ohne Code können wir halt auch nicht helfen

Hättest du mal runtergescrollt:
Da ist Code
Problem bereits gelöst
Trotzdem danke^^

Hättest du mal runtergescrollt:
Hättest du doch mal den Tipp vom PerfectMuffin gelesen, da wird genaustens erklärt, wie ein Anfänger eine Frage zu stellen hat. Der Code kommt IN die Frage formatiert rein
Ich nehme an das Problem ist eine Fehlerhafte Umsetzung von einer Art Füllalgorithmus?