Probleme bei GameofLife

Java xyrse123

Bekanntes Mitglied
Hallo,
Ich wollte ein GameofLife programmieren. Die zufällig erzeugte Welt flackert einmal kurz auf und das Panel bleibt dann grau, aber der Generationen Zähler zählt weiter hoch. Könnte mir jemand einen Tipp geben woran das liegt?
Schon mal Danke im Vorraus.
Java:
import java.awt.*;
import java.util.Random;
import javax.swing.*;

public class GameofLife extends JPanel {
    static Thread m = new Thread(new MyThread());
    private int[][] Welt = new int[200][200];
    private int GenerationenZähler;
    final static GameofLife Feld = new GameofLife(600, 600);

    public GameofLife(int Breite, int Höhe) {
        setName("Conways Game of Life");
        Welterzeugen();

    }

    private void Welterzeugen() { // Welt wird zufällig gefüllt
        for (int a = 0; a < 200; a++) {
            for (int b = 0; b < 200; b++) {
                if (Math.random() > 0.8)
                    Welt[a][b] = 1; // lebendig
                else
                    Welt[a][b] = 0; // tot

            }
        }
    }

    public void updateWelt() { // regelen werden angewendet
        for (int a = 0; a < 200; a++) {
            for (int b = 0; b < 200; b++) {
                wendeRegelnAn(a, b);
            }
        }
    }

    public Dimension getPreferredSize() {
        return new Dimension(600, 600);
    }

    private void wendeRegelnAn(int a, int b) { // Populationregeln
        int nachbarn = 0;
        if (a >= 1 && b >= 1 && a <= 198 && b <= 198) {
            for (int i = a - 1; i <= a + 1; ++i) {
                for (int j = b - 1; j <= b + 1; ++j) {
                    if (Welt[i][j] == 1) // Nachbar werden gezählt
                        nachbarn += 1;

                    if (Welt[i][j] == 0) {
                        nachbarn -= 1;
                    }
                }
            }
        }

        if (Welt[a][b] == 1) { // zur Zeit t lebendig
            if ((nachbarn < 2) || (nachbarn > 3)) {
                Welt[a][b] = 0; // Zelle tot
            }
        }

        if ((nachbarn == 2) || (nachbarn == 3)) {
            Welt[a][b] = 1;
        }

        if (Welt[a][b] == 0 && nachbarn == 3) {
            Welt[a][b] = 1;
        }
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.drawString("Generation: " + GenerationenZähler++, 0, 10);
        for (int a = 1; a < 199; a++) {
            for (int b = 1; b < 199; b++) {
                if (Welt[a][b] == 1) {
                    g.setColor(Color.red);
                    g.fillRect(a * 3, b * 3, 3, 3);
                }
            }
        }
    }

