Game of Life - Nachbarn zählen

DaPatrick

Mitglied
Hi Leute,

hab folgendes Problem: Habe ein Programm mit dem ich bei einer wahlweise begrenzten oder unbegrenzten Welt ein Spielfeld erzeugen kann und davon die Generationen berechne und auf der Konsole ausgebe. Es funktioniert bisher alles bis auf, dass er mir die Generationen falsch berechnet..

Den Fehler finde ich leider nicht und daher würde ich euch bitten, ob ihr ihn seht und mir weiterhelfen könnt 😉

[Java] ...
/** Startet das Spiel und entwickelt die naechste Generation
*/
public void start() {

/** Zunaechst muss eine Kopie der Welt erstellt werden,
* die aber nur zur Entwicklung der Generation gebraucht
* wird und sonst keine weitere Anwendung hat
* @param zeile: Laufvariable zum Durchlauf aller Zeilen
* @param spalte: Laufvariable zum Durchlauf aller Spalten
*/

this.welt_kopie = new boolean[this.z][this.s];

for (int zeile = 0; zeile < this.z; zeile++) {
for (int spalte = 0; spalte < this.s; spalte++) {
welt_kopie[zeile][spalte] = this.welt[zeile][spalte];
}
}

/** Durchlaufe das Spielfeld nach Zeilen und Spalten
*/
for(int zeile = 0; zeile < this.z; zeile++) {
for(int spalte = 0; spalte < this.s; spalte++) {


/** Berechne die Nachbar der Zellen und nach den Spielregeln schließlich die naechste Generation
* Spielregeln: 1. Eine Zelle bleibt lebendig, wenn sie 2 oder 3 lebendige Nachbarn besitzt
* 2. Eine Zelle wird geboren, wenn sie genau 3 lebendige Nachbarn besitzt
* 3. Eine Zelle stirbt, wenn sie 0, 1 oder mehr als 3 Nachbarn besitzt
*/

if(welt[zeile][spalte] == true) {

/** Regel 1 */
if(getNachbarn(zeile, spalte)==2 || getNachbarn(zeile, spalte)==3) welt_kopie[zeile][spalte] = true;

/** Regel 3 */
else welt_kopie[zeile][spalte] = false;
}
else {
/** Regel 2 */
//if(getNachbarn(zeile, spalte)==3) welt_kopie[zeile][spalte] = true;
}
}
}


this.welt = this.welt_kopie;


}





/** get-Methoden */

public boolean showNachbarn(int z, int s) {

if(begrenzt == true) {

if(z==-1 || s==-1 || s==getSpalten() || z==getZeilen()) {

return false;
}
else return getZelle(z, s);
}
else {
if(s==-1)
{
s=getSpalten()-1;
}
if(z==-1)
{
z=getZeilen()-1;
}
if(s==getSpalten())
{
s=0;
}
if(z==getZeilen())
{
z=0;
}

return getZelle(z, s);
}

}



/** Methode zur Bestimmung der Nachbarn
* @param z: Zeile der Zelle
* @param s: Spalte der Zelle
* @param nachbar: Anzahl der lebendigen Nachbarn einer Zelle
* @return nachbar-1: Ausgabe aller lebendigen Nachbarn abzueglich der Zelle selbst
*/
public int getNachbarn(int z, int s) {

int nachbar = 0;

if((z+this.z)%this.z!=0 && (s+this.s)%this.s!=0) {

for (int zeile = z-1; zeile <= z+1; zeile++) {
for (int spalte = s-1; spalte <= s+1; spalte++) {

if (showNachbarn(zeile, spalte) == true) nachbar++;
}
}
return nachbar-1;
}
else return nachbar;
}
... [/Java]
 
Habe ich 😉

Hab eine CLI, die eine Datei einlesen kann und daraus dann die Welt auf der Konsole erstellt 🙂 Allerdings wie gesagt nicht die richtigen Generationen 🙂

Weiß jemand weiter? Was ich da vllt falsch gemacht habe?

Danke im Voraus 😉
 
Ist halt so schwer nachzuvollziehen, aber bei
if(welt[zeile][spalte] == true) {
sieht's aus als würden nur Zellen lebendig werden können, die sowieso schon leben...
 
Ich hab es auch eimal nachprogrammiert! Wer es sich aus Problem-behandelnden Gründen
noch mal genauer ansehen will, kann es sich hier downloaden!
 
Ich würde erst mal die Methoden anders benennen:

showNachbarn

Besser wäre hasNachbarn.

(Tolles Denglisch, aber ok, technische Sachen Englisch, fachliche Angelegenheiten Deutsch)



getNachbarn

Besser wäre getNachbarCount.

this.welt_kopie

Besser wäre zellArrArr.

Ich nutze zur Benennung von Collections/Arrays nicht einfach ein nachfolgendes 's' für den englischen Plural,
sondern den jeweiligen Collection-Typ, bei einem zweidimensionalen Array eben ...ArrArr,
Beim Auspacken der jeweiligen Collection/Array wird dem aktuellen Element immer der jeweilige Name der
Collection ohne den Postfix gegeben.

Nun ist klar, dass Dein Datenmodell ein zweidimensionales boolean-Array ist.

Dann würde ich Methoden zur Prüfung der Nachbar-Position schreiben.
Java:
boolean hasNachbarTopLeft( int row, int col )
{
    if ( row > 0 && col > 0 )
    {
        return this.zellArrArr[ row ][ col ];
    }
    return false;
}

In der Methode getNachbarCount werden diese dann der Reihe nach aufgerufen.

Da kannst Du jeweils ein if machen:

Java:
int getNachbarCount( int row, int col )
{
    int count = 0;

    if ( hasNachbarTopLeft( row , col ) )
    {
        count++;
    }

    return count;
}

Möglich wäre aber auch dieser Stil:

Java:
    return
    ( hasNachbarTopLeft( row , col ) ? 1 : 0 ) +
    ... und so weiter ...

Also möglichst kleine Methoden,
die nur etwas bestimmtes machen,
die Profis nennen das
separation of concerns.

Eventuell Zwischenschritte durch Tests mit JUnit absichern.
Ist mir jetzt aber zu anstrengend, dafür eine Anleitung zu schreiben.
 
du könntest auch so was machen

Java:
for (int row =0; row< matrix.length; row++){
      for (int col =0; col < matrix[ row].length; col++){
           // alle "spezialfälle abfragen( feld am oberen Rand, obere Rand und obere Ecke links rechts row=0
           // und col =0 oder col =matrix[ row].length-1
           if (row ==0 && col ==0){
                sumNachbarn = matrix[row][col+1] +matrix[row +1][col] + matrix[row +1][col+1];
           // alle seitlichen felder => col =0 und col =matrix[ row].length-1
           } else if{
             ....
           // alle "spezialfälle abfragen( feld am oberen Rand, obere Rand und obere Ecke links rechts
           // row = matrix.length-1
           // und col =0 oder col =matrix[ row].length-1
           } else{
               // alle felder um das zentrum drum rum

so für alle 8 spezialfälle
4 ecken und 4 ränder
und als 9 dann den fall dass du nicht am rand bis und alle felder drum rum zählen musst/sollst
du kannst die reihenfolge auch anpassen, aber so hast du am wenigsten arbeit
 

Zurück
Oben