# Java Spiel des Lebens



## ScorixEar (19. Apr 2016)

Hi Leute,
ich habe gerade einen alten Versuch des Spiel des Lebens von John Horton Conway (Wikipedia!) wiedergefunden und mich gefragt, wieso ich jenen nicht zu Ende programmiert habe.

Das Spiel des Lebens baut ja darauf, dass nach bestimmten Regeln Zellen (bei mir Graphics) Sterben oder geboren werden beziehungsweise Leben.
Die Regeln lauten:
1. Sind um eine tote Zelle genau 3 Zellen lebend, wird sie in der nächsten Generation geboren
2. Sind um eine lebende Zelle weniger als 2 Zellen lebend, stirbt sie in der nächsten Generation
3. Sind um eine lebende Zelle genau 2 oder 3 Zellen lebend, bleibt sie am leben
4. Sind um eine lebende Zelle mehr als 3 Zellen lebend, stirbt sie

Dies habe ich versucht, nur leider ergibt die Umsetzung ein Muster, welches wie ein wandelndes Labyrinth aussieht und nicht die zu erwartenden statischen, oszillierenden und wandernden Muster. Verändere ich die 3. Regel auf ausschließlich 2 Zellen und erniedrige die 4. Regeln auf ab 3 Zellen, dann erscheinen statische und oszillierende Muster, jedoch keine wandernden und generell ist das Chaos, was normalerweise erscheint auch nicht vorhanden. Irgendetwas stimmt bei den Regeln oder beim Ausführen der Regeln nicht.

Hinzu kommt, dass sich das Panel, auf dem die Graphics liegen, bei dem knopfdruck start über das alte Panel zeichnet, während das alte sich zusammen mit dem Start und Stop button nach rechts-unten verschiebt und ich weiß auch nicht, wie jenes zustande kommt.

Mein Code ist eine Klasse:

```
import java.awt.*;
import java.awt.event.*;

import javax.swing.*;
public class GoL{
  boolean[][] leben=new boolean[151][151];          //100 Quadrate + 1 Reihe drum rum die nicht sichbar ist
  JButton Decaption;                      //manuelle Wahrscheinlichkeitsbestimmung -- noch nicht eingefügt
  JButton Start;                        //Startet das Leben und Sterben
  JButton Stop;                       //Stop die Orgie
  JPanel p=new Panel(leben);
  JPanel e;
  MouseListener click;//Das Quadrat aus 100 Quadraten
  boolean d = false;                      //Decaption Regler (noch nicht eingebaut)
  boolean start=false;                      //Start/Stop-Regler geht nicht deswegen auf immer an (true)
  JTextField Wahrscheinlichkeit;                //Für Decaption --- Konnte noch nicht getestet werden (Benutzte Wahrscheinlichkeit.setTest())
  String w;                         //Text des JTextField
  double wahr;                        //umgeändert in ein double-wert
  int k = 0;                          //wahrscheinloch notwendige Variable --- noch nicht eingefügt
  double r=0;
  //int r2=0;                     //RandomZahl für 1.Generation
  JFrame frame = new JFrame();;
  public static void main (String args[]){   
    GoL gui = new GoL();     
    gui.los();                       
  }
  public void los(){
    Decaption = new JButton("Decaption");         //3 Buttons
    Start = new JButton("Start");
    Stop = new JButton("Stop");
    Wahrscheinlichkeit =  new JTextField();         //1 Textfeld
    Wahrscheinlichkeit.setText("0.5");
    w = Wahrscheinlichkeit.getText();
    wahr= Double.parseDouble(w);              //schonmal in double umwandeln
    Decaption.addActionListener(new Decaption());     //alles zufügen
    Start.addActionListener(new Start());
    Stop.addActionListener(new Stop());
    Wahrscheinlichkeit.addActionListener(new Wahr());
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //einrichten
    frame.getContentPane().add(BorderLayout.EAST, Decaption);
    frame.getContentPane().add(BorderLayout.NORTH, Stop);
    frame.getContentPane().add(BorderLayout.WEST, Start);
    frame.getContentPane().add(BorderLayout.SOUTH, Wahrscheinlichkeit);
   
    alife();                        //erste Wahrscheinlichkeit in Quadrate umsetzten
    p=new Panel(leben);
    //Panel erstellen
   
    frame.getContentPane().add(p);
   
   
    frame.setSize(1500, 900);               //Size setzten
    frame.setVisible(true);               //Sichtbar machen
   
    while(true)
    {
      try {
        Thread.sleep(20);
      } catch (InterruptedException e2) {
        e2.printStackTrace();
      }
      if(d==true)
      {
        alife();
        frame.getContentPane().remove(p);
        p=new Panel(leben);
       
        frame.getContentPane().add(p);
        frame.setVisible(true);
        d=false;
      }
     
      for(int i = p.getX()-5;i<p.getX()+10;i++)
      {
        for(int j = p.getY()-5;i<p.getY()+10;j++)
        {
          if (i>0&&i<151&&j>0&&j<151)
          leben[i][j] = true;
          frame.getContentPane().remove(p);
          p=new Panel(leben);
         
          frame.getContentPane().add(p);
        }
      }
      while(start==true)
      {
        try {
          Thread.sleep(100);
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
        rules(); 
        try {
          Thread.sleep(10);
        } catch (InterruptedException e1) {
          e1.printStackTrace();
        }
       
        frame.getContentPane().remove(p);
        p=new Panel(leben);
       
        frame.getContentPane().add(p);
        frame.setVisible(true);
      }
    }
   
   
   
  }
  class Decaption implements ActionListener{          //Selbstgewählte Wahrscheinlichkeit start
    public void actionPerformed(ActionEvent event){
      d=true;
      start=false;
     
    }
  }
  class Start implements ActionListener{            //Generationen Start
    public void actionPerformed(ActionEvent event){
      start=true;
      d=false;
     
    }
  }
  class Stop implements ActionListener{           //Generationen Stop
    public void actionPerformed(ActionEvent event){
      start=false;
      d=false;
    }
  }
  class Wahr implements ActionListener{           //Selbstgewählte Wahrscheinlichkeit umgesetzt --- funktioniert nicht
    public void actionPerformed(ActionEvent event) {
      w = Wahrscheinlichkeit.getText();
      wahr= Double.parseDouble(w);
    }
  }
 
 
  public void rate(){                     //Wahrscheinlichkeitsberechnung
    r= Math.random();
    if(r<Double.parseDouble(Wahrscheinlichkeit.getText())){
      r=1;
    } else {
      r=0;
    }
    //System.out.println(r);
   
  }
  public void alife() {                   //1. Generation
   
    for(int i = 1;i<150;i++) {
      for(int j=1;j<150;j++){
        rate();
        if(r>=1.0){
          //System.out.println(r);
          leben[i][j]=true;
          //System.out.println(leben[i][j]);
        }else if (r<=1.0){
          leben[i][j]=false;
          //System.out.println(leben[i][j]);
        }
       
      }
    }
  }
  public void rules(){                  //Regeln:
   
    for(int i=1;i<150;i++)                //1. Dimension
    {
      for(int j=1;j<150;j++)              //2. Dimension
      {
        int al=0;
        if(leben[i-1][j])
        al++;
        if(leben[i+1][j])
        al++;
        if(leben[i-1][j-1])
        al++;
        if(leben[i+1][j-1])
        al++;
        if(leben[i-1][j+1])
        al++;
        if(leben[i+1][j+1])
        al++;
        if(leben[i][j+1])
        al++;
        if(leben[i][j-1])
        al++;
        if(leben[i][j])
        {
          if(al>3)
          {
            leben[i][j]=false;
          }
          else if (al<2)
          {
            leben[i][j]=false;
          }
          else if(al==2||al==3)
          {
            leben[i][j]=true;
          }
        }else
        {
          if(al==3)
          {
            leben[i][j]=true;
          }
          else
          leben[i][j]=false;
        }
       
      }
    }
   
   
  }
 
}
class Panel extends JPanel{                 //Panel zur Quadraterstellung
  boolean[][]l;                     //Leben[][] in ein l[][]
  public Panel(boolean[][] leben){
    l=leben;
  }
  public Panel(){
   
  }
  public void paintComponent(Graphics g) {        //Zeichen
   
    g.setColor(Color.black);
    for(int i = 1;i<150;i++) {              //Für jede Dimension
      for(int j=1;j<150;j++){
        if(l[i][j] ==true){
          g.setColor(Color.red);         
        } else {
          g.setColor(Color.black);
        }
        g.fillRect(i*6,j*6,6,6);
       
       
      }
    }
   
   
  }
}
```
vielleicht könnte einer von euch sich das mal anschauen, es macht wirklich Spaß, mit so etwas rum zu spielen ^^
lg Paul


----------



## Meniskusschaden (19. Apr 2016)

Ich vermute, du schreibst das Berechnungsergebnis einer Zelle sofort in dein Array, so daß es die Berechnung der nächsten Zellen bereits beeinflusst, obwohl es eigentlich erst zur nächsten Generation gehört.


----------



## Jardcore (20. Apr 2016)

ScorixEar hat gesagt.:


> *if*(leben[i-1][j])
> al++;
> *if*(leben[i+1][j])
> al++;
> ...





ScorixEar hat gesagt.:


> *for*(*int* i = p.getX()-5;i<p.getX()+10;i++)
> {
> *for*(*int* j = p.getY()-5;i<p.getY()+10;j++)
> {
> ...



Versuche doch deinen Code noch ein wenig besser zu strukturieren. Am besten du lagerst komplizierte Rechnungen und Abfragen in zusätzliche Methoden oder Klassen aus und versuche Magic Numbers zu vermeiden. Dann kannst du auch einfacher Testen, Debuggen und dadurch deine Fehler finden.

Hier gibts ein paar grundsätzliche Regeln:
http://clean-code-developer.de/die-tugenden/


----------



## ScorixEar (20. Apr 2016)

@Meniskusschaden Oh je, danke, so simpel xD
@Jardcore Ich kann dir versichern, ich schreibe nicht so, es ist ein sehr alter Code und er entspricht längst nicht mehr meinen Programmierstil. Schon allein nur eine Klasse zu benutzten erscheint mir widerwertig xD
EDIT

```
while(start==true)
      {
        try {
          Thread.sleep(100);
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
        leben2=leben;
        rules();
        leben=leben2; 
        try {
          Thread.sleep(10);
        } catch (InterruptedException e1) {
          e1.printStackTrace();
        }
       
        //p.setVisible(false);
        //p.setEnabled(false);
        frame.getContentPane().remove(p);
        p=new Panel(leben);
        frame.getContentPane().add(p);
        //p.setEnabled(true);
        frame.repaint();
        //p.setVisible(true);
       
      }
    }
public void rules(){                  //Regeln:
   
    for(int i=1;i<150;i++)                //1. Dimension
    {
      for(int j=1;j<150;j++)              //2. Dimension
      {
        int al=0;
        if(leben[i-1][j])
        al++;
        if(leben[i+1][j])
        al++;
        if(leben[i-1][j-1])
        al++;
        if(leben[i+1][j-1])
        al++;
        if(leben[i-1][j+1])
        al++;
        if(leben[i+1][j+1])
        al++;
        if(leben[i][j+1])
        al++;
        if(leben[i][j-1])
        al++;
        if(leben[i][j])
        {
          if(al>=3)
          {
            leben2[i][j]=false;
          }
          else if (al<2)
          {
            leben2[i][j]=false;
          }
          else if(al==2||al==3)
          {
            leben2[i][j]=true;
          }
        }else
        {
          if(al==3)
          {
            leben2[i][j]=true;
          }
          else
          leben2[i][j]=false;
        }
       
      }
    }
   
   
   
  }
```
Ich habe nun leben2 mal kurz ins Leben gerufen, welches die Ergebnisse speichert und erst am Ende das alles zu leben zuweist. Allerdings ergibt sich immernoch dieses ausbreitende Labyrinth


----------



## Flown (20. Apr 2016)

Gutes Training wäre, den Code neu zu schreiben und dann noch mal hier sauber zu posten!


----------



## ScorixEar (20. Apr 2016)

@Flown Da hättest du recht, aber dieser Phlegmatikus


----------



## Flown (20. Apr 2016)

Man muss jetzt sagen, dass man diesen Code in 20 min runterschreiben kann und dann ists für allemal gegessen.


----------



## Meniskusschaden (20. Apr 2016)

ScorixEar hat gesagt.:


> leben2=leben;
> rules();
> leben=leben2;


Ich glaube so funktioniert das nicht, denn du benutzt jetzt nur ein Array mit zwei Referenzen und hast deshalb immer noch dasselbe Problem. Du kannst für leben2 doch eigentlich einfach eine neue Array-Instanz erstellen. Sie muß ja keine Kopie von leben sein, denn es werden ohnehin alle Zellen neu berechnet.


----------



## ScorixEar (20. Apr 2016)

@Meniskusschaden Ich habe zwei Arrays erstellt, die gespiegelt werden. Dann wird allerdings das eine Array zum überprüfen der Regeln genommen und nach dem Ergebnis das gespiegelte Array verändert. Und erst am ende, wenn das 1. array durchgeschaut wurde, werden beide wieder abgeglichen. Das Array, an dem die Regeln angewendet werden, wird ja nicht verändert, während die Regeln angewendet werden sondern nur das andere Array


----------



## Meniskusschaden (20. Apr 2016)

Du hast zwar zunächst zwei Arrays erstellt, aber nach`leben2=leben;`enthält leben2 keine Kopie von leben, sondern es referenziert dasselbe array wie leben. Wenn du also eine Zelle in leben2 veränderst, hast du damit dieselbe Zelle in leben verändert. Die Zeile`leben=leben2;`ist wirkungslos, weil zu diesem Zeitpunkt bereits beide Variablen auf dasselbe Array zeigen.

Wenn du vor jedem Aufruf von rule() ein neues Array leben2 erstellst, müsste es meines Erachtens funktionieren. Dann ist die Zeile`leben=leben2;`auch wieder sinnvoll und nötig.


----------



## ScorixEar (21. Apr 2016)

@Meniskusschaden Ach ja, ich bin dumm. Sehr dumm. Jetzt funktioniert das auch alles.
Jetzt noch das Problem, dass sich das alles nach unten verschiebt. Aber vielleicht löst sich das auch, wenn ich das nochmal neu schreibe.


----------