    static class MyThread extends Thread {
        public void run() {
            while (true) {
                try {
                    Thread.sleep(100);
                    Feld.updateWelt();
                    Feld.repaint();

                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static void main(String[] args) {

        JFrame frame = new JFrame();
        frame.getContentPane().add(Feld);
        frame.pack();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
        m.start();
    }
}
[/code=Java]
 
Hab schon länger nichts mehr mit GameOfLife gemacht. Aber warum veringerst du die Nachbar Anzahl wenn eine Nachbar Zelle == 0? Sollte man nicht einfach nur die Anzahl der lebendigen nachbarn zählen?
 
Danke dir, das war der Fehler. Was ich nur nicht verstehe warum fast alle Zellen am Anfang lebendig sind. Wegen dem
Math.random() >0.8 müssten doch theoretisch rund 20% der Zellen am Anfang lebendig sein.
 
Ich hätte noch was einzubringen. Nochmal: ich bin mit den Regeln nicht mehr ganz so vertraut. Aber, beim Zählen der lebendigen Nachbarn einer Zelle. Sollte man es dann nicht aktiv vermeiden die Zelle (für die man die Nachbarn zählt) selber "mitzuzählen" sollte sie lebendig sein?
Ansonsten hätte doch z.B. eine lebendige Zelle an Koordinate 1/1, die sonst keine lebendigen Nachbarn hat, fehlerhafterweise einen Nachbar-Count von 1.
 
Wie bekomme ich es den hin das erst von allen Zellen die Nachbar gezählt werden und dann erst die Zellen gesetzt werden? Ich habe jetzt folgendes verändert, aber es ist immer noch das selbe Problem:
Java:
private int Nachbarn(int Welt[][], int a, int b) { // Zählt die Nachbarnzellen
  int nachbarn = 0;
  for (int i = a - 1; i <= a + 1; ++i) // ohne den Rand
   for (int j = b - 1; j <= b + 1; ++j)
    if (Welt[i][j] == 1 &&( a!=i || b!=j)) // Damit lebende Zelle nicht mit gezählt wird, ist das so richtig?
     nachbarn += 1;
  return nachbarn;
 }
 
private void wendeRegelnAn(int Welt[][]) { // Populationregeln
  int nachbarn = 0;
  for (int a = 1; a < 199; a++) {
   for (int b = 1; b < 199; b++) {
    nachbarn = Nachbarn(Welt, a, b);
    if (Welt[a][b] == 1) { // zur Zeit t lebendig
     if ((nachbarn < 2) || (nachbarn > 3)) {
      Welt[a][b] = 0; // Zelle tot
     }
    }
    if ((nachbarn == 2) || (nachbarn == 3)) {
     Welt[a][b] = 1;
    }
    if (Welt[a][b] == 0 && nachbarn == 3) {
     Welt[a][b] = 1;
    }
   }
  }
 }
[Code]
 
Einerseits darfst du den Zustand der alten Generation nicht verändern, bevor du mit deren Auswertung fertig bist. Andererseits musst du die dabei gewonnenen Informationen über die neue Generation natürlich auch irgendwo unterbringen. Du musst dir also etwas überlegen, um zwei Generationen speichern zu können.
 
Es funktioniert jetzt, aber wenn ich z.B den Gleiter initialiesiere ist der nach 3 Generationen weg,obwohl er sich eigentlich immer weiter über das Feld bewegen müsste (und dann irgendwann vom Feld verschwindet). Habe ich noch was bei den Spielregeln falsch oder liegt es an der etwas umständlichen Bedingung für die lebende Zelle damit sie nicht als ihre Nachbarzelle gezählt wird?
Java:
for (int i = a - 1; i <= a + 1; ++i) // ohne den Rand
            for (int j = b - 1; j <= b + 1; ++j)
                if (Welt[i][j] == 1 &&( (a<=i &&b<j) ||(a<i&& b<=j))) //die lebende Zelle soll nicht als ihr Nachbar
                    nachbarn += 1;                                                         //gezählt werden
        return nachbarn;
[code]
 
Ich habe die Bedingung jetzt so verändert:
Java:
if (Welt[i][j] == 1  && Welt[i][j]!=Welt[a][b]) {         
     nachbarn += 1;       
    }
Damit müsste doch die Adresse verglichen werden und nicht der Inhalt.
Aber die Nachfolgegenerationen sind immer noch nicht richtig.
 
Post #15 bitte einfach ignorieren, ich konnte ihn nicht mehr bearbeiten😕. Folgendes habe ich verändert damit die lebende Zelle nicht mitgezählt wird:
Java:
for (int i = a - 1; i <= a + 1; ++i) // ohne den Rand
            for (int j = b - 1; j <= b + 1; ++j)
                if (Welt[i][j] == 1 ) {                                                                             
                    nachbarn += 1;                                                                     
                }
                if(Welt[a][b]==1)    {
                    nachbarn--;
                }
Aber die Nachfolgegenerationen sind immer noch nicht richtig.
 
Angenommen, die Zelle an Position a,b ist lebendig. Wie oft wird nachbarn-- in der Schleife denn dann ausgeführt?

In #10 sah deine Abfrage noch so aus:
Java:
if (Welt[i][j] == 1 && (a!=i || b!=j)) 
     nachbarn += 1;
Ist dir bewusst, was das Problem damit war?
 
Ja ich habe es getestet und funktioniert nicht.
Hier nochmal der aktuelle Stand:
Java:
mport java.awt.*;
import java.util.Random;
import javax.swing.*;

public class GameofLife extends JPanel {
    static Thread m = new Thread(new MyThread());
    private static int[][] Welt;
    private static int[][] Welt_neu;
    private int GenerationenZähler;
    static GameofLife Feld = new GameofLife(600, 600);

    public GameofLife(int Breite, int Höhe) {
        setName("Conways Game of Life");
        this.Welt = new int[100][100];
        Welterzeugen();

    }

    private void Welterzeugen() { // Gleiter wird initialisiert

        Welt[20][10] = 1;
        Welt[21][10] = 1;
        Welt[22][10] = 1;

        Welt[21][8] = 1;
        Welt[22][9] = 1;
        
    }

    public int[][] updateWelt() { // regelen werden angewendet
        Welt = wendeRegelnAn(Welt);

        return Welt;
    }

    public Dimension getPreferredSize() {
        return new Dimension(600, 600);
    }

    private int Nachbarn(int Welt[][], int a, int b) { // x,y
        int nachbarn = 0;
        for (int i = a - 1; i <= a + 1; ++i) // ohne den Rand
            for (int j = b - 1; j <= b + 1; ++j)
                if (Welt[i][j] == 1 && (a != i || b != j))
                    nachbarn += 1;
        return nachbarn;
    }

    private int[][] wendeRegelnAn(int Welt[][]) { // Populationregeln

        int Welt_neu[][] = new int[100][100];

        for (int a = 1; a < 99; a++) {
            for (int b = 1; b < 99; b++) {

                int nachbarn = Nachbarn(Welt, a, b);
                System.out.println(nachbarn);
                if (Welt[a][b] == 1) { // zur Zeit t lebendig
                    if ((nachbarn < 2) || (nachbarn > 3)) {
                        Welt_neu[a][b] = 0; // Zelle tot
                    }

                }
                if (Welt[a][b] == 0 && nachbarn == 3) {
                    Welt_neu[a][b] = 1;
                }

            }
        }
        return Welt_neu;

    }   
    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.drawString("Generation: " + GenerationenZähler++, 0, 10);
        for (int a = 1; a < 99; a++) {
            for (int b = 1; b < 99; b++) {
                if (Welt[a][b] == 1) {
                    g.setColor(Color.red);
                    g.fillRect(a * 6, b * 6, 6, 6);
                }
            }
        }
    }

    static class MyThread extends Thread {
        public void run() {

            while (true) { // true
                try {

                    Thread.sleep(150);
                    Feld.updateWelt();

                    Feld.repaint();

                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
        }
    }

    public static void main(String[] args) {

        JFrame frame = new JFrame();
        frame.getContentPane().add(Feld);
        frame.pack();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
        m.start();
    }
}
 
So jetzt funktioniert alles. Hier noch mal die Regeln:
Java:
if (Welt[a][b] == 1) { // zur Zeit t lebendig
                    if ((nachbarn < 2) || (nachbarn > 3)) {
                        Welt_neu[a][b] = 0; // Zelle tot
                    }
                    if (nachbarn == 2 || nachbarn == 3) {
                        Welt_neu[a][b] = 1;
                    }
                }
                if (Welt[a][b] == 0 && nachbarn == 3) { // zur Zeit t  tot
                    Welt_neu[a][b] = 1;
                }
 

Zurück
Oben