Game of Life Nachbarn zählen

X

Xylene

Mitglied
Hallo Leute,
Ich bin noch ein ziemlicher Anfänger und entschuldige mich jetzt schonmal für dumme fragen etc., ich hab auch echt viele Threads dazu gelesen aber nie hab ich genau das gefunden was ich brauche, nun sitze ich hier schon einige Stunden an einer Aufgabe in der ich zunächst eine Methode schreiben sollte die ein Feld mit Größe und Breite N erzeugt und dann meine Initialen mit + in das Feld schreibt, die Teilaufgabe ist soweit kein Problem aber jetzt soll ich in der nächsten Aufgabe eine Methode (wirklich nur eine) erstellt werden die das Game of Life auf das vorher erzeugte Feld anwendet. (Lebende Zellen enthalten '+', Tote enthalten enthalten '-' und leere Zellen enthalten 'Leerzeichen')
Ich hab das problem das ich wenn es darum geht die lebenden Nachbarn zu ermitteln immer wieder ein
"Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index -2 out of bounds for length 12
at x.gameOfLife(x.java:58)
at x.main(x.java:11)"
erhalte.
Ich weiß auch woran es liegt, nämlich weil beim abfragen der Nachbarn teilweise auf einen Index zugegriffen wird der außerhalb des Feldes liegt.
Vielleicht kann mir ja einer von euch weiterhelfen und mir sagen was ich falsch gemacht habe.

Schonmal vielen Dank im Vorraus für mögliche Antworten!! :)

Folgend mein bisheriger Quellcode:

Java:
public class Aufgabe {

    public static void main(String[] args) {
      
int n = 12

;

ausgabe(erstelleFeld(n)); 
ausgabe2(gameOfLife(erstelleFeld(n),12));
    }
  
  

  
public static char[][] erstelleFeld(int n){
    char [][] erg = new char [n][n];

    for(int i = 0; i<erg.length; i++) {
        for(int j = 0; j<erg[i].length; j++) {
            if (j==1 && i>= n/4 && i<=n/4*3+1 || i==n/4*3+1 && j>= 2 & j<=(n/3))                                // Buchstabe L
                erg[i][j] = '+';
              
                else if (i==n/4 & j>= n/2 & j<=n || i==n/2 & j>= n/2 & j<=n || i==n/4*3+1 & j>= n/2 & j<=n-1 || i>=n/4 & i<=n/2 & j==n/2 || i>=n/2 & i<=n/4*3 & j==n-1 )      //Buchstabe S
                    erg[i][j] = '+';     
          
                else erg[i][j] = ' ';
        }
    }
    return erg;
                                            }

public static void ausgabe(char[][] erg) {
    for (int i = 0; i<erg.length; i++) {
        for (int j = 0; j<erg[i].length; j++)
            System.out.print(erg[i][j]+" ");
        System.out.println();
    }
  
  
  
}



public static char [][]gameOfLife(char[][] erg, int t){

    char[][] zukunft = new char[erg.length][erg.length];

    for (int i = 0; i < erg.length - 1; i++) {
        for (int j= 0; j < erg.length - 1; j++) {
            int lebendigeNachbarn=0;
            for(int k= -1;k<=1;k++) {
                        for(int l= -1;l<=1;l++) {

                          
                             if (erg[k-1][l-1] == '+')
                            lebendigeNachbarn++;
                                else if (erg[k-1][l] == '+')
                                lebendigeNachbarn++;
                                    else if (erg[k-1][l+1] == '+')
                                        lebendigeNachbarn++;
                                            else if (erg[k][l-1] == '+')
                                            lebendigeNachbarn++;
                                                    else if (erg[k][l+1] == '+')
                                                    lebendigeNachbarn++;
                                                        else if (erg[k+1][l-1] == '+')
                                                        lebendigeNachbarn++;
                                                            else if (erg[k+1][l] == '+')
                                                            lebendigeNachbarn++;
                                                                else if (erg[k+1][l+1] == '+')
                                                                lebendigeNachbarn++;}
          
                        if((erg[i][j]=='+')&&(lebendigeNachbarn<2))
                            zukunft[i][j]='-';
                        else if ((erg[i][j]=='-')&&(lebendigeNachbarn==3))
                            zukunft[i][j]='+';
                            else if ((erg[i][j]=='+')&&(lebendigeNachbarn==3||lebendigeNachbarn==2))
                                zukunft[i][j]='+';
                                else if ((erg[i][j]=='+')&&(lebendigeNachbarn>3))
                                    zukunft[i][j]='-';
                                else zukunft[i][j]=erg[i][j];
                              
  
            }}
    }        return zukunft;    }

  

      


public static void ausgabe2(char[][] zukunft) {
    for (int i = 0; i<zukunft.length; i++) {
        for (int j = 0; j<zukunft[i].length; j++)
            {if (zukunft[i][j] == '-')
                System.out.print("- ");
             else System.out.print("+ ");}
                System.out.println();
    }

}}
 
Zuletzt bearbeitet von einem Moderator:
kneitzel

kneitzel

Top Contributor
Also mir ergibt sich nicht wirklich, was Du da baust. Das fängt schon mit der Aufgabenstellung an: Besagt die Aufgabenstellung wirklich, dass es nur eine einzige Methode geben darf? Das ist extrem ungewöhnlich und würde mich sehr wundern.

Ansonsten ergibt Deine Methode auch noch nicht wirklich viel Sinn.

Du hast zwei Schleifen, um über alle Felder zu gehen. Das ist noch ok. Nur nenne diese nicht i und j. Nenne sie so, dass Du verstehst, was sie sind. Also feldX, feldY so du durch die Felder gehen willst.

Dann hast Du zwei Schleifen die jeweils von -1 bis 1 gehen - das wäre ok um z.B. alle Nachbarn abzuprüfen.
Da ist k und l aber wieder extrem schlecht. deltaX/deltaY oder so wäre dann besser ...

Dann scheint es so, als ob Du die Idee, die Nachbarn über Schleifen abzuprüfen, vergessen hast und nun die Nachbarn aufzählen willst. Dabei nimmst Du aber nicht die feld Koordinaten i/j sondern k/l. So kommst Du dann auch auf -2. Ansonsten fängst Du auch nicht immer bei 0 an zu zählen sondern machst da weiter, wo Du ggf. schon aufgehört hast. Und durch das if else if ... prüfst du Nachbarfelder nur, wenn noch nichts gefunden wurde. Aber Du willst ja nicht abbrechen zu zählen sondern alle lebendigen Nachbarn finden ....

Und das Problem mit dem index: das feld mit x-Koordinate feldX -1 prüfst Du nur, wenn feldX > 0 ist. Und das feldX +1 prüfst Du nur, wenn feldX < ArrayGröße - 2 ist.
Das gleiche bei feldY.

So eine Überprüfung wäre dann z.B.
if (feldX > 0 && erg[feldX-1][feldY]=='+') lebendigeNachbarn++;

Also ich sehe hier zwei Tasks:
1. umbenennen der variablen - das macht Verwechslungen schwerer
2. Entscheide Dich, wie Du zählen willst.
3. Setz den Zähler auf 0 ehe Du anfängst zu zählen.
4. Wenn Du es nicht in mehrere Methoden unterteilen darfst, dann schreib Dir saubere Kommentare, damit Du weisst, wo Du was machst. Der Code wird unübersichtlich und nicht lesbar. Da sind dann Kommentare sinnvoll.
 
X

Xylene

Mitglied
Also mir ergibt sich nicht wirklich, was Du da baust. Das fängt schon mit der Aufgabenstellung an: Besagt die Aufgabenstellung wirklich, dass es nur eine einzige Methode geben darf? Das ist extrem ungewöhnlich und würde mich sehr wundern.

Ansonsten ergibt Deine Methode auch noch nicht wirklich viel Sinn.

Du hast zwei Schleifen, um über alle Felder zu gehen. Das ist noch ok. Nur nenne diese nicht i und j. Nenne sie so, dass Du verstehst, was sie sind. Also feldX, feldY so du durch die Felder gehen willst.

Dann hast Du zwei Schleifen die jeweils von -1 bis 1 gehen - das wäre ok um z.B. alle Nachbarn abzuprüfen.
Da ist k und l aber wieder extrem schlecht. deltaX/deltaY oder so wäre dann besser ...

Dann scheint es so, als ob Du die Idee, die Nachbarn über Schleifen abzuprüfen, vergessen hast und nun die Nachbarn aufzählen willst. Dabei nimmst Du aber nicht die feld Koordinaten i/j sondern k/l. So kommst Du dann auch auf -2. Ansonsten fängst Du auch nicht immer bei 0 an zu zählen sondern machst da weiter, wo Du ggf. schon aufgehört hast. Und durch das if else if ... prüfst du Nachbarfelder nur, wenn noch nichts gefunden wurde. Aber Du willst ja nicht abbrechen zu zählen sondern alle lebendigen Nachbarn finden ....

Und das Problem mit dem index: das feld mit x-Koordinate feldX -1 prüfst Du nur, wenn feldX > 0 ist. Und das feldX +1 prüfst Du nur, wenn feldX < ArrayGröße - 2 ist.
Das gleiche bei feldY.

So eine Überprüfung wäre dann z.B.
if (feldX > 0 && erg[feldX-1][feldY]=='+') lebendigeNachbarn++;

Also ich sehe hier zwei Tasks:
1. umbenennen der variablen - das macht Verwechslungen schwerer
2. Entscheide Dich, wie Du zählen willst.
3. Setz den Zähler auf 0 ehe Du anfängst zu zählen.
4. Wenn Du es nicht in mehrere Methoden unterteilen darfst, dann schreib Dir saubere Kommentare, damit Du weisst, wo Du was machst. Der Code wird unübersichtlich und nicht lesbar. Da sind dann Kommentare sinnvoll.
Hallo, erstmal vielen Dank für die so ausführliche Antwort!

Ich hab jetzt wie von dir vorgeschlagen die Variablen i/j in feldX/feldY und k/l in deltaX/deltaY umbenannt und alles mit Kommentaren bearbeitet um es etwas lesbarer zu machen.

Auch die vertauschten koordinaten i/j habe ich durch k/l ersetzt (also jetzt deltaX/deltaY) und das Problem mit der "ArrayIndexOutOfBoundsException: Index -2" soweit behoben.

Das Problem, das durch das if else if nur geprüft wird wenn noch nichts gefunden wurde sollte denke ich durch das bloße entfernen der else's behoben sein oder?

Auch das hab ich soweit ich es verstanden habe geändert, doch leider scheint etwas mit der Nachbarschaft immer noch nicht ganz zu funktionieren, das ausgegebene Feld ist leider immer noch nicht das was es sein soll :/

Es wäre daher echt lieb wenn du vielleicht noch einmal düber schauen und mir deine Meinung dazu sagen könntest.

Vielen Dank schonmal im Vorraus!

MFG Xylene

Folgend mein bisheriger Quellcode:
Java:
public class Aufgabe {

    public static void main(String[] args) {
        
int n = 12

;

ausgabe(erstelleFeld(n));   
ausgabe2(gameOfLife(erstelleFeld(n),12));
    }
    
    

    
public static char[][] erstelleFeld(int n){
    char [][] erg = new char [n][n];

    for(int i = 0; i<erg.length; i++) {
        for(int j = 0; j<erg[i].length; j++) {
            if (j==1 && i>= n/4 && i<=n/4*3+1 || i==n/4*3+1 && j>= 2 & j<=(n/3))                                // Buchstabe L
                erg[i][j] = '+';
                
                else if (i==n/4 & j>= n/2 & j<=n || i==n/2 & j>= n/2 & j<=n || i==n/4*3+1 & j>= n/2 & j<=n-1 || i>=n/4 & i<=n/2 & j==n/2 || i>=n/2 & i<=n/4*3 & j==n-1 )      //Buchstabe S
                    erg[i][j] = '+';       
            
                else erg[i][j] = ' ';
        }
    }
    return erg;
                                            }

public static void ausgabe(char[][] erg) {
    for (int i = 0; i<erg.length; i++) {
        for (int j = 0; j<erg[i].length; j++)
            System.out.print(erg[i][j]+" ");
        System.out.println();
    }
    
    
    
}



public static char [][]gameOfLife(char[][] erg, int t){
    
    char[][] zukunft = new char[erg.length][erg.length];

    for (int FeldX = 0; FeldX < erg.length - 1; FeldX++) {                     //Schleife zum durchlaufen des ganzen Feldes
        for (int FeldY= 0; FeldY < erg.length - 1; FeldY++) {
            int lebendigeNachbarn=0;
            
            
            for(int DeltaX= -1;DeltaX<=1;DeltaX++) {                        //Schleife für die 3x3 Nachbarsuche
                for(int DeltaY= -1;DeltaY<=1;DeltaY++) {

                    if (FeldX>0 & FeldY>0 && erg[FeldX-1][FeldY-1] == '+')        // Regeln für Moore Nachbarschaft
                        lebendigeNachbarn++;
                        if (FeldX>0 && erg[FeldX-1][FeldY] == '+')
                            lebendigeNachbarn++;
                            if (FeldX>0 && erg[FeldX-1][FeldY+1] == '+')
                                lebendigeNachbarn++;
                                if (FeldY>0 && erg[FeldX][FeldY-1] == '+')
                                    lebendigeNachbarn++;
                                    if (FeldY<erg.length-2 &&erg[FeldX][FeldY+1] == '+')
                                        lebendigeNachbarn++;
                                        if (FeldX<erg.length-2 & FeldY>0 &&erg[FeldX+1][FeldY-1] == '+')
                                            lebendigeNachbarn++;
                                            if (FeldX<erg.length-2 && erg[FeldX+1][FeldY] == '+')
                                                lebendigeNachbarn++;
                                                if (FeldY<erg.length-2 & FeldX<erg.length-2  && erg[FeldX+1][FeldY+1] == '+')
                                                    lebendigeNachbarn++;}}
            
            
                if((erg[FeldX][FeldY]=='+')&&(lebendigeNachbarn<2))        // Regeln für Generation
                    zukunft[FeldX][FeldY]='-';
                        else if ((erg[FeldX][FeldY]=='-')&&(lebendigeNachbarn==3))
                                zukunft[FeldX][FeldY]='+';
                                else if ((erg[FeldX][FeldY]=='+')&&(lebendigeNachbarn==3||lebendigeNachbarn==2))
                                        zukunft[FeldX][FeldY]='+';
                                    else if ((erg[FeldX][FeldY]=='+')&&(lebendigeNachbarn>3))
                                            zukunft[FeldX][FeldY]='-';
                                            else zukunft[FeldX][FeldY]=erg[FeldX][FeldY];}}       
    return zukunft;    }

    

        


public static void ausgabe2(char[][] zukunft) {
    for (int i = 0; i<zukunft.length; i++) {
        for (int j = 0; j<zukunft[i].length; j++) {
            System.out.print(zukunft[i][j]+ " ");
            
        }System.out.println();
    }

}}
 
X

Xylene

Mitglied
Hallo, erstmal vielen Dank für die so ausführliche Antwort!

Ich hab jetzt wie von dir vorgeschlagen die Variablen i/j in feldX/feldY und k/l in deltaX/deltaY umbenannt und alles mit Kommentaren bearbeitet um es etwas lesbarer zu machen.

Auch die vertauschten koordinaten i/j habe ich durch k/l ersetzt (also jetzt deltaX/deltaY) und das Problem mit der "ArrayIndexOutOfBoundsException: Index -2" soweit behoben.

Das Problem, das durch das if else if nur geprüft wird wenn noch nichts gefunden wurde sollte denke ich durch das bloße entfernen der else's behoben sein oder?

Auch das hab ich soweit ich es verstanden habe geändert, doch leider scheint etwas mit der Nachbarschaft immer noch nicht ganz zu funktionieren, das ausgegebene Feld ist leider immer noch nicht das was es sein soll :/

Es wäre daher echt lieb wenn du vielleicht noch einmal düber schauen und mir deine Meinung dazu sagen könntest.

Vielen Dank schonmal im Vorraus!

MFG Xylene

Folgend mein bisheriger Quellcode:
Java:
public class Aufgabe {

    public static void main(String[] args) {
       
int n = 12

;

ausgabe(erstelleFeld(n));  
ausgabe2(gameOfLife(erstelleFeld(n),12));
    }
   
   

   
public static char[][] erstelleFeld(int n){
    char [][] erg = new char [n][n];

    for(int i = 0; i<erg.length; i++) {
        for(int j = 0; j<erg[i].length; j++) {
            if (j==1 && i>= n/4 && i<=n/4*3+1 || i==n/4*3+1 && j>= 2 & j<=(n/3))                                // Buchstabe L
                erg[i][j] = '+';
               
                else if (i==n/4 & j>= n/2 & j<=n || i==n/2 & j>= n/2 & j<=n || i==n/4*3+1 & j>= n/2 & j<=n-1 || i>=n/4 & i<=n/2 & j==n/2 || i>=n/2 & i<=n/4*3 & j==n-1 )      //Buchstabe S
                    erg[i][j] = '+';      
           
                else erg[i][j] = ' ';
        }
    }
    return erg;
                                            }

public static void ausgabe(char[][] erg) {
    for (int i = 0; i<erg.length; i++) {
        for (int j = 0; j<erg[i].length; j++)
            System.out.print(erg[i][j]+" ");
        System.out.println();
    }
   
   
   
}



public static char [][]gameOfLife(char[][] erg, int t){
   
    char[][] zukunft = new char[erg.length][erg.length];

    for (int FeldX = 0; FeldX < erg.length - 1; FeldX++) {                     //Schleife zum durchlaufen des ganzen Feldes
        for (int FeldY= 0; FeldY < erg.length - 1; FeldY++) {
            int lebendigeNachbarn=0;
           
           
            for(int DeltaX= -1;DeltaX<=1;DeltaX++) {                        //Schleife für die 3x3 Nachbarsuche
                for(int DeltaY= -1;DeltaY<=1;DeltaY++) {

                    if (FeldX>0 & FeldY>0 && erg[FeldX-1][FeldY-1] == '+')        // Regeln für Moore Nachbarschaft
                        lebendigeNachbarn++;
                        if (FeldX>0 && erg[FeldX-1][FeldY] == '+')
                            lebendigeNachbarn++;
                            if (FeldX>0 && erg[FeldX-1][FeldY+1] == '+')
                                lebendigeNachbarn++;
                                if (FeldY>0 && erg[FeldX][FeldY-1] == '+')
                                    lebendigeNachbarn++;
                                    if (FeldY<erg.length-2 &&erg[FeldX][FeldY+1] == '+')
                                        lebendigeNachbarn++;
                                        if (FeldX<erg.length-2 & FeldY>0 &&erg[FeldX+1][FeldY-1] == '+')
                                            lebendigeNachbarn++;
                                            if (FeldX<erg.length-2 && erg[FeldX+1][FeldY] == '+')
                                                lebendigeNachbarn++;
                                                if (FeldY<erg.length-2 & FeldX<erg.length-2  && erg[FeldX+1][FeldY+1] == '+')
                                                    lebendigeNachbarn++;}}
           
           
                if((erg[FeldX][FeldY]=='+')&&(lebendigeNachbarn<2))        // Regeln für Generation
                    zukunft[FeldX][FeldY]='-';
                        else if ((erg[FeldX][FeldY]=='-')&&(lebendigeNachbarn==3))
                                zukunft[FeldX][FeldY]='+';
                                else if ((erg[FeldX][FeldY]=='+')&&(lebendigeNachbarn==3||lebendigeNachbarn==2))
                                        zukunft[FeldX][FeldY]='+';
                                    else if ((erg[FeldX][FeldY]=='+')&&(lebendigeNachbarn>3))
                                            zukunft[FeldX][FeldY]='-';
                                            else zukunft[FeldX][FeldY]=erg[FeldX][FeldY];}}      
    return zukunft;    }

   

       


public static void ausgabe2(char[][] zukunft) {
    for (int i = 0; i<zukunft.length; i++) {
        for (int j = 0; j<zukunft[i].length; j++) {
            System.out.print(zukunft[i][j]+ " ");
           
        }System.out.println();
    }

}}
Um nochmal etwas genauer auf die Aufgabenstellung einzugehen:

Das ist die 1. Aufgabe auf der unser "Game of Life" basieren soll:
Erstellen Sie eine Methode erstelleFeld, die zu der als Parameter gegebenen Zahl n>10 ein Feld von Zeichen (char) mit n Zeilen und n Spalten erstellt und anschließend Ihre Initialen als Muster der Zeichen ‘+‘ und ‘ ‘ (Leerzeichen) in das Feld einträgt. Die Größe der Buchstaben muss dabei wenigstens die Höhe n/2 und Breite n/4 besitzen. Das in dieser Weise gefüllte Feld soll dann zurückgegeben werden.

Für die Initialen des Namens Max Mustermann könnte die Methode für n = 12 z.B. das folgende Feld zurückgeben: (siehe Bild)


Und das die eigentliche Aufgabe:
Implementieren Sie eine Methode gameOfLife(char[][] feld, int t), die Conways Spiel des Lebens t Schritte (Generationen) auf dem Feld feld simuliert und das Ergebnis wieder als Feld zurückgibt. Interpretieren Sie Felder mit dem Zeichen ‘+‘ als lebende Zellen, ‘-‘ als tote Zellen und ‘ ‘ als leere Felder. Setzen Sie die Felder außerhalb von feld als konstant leere Felder voraus. Diese Felder müssen Sie nicht auf (lebende oder tote) Zellen setzen, so dass sich das gesamte Spiel innerhalb von feld abspielt. Das zurückgegebene Feld soll die gleiche Zeilen- und Spaltenanzahl wie feld haben.
 

Anhänge

  • Unbenannt.png
    Unbenannt.png
    3,9 KB · Aufrufe: 64
kneitzel

kneitzel

Top Contributor
Ja genau. Das sieht schon recht gut aus.

Kleine Bemerkung am Rande: Variablen schreibt an in der Regel klein, also feldX, feldY, deltaX und deltaY. Falls ich es falsch gemacht haben sollte, dann tut es mir leid. Ich schreibe oft auf dem Handy und da wird dann die Rechtschreibkorrektur aktiv und Apple meint, dass Substantive groß geschrieben werden sollen und so ... Sollte der Fehler von mir ausgegangen sein, so täte es mir leid.

Ein einziger Punkt ist aber noch nicht zu finden:
Du hast Schleifen für deltaX/deltaY -> Wo verwendest Du diese? Brauchst Du diese überhaupt?

Ich nehme die Antwort mal weg: Diese Schleifen müssen weg!

Diese Schleifen wären nur eine andere Form für das zählen gewesen (Dein Code nur umformatiert):
Java:
if (FeldX>0 & FeldY>0 && erg[FeldX-1][FeldY-1] == '+') lebendigeNachbarn++;
if (FeldX>0 && erg[FeldX-1][FeldY] == '+') lebendigeNachbarn++;
if (FeldX>0 && erg[FeldX-1][FeldY+1] == '+') lebendigeNachbarn++;
if (FeldY>0 && erg[FeldX][FeldY-1] == '+') lebendigeNachbarn++;
if (FeldY<erg.length-2 &&erg[FeldX][FeldY+1] == '+') lebendigeNachbarn++;
if (FeldX<erg.length-2 & FeldY>0 &&erg[FeldX+1][FeldY-1] == '+') lebendigeNachbarn++;
if (FeldX<erg.length-2 && erg[FeldX+1][FeldY] == '+') lebendigeNachbarn++;
if (FeldY<erg.length-2 & FeldX<erg.length-2  && erg[FeldX+1][FeldY+1] == '+') lebendigeNachbarn++;

Ich habe die if Bedingungen mal so geschrieben, dass diese untereinander sind. Und dann kannst Du erkennen, dass er
für alle FeldX-1 alle FeldY nutzt (-1, 0 , +1)
für alle FeldX (fast) alle FeldY nutzt (-1, +1)
für alle FeldX+1 alle FeldY nutzt (-1, 0 , +1)

Das wären also die zwei Schleifen. Außen das -1 bis 0, innen das -1 bis 0 -> So wie Du es hattest.

Da wäre dann innerhalb der Schleifen nur noch eine if Abfrage mit vielen Checks:
- (deltaX != 0 || deltaY != 0) -> Abfangen, dass er das Feld selbst mit prüft.
- (feldX + deltaX) > 0 -> untere Grenze. Addition, da das Delta ja negativ sein kann.
- (feldX + deltaX) < erg.length-2 -> obere Grenze.
- (feldY + deltaY) > 0 -> untere Grenze. Addition, da das Delta ja negativ sein kann.
- (feldY + deltaY) < erg.length-2 -> obere Grenze.
- erg[feldX+deltaX][feldY+deltaY]=='+' -> Prüfung: Ist Nachbar lebendig?

Das ist aber ein entweder / oder: Entweder du hast diese 8 Prüfungen von Hand gemacht oder du hast die Prüfungen mit der Schleife und dem modifizierten if gemacht.

Generell wäre mein Ansatz in etwa sowas:
Java:
lebendigeNachbarn=0;
for(int deltaX=-1; deltaX <= 1; deltaX++) {
    for(int deltaY=-1; deltaY <= 1; deltaY++) {
        if (deltaX == 0 && deltaY == 0) continue;
        
        if (istFeldLebendig(erg, fieldX+deltaX, fieldY+deltaY))
            lebendigeNachbarn++;
    }
}
Und die Prüfung, ob das Feld innerhalb der Grenzen ist, ist dann in der Methode istFeldLebendig. Das macht es dann etwas einfacher und lesbarer - aber das war ja (vermutlich) ausgeschlossen. Im Augenblick weiß ich nicht, was ich bevorzugen würde. Ich denke, die beiden Schleifen würde ich aus Gründen der Lesbarkeit nicht nutzen wollen und ich würde die 8 if bevorzugen.
Und wenn weitere Methoden: Dann würde diese zwei Schleifen auch in einer Methode haben. Das wäre eine anzahlLebendigeNachbarn Methode, die erg, feldX und feldY als Parameter besitzt/bekommt. (erg wäre auch eher spielfeld oder so...)

Wurde der Punkt deutlich? Also mein Vorschlag in kürze: Lösche die zwei Schleifen mit deltaX/deltaY einfach komplett raus.
 
krgewb

krgewb

Top Contributor
Sind die Einrückungen richtig? Ich denke, das muss untereinander stehen.
Java:
    if (FeldX>0 & FeldY>0 && erg[FeldX-1][FeldY-1] == '+')        // Regeln für Moore Nachbarschaft
                        lebendigeNachbarn++;
                        if (FeldX>0 && erg[FeldX-1][FeldY] == '+')
                            lebendigeNachbarn++;
                            if (FeldX>0 && erg[FeldX-1][FeldY+1] == '+')
                                lebendigeNachbarn++;
                                if (FeldY>0 && erg[FeldX][FeldY-1] == '+')
                                    lebendigeNachbarn++;
                                    if (FeldY<erg.length-2 &&erg[FeldX][FeldY+1] == '+')
                                        lebendigeNachbarn++;
                                        if (FeldX<erg.length-2 & FeldY>0 &&erg[FeldX+1][FeldY-1] == '+')
                                            lebendigeNachbarn++;
                                            if (FeldX<erg.length-2 && erg[FeldX+1][FeldY] == '+')
                                                lebendigeNachbarn++;
                                                if (FeldY<erg.length-2 & FeldX<erg.length-2  && erg[FeldX+1][FeldY+1] == '+')
                                                    lebendigeNachbarn++;}}
In Eclipse kannst du mit STRG + Shift + F die Einrückungen automatisch verbessern lassen.
 
kneitzel

kneitzel

Top Contributor
Wieso macht ihr eigentlich erg.length-2 und nicht erg.length-1 ?
Dein Hinweis ist korrekt. Bei meinem Code hat sich da ein Fehler eingeschlichen:
- (feldX + deltaX) => 0 -> untere Grenze. Addition, da das Delta ja negativ sein kann.
- (feldX + deltaX) < erg.length -> obere Grenze.

Hier ist das delta bereits hinzugefügt/abgezogen, daher ist der check auf >= 0 und < erg.length (oder <= erg.length - 1) richtig.

(FeldX>0 && erg[FeldX-1][FeldY] == '+') ist aber korrekt, denn FeldX muss > 0 sein, damit FeldX-1 >= 0 ist.

(FeldY<erg.length-2 &&erg[FeldX][FeldY+1] == '+') ist tatsächlich nicht korrekt. Da hätte entweder <= erg.length - 2 oder < erg.length - 1 stehen müssen.

Da war ich dann am Ende tatsächlich einfach zu nachlässig.
 
X

Xylene

Mitglied
VIelen Dank für die vielen Antworten!I
So langsam nähern wir uns der Lösung, ich hab soweit ich es von euch verstanden habe alles geändert.
Also die eine Schleife gelöscht und die If's entsprechend angepasst.
Ich hab das letzte else für die Regeln noch so geändert das er anstelle leerer zellen einfach tote zellen schreibt (also '-')
Dennoch scheint die nachbarzählung immer noch nicht korrekt zu funktionieren, er verändert das Ausgangs Muster auf jedenfall aber nicht so wie es sein soll
Ich habe ein Test Programm in dem ich mein Ausgangs-Feld eingebe und darauf die Game of Life Regeln anwende um zu sehen wie das Ergebnis aussehen soll (vielleicht übertrage ich auch das Feld die ganze zeit Falsch), ich füge mal ein paar screenshots zum veranschaulichen hinzu (auch mein ergebnis in Eclipse)

Anbei noch mein neuer Code:
Java:
public static char [][]gameOfLife(char[][] erg, int t){
  
    char[][] zukunft = new char[erg.length][erg.length];

    for (int FeldX = 1; FeldX < erg.length - 1; FeldX++) {                                                         //Schleife zum durchlaufen des ganzen Feldes
        for (int FeldY= 1; FeldY < erg.length - 1; FeldY++) {
            int lebendigeNachbarn=0;
          
          
          

                    if (FeldX>0 & FeldY>0 && erg[FeldX-1][FeldY-1] == '+') lebendigeNachbarn++;                    // Regeln für Moore Nachbarschaft
                    if (FeldX>0 && erg[FeldX-1][FeldY] == '+') lebendigeNachbarn++;
                    if (FeldX>0 && erg[FeldX-1][FeldY+1] == '+') lebendigeNachbarn++;
                    if (FeldY>0 && erg[FeldX][FeldY-1] == '+') lebendigeNachbarn++;
                    if (FeldY<=erg.length-2 &&erg[FeldX][FeldY+1] == '+') lebendigeNachbarn++;
                    if (FeldX<erg.length-2 & FeldY>0 &&erg[FeldX+1][FeldY-1] == '+') lebendigeNachbarn++;
                    if (FeldX<erg.length-2 && erg[FeldX+1][FeldY] == '+') lebendigeNachbarn++;
                    if (FeldY<erg.length-2 & FeldX<erg.length-2  && erg[FeldX+1][FeldY+1] == '+') lebendigeNachbarn++;
                  
                    if((erg[FeldX][FeldY]=='+')&&(lebendigeNachbarn<2))                                            // Regeln für Generation
                        zukunft[FeldX][FeldY]='-';
                    else if ((erg[FeldX][FeldY]=='-')&&(lebendigeNachbarn==3))
                            zukunft[FeldX][FeldY]='+';
                    else if ((erg[FeldX][FeldY]=='+')&&(lebendigeNachbarn==3||lebendigeNachbarn==2))
                            zukunft[FeldX][FeldY]='+';
                    else if ((erg[FeldX][FeldY]=='+')&&(lebendigeNachbarn>3))
                            zukunft[FeldX][FeldY]='-';
                    else     zukunft[FeldX][FeldY]='-';}}     
    return zukunft;    }
 

Anhänge

  • GOL.png
    GOL.png
    16,6 KB · Aufrufe: 83
  • GOL2.png
    GOL2.png
    17,8 KB · Aufrufe: 71
  • Unbenannt.png
    Unbenannt.png
    2,9 KB · Aufrufe: 47
Zuletzt bearbeitet:
X

Xylene

Mitglied
Dein Hinweis ist korrekt. Bei meinem Code hat sich da ein Fehler eingeschlichen:
- (feldX + deltaX) => 0 -> untere Grenze. Addition, da das Delta ja negativ sein kann.
- (feldX + deltaX) < erg.length -> obere Grenze.

Hier ist das delta bereits hinzugefügt/abgezogen, daher ist der check auf >= 0 und < erg.length (oder <= erg.length - 1) richtig.

(FeldX>0 && erg[FeldX-1][FeldY] == '+') ist aber korrekt, denn FeldX muss > 0 sein, damit FeldX-1 >= 0 ist.

(FeldY<erg.length-2 &&erg[FeldX][FeldY+1] == '+') ist tatsächlich nicht korrekt. Da hätte entweder <= erg.length - 2 oder < erg.length - 1 stehen müssen.

Da war ich dann am Ende tatsächlich einfach zu nachlässig.
(Nachtrag) Gerade fällt mir auf das im Ergebnis die letzte Spalte einfach abgeschnitten wird obwohl da auch wenn dann '-' stehen sollten.
 
kneitzel

kneitzel

Top Contributor
Die Schleifen sind falsch. FeldX und FeldY müssen von 0 bis erg.length-1 laufen. Also:

Java:
   for (int FeldX = 0; FeldX < erg.length; FeldX++) {                                                         //Schleife zum durchlaufen des ganzen Feldes
        for (int FeldY = 0; FeldY < erg.length; FeldY++) {
==> Dadurch hast Du die Ränder nicht mit geprüft / verändert!

Bei allen Zugriffen auf erg musst Du prüfen:
Wenn ein Feld -1 berechnet wird, dann muss das Feld > 0 sein.
Wenn ein Feld +1 berechnet wird, dann muss das Feld < erg.length-1 sein.

Also richtig:
if (FeldX>0 & FeldY>0 && erg[FeldX-1][FeldY-1] == '+')
==> Beide Felder haben -1, daher müssen beide > 0 sein.

Falsch;
if (FeldX>0 && erg[FeldX-1][FeldY+1] == '+')
FeldX prüfst Du zwar richtig, aber FeldY prüfst Du nicht. Das müsste also sein:
if (FeldX>0 && FeldY < erg.length-1 && erg[FeldX-1][FeldY+1] == '+')
Oder um es evtl. einfacher zu verstehen:
if (FeldX>0 && FeldY+1 < erg.length && erg[FeldX-1][FeldY+1] == '+')
==> Array-Index muss kleiner der Länge sein und wir sprechen ja FeldY+1 an....

So musst Du bei jedem Feld den Check machen....

Das dürfte das Problem hoffentlich erst einmal beheben.

Ein weiterer Punkt, den Du nicht ändern musst, aber den ich anmerken möchte (Und den du am Besten ignorierst, bis Dein Programm richtig läuft): Dein Feld ist ein Quadrat. Wenn dem nicht so wäre, dann müsstest Du bei FeldY prüfen:
if (FeldX>0 && FeldY+1 < erg[FeldX-1].length && erg[FeldX-1][FeldY+1] == '+')
und die Schleifen wären:

Java:
   for (int FeldX = 0; FeldX < erg.length; FeldX++) {                                                         //Schleife zum durchlaufen des ganzen Feldes
        for (int FeldY = 0; FeldY < erg[FeldX].length; FeldY++) {
erg ist ein Array von Arrays. erg könnte ja 50 Arrays der Länge 100 enthalten. Dann willst Du mit FeldX durch die 50 Arrays durchgehen und da willst du ja alle 100 Felder ansprechen ...
 
X

Xylene

Mitglied
Die Schleifen sind falsch. FeldX und FeldY müssen von 0 bis erg.length-1 laufen. Also:

Java:
   for (int FeldX = 0; FeldX < erg.length; FeldX++) {                                                         //Schleife zum durchlaufen des ganzen Feldes
        for (int FeldY = 0; FeldY < erg.length; FeldY++) {
==> Dadurch hast Du die Ränder nicht mit geprüft / verändert!

Bei allen Zugriffen auf erg musst Du prüfen:
Wenn ein Feld -1 berechnet wird, dann muss das Feld > 0 sein.
Wenn ein Feld +1 berechnet wird, dann muss das Feld < erg.length-1 sein.

Also richtig:
if (FeldX>0 & FeldY>0 && erg[FeldX-1][FeldY-1] == '+')
==> Beide Felder haben -1, daher müssen beide > 0 sein.

Falsch;
if (FeldX>0 && erg[FeldX-1][FeldY+1] == '+')
FeldX prüfst Du zwar richtig, aber FeldY prüfst Du nicht. Das müsste also sein:
if (FeldX>0 && FeldY < erg.length-1 && erg[FeldX-1][FeldY+1] == '+')
Oder um es evtl. einfacher zu verstehen:
if (FeldX>0 && FeldY+1 < erg.length && erg[FeldX-1][FeldY+1] == '+')
==> Array-Index muss kleiner der Länge sein und wir sprechen ja FeldY+1 an....

So musst Du bei jedem Feld den Check machen....

Das dürfte das Problem hoffentlich erst einmal beheben.

Ein weiterer Punkt, den Du nicht ändern musst, aber den ich anmerken möchte (Und den du am Besten ignorierst, bis Dein Programm richtig läuft): Dein Feld ist ein Quadrat. Wenn dem nicht so wäre, dann müsstest Du bei FeldY prüfen:
if (FeldX>0 && FeldY+1 < erg[FeldX-1].length && erg[FeldX-1][FeldY+1] == '+')
und die Schleifen wären:

Java:
   for (int FeldX = 0; FeldX < erg.length; FeldX++) {                                                         //Schleife zum durchlaufen des ganzen Feldes
        for (int FeldY = 0; FeldY < erg[FeldX].length; FeldY++) {
erg ist ein Array von Arrays. erg könnte ja 50 Arrays der Länge 100 enthalten. Dann willst Du mit FeldX durch die 50 Arrays durchgehen und da willst du ja alle 100 Felder ansprechen ...
Hallo, erstmal frohes neues Jahr!
Vielen dank für deine Hilfe bisher, ich hab die Schleife und die If's dementsprechend angepasst, wir kommen dem gewünschten Ergebnis schon sehr nahe, aber leider noch nicht zu 100% (siehe Bild 1. Spalte)
Es wäre also echt lieb wenn du noch einmal drüber schauen könntest.
Du hast recht bei einem nicht quadratischen Feld müsste man die schleife wahrscheinlich nochmal verändern allerdings ist das ja von der Aufgabenstellung her nicht nötig, trotzdem danke für die Anmerkung!

Folgend meine neue Version des Codes:
Java:
    public static char [][]gameOfLife(char[][] erg, int t){
    
        char[][] zukunft = new char[erg.length][erg.length];

        
        for (int feldX = 0; feldX < erg.length ; feldX++)
        {
            for (int feldY= 0; feldY < erg.length ; feldY++)
            {
                int lebendigeNachbarn=0;
                if (feldX>0 & feldY>0 && erg[feldX-1][feldY-1] == '+') lebendigeNachbarn++;
                if (feldX>0 && erg[feldX-1][feldY] == '+') lebendigeNachbarn++;
                if (feldX>0 &feldY<erg.length-1&& erg[feldX-1][feldY+1] == '+') lebendigeNachbarn++;
                if (feldY>0 && erg[feldX][feldY-1] == '+') lebendigeNachbarn++;
                if (feldY<erg.length-1 &&erg[feldX][feldY+1] == '+') lebendigeNachbarn++;
                if (feldX<erg.length-1 & feldY>0 &&erg[feldX+1][feldY-1] == '+') lebendigeNachbarn++;
                if (feldX<erg.length-1 && erg[feldX+1][feldY] == '+') lebendigeNachbarn++;
                if (feldY<erg.length-1 & feldX<erg.length-1  && erg[feldX+1][feldY+1] == '+') lebendigeNachbarn++;
                                                                            
                            
                        if((erg[feldX][feldY]=='+')&&(lebendigeNachbarn<2))
                                zukunft[feldX][feldY]='-';
                        else if ((erg[feldX][feldY]=='-' |erg[feldX][feldY]==' ')&&(lebendigeNachbarn==3))
                                zukunft[feldX][feldY]='+';
                        else if ((erg[feldX][feldY]=='+')&&(lebendigeNachbarn==3||lebendigeNachbarn==2))
                                    zukunft[feldX][feldY]='+';
                        else  if ((erg[feldX][feldY]=='+')&&(lebendigeNachbarn>3))
                                        zukunft[feldX][feldY]='-';
                                    else zukunft[feldX][feldY]='-';
            }}
                
        return zukunft;}
 

Anhänge

  • asfsafa.png
    asfsafa.png
    1,7 KB · Aufrufe: 97
I

iwer1

Mitglied
Du solltest es wie @kneitzel hoffentlich auch schreibt in mehrere Methoden aufteilen. Dann kommt so etwas ähnliches dabei heraus:
Java:
    private static char aliveCh = 'x';
    private static char deadCh = '-';

    private static int neighbours(char[][] c, int x, int y) {
        int n = 0;
        for (int i = x - 1; i <= x + 1; i++) {
            for (int j = y - 1; j <= y + 1; j++) {
                if (i >= 0 && i < c.length && j >= 0 && j < c[0].length && (x != i || y != j)) {
                    if (c[i][j] == aliveCh) {
                        n++;
                    }
                }
            }
        }
        return n;
    }

    private static boolean alive(char[][] c, int x, int y) {
        int neighbours = neighbours(c, x, y);
        if (c[x][y] == deadCh && neighbours == 3) {
            return true;
        }
        if (c[x][y] == aliveCh && (neighbours == 2 || neighbours == 3)) {
            return true;
        }
        return false;
    }

    public static char[][] getNext(char[][] current) {
        char[][] next = new char[current.length][current[0].length];

        for (int i = 0; i < current.length; i++) {
            for (int j = 0; j < current[0].length; j++) {
                if (alive(current, i, j)) {
                    next[i][j] = aliveCh;
                } else {
                    next[i][j] = deadCh;
                }
            }
        }

        return next;
    }
 
I

iwer1

Mitglied
Naja dann faltet er es eben wieder ein (er muss nur aus den drei Methoden eine Methode machen). Das sollte nun wirklich nicht so schwer sein. So viel Transferleistung darf man (auch hier) von Anfängern erwarten.
 
C

christian30251

Mitglied
Ich bin gerade in Berufsausbildung zum Softwareentwickler und habe das GoL auch programmieren müssen, allerdings schon objektorientiert.
Wenn dich interessiert, wie ich es gelöst habe, kannst du dir gerne mein Github Repository anschauen:


Gruß,
Christian
 
kneitzel

kneitzel

Top Contributor
Wobei man dazu sagen muss: wenn man Studenten nicht dazu zwingt, solche Dinge so zu lösen, ist später ALLES als String[][][] modelliert
Was? Es geht nichts über eine Map<String, String>! Arrays sind was für Anfänger!

Mit der Map kann man fast alles machen - und auch die ganze Entwicklung von Datenbanken wird deutlich vereinfacht, da es halt nur eine Tabelle gibt mit UUID, String, String ... Wobei die Strings VARCHAR(MAX) sind (war ja klar, oder?)

Und dann hat man eine Super Klasse SuperObject - damit kann man alles machen und braucht auch keinerlei Instanzvariablen mehr!
Da reicht dann ein setValue("ID", 1234L) und getValueAsLong("ID") statt einer Instanzvariable "long ID" ...

Hmm ... mir fallen nicht mehr kranke Ideen ein ... Was kann man noch kaputt machen? Typsicherheit, UNterstützung der IDE und so habe ich schon geschrottet ... :)
 
H

httpdigest

Top Contributor
Wenn uns LISP und die ganzen Sprachen, die es beeinflusst hat, eines lehrt, dann doch, dass man nur Listen braucht, keine Maps. Maps sind nur Listen von Key-Value-Paaren (und Paare sind zweielementige Listen). :)
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
D Game of Life - Nachbarn zählen Java Basics - Anfänger-Themen 8
P Moore Nachbarschaft-Game of Life Java Basics - Anfänger-Themen 1
L Conways Game of Life Java Basics - Anfänger-Themen 4
J Game of life Java Basics - Anfänger-Themen 3
E Belebeste Area im Game of Life suchen Java Basics - Anfänger-Themen 0
B Wer kennt einen Link für vollständiges, leichtverständliches "Game of Life"? Java Basics - Anfänger-Themen 1
C Game of life Java Basics - Anfänger-Themen 14
P Game of Life Java Basics - Anfänger-Themen 18
C Conways Game of Life / "Waldbrandsimulation": wieso temporäres Hilfs-Array?! Java Basics - Anfänger-Themen 8
K Game of Life Implementierung Java Basics - Anfänger-Themen 30
Developer_X Game of Life Java Basics - Anfänger-Themen 10
L Game of life in einem FensterVisualisieren Java Basics - Anfänger-Themen 2
D Game of Life Java Basics - Anfänger-Themen 14
P 2D Game Java Basics - Anfänger-Themen 6
B Verwirrender Game Loop Java Basics - Anfänger-Themen 6
B "Snake"-Game verbuggt Java Basics - Anfänger-Themen 0
K Game of live Java Basics - Anfänger-Themen 4
F Java Collectors Game Hilfe Java Basics - Anfänger-Themen 4
C Wie kann ich jetzt von der Game.java auf die Timer.java zugreifen? Java Basics - Anfänger-Themen 6
F Game-Engine für textbasierendes Spiel: Architektur? Java Basics - Anfänger-Themen 9
D Textfield im Game ,Problem: while-Schleife Java Basics - Anfänger-Themen 1
K Gutes Java 3D Game Tutorial gesucht Java Basics - Anfänger-Themen 6
Java-Insel Game-Konzept Java Basics - Anfänger-Themen 10
G Game Loop Problem Java Basics - Anfänger-Themen 9
T Kleines Game mit Kollision Java Basics - Anfänger-Themen 2
V Start ins Java Game Development Java Basics - Anfänger-Themen 22
I Programm Game & AR Java Basics - Anfänger-Themen 13
T Anagram Game - warum ist es auf 2 Packages aufgeteilt? Java Basics - Anfänger-Themen 3
S 3d-game java3d/eigene API Java Basics - Anfänger-Themen 4
C Pong Game Java Basics - Anfänger-Themen 2
B Erste Schritte Way of life ohne import - Habe Beispiel, macht Unfug Java Basics - Anfänger-Themen 21
E Summe der "Nachbarn" eines Wertes in einem Array bestimmen Java Basics - Anfänger-Themen 8
D Spiel des Lebens Nachbarn zählen Java Basics - Anfänger-Themen 6

Ähnliche Java Themen

Anzeige

Neue Themen


Oben