Java Arrays verschiedenen Typs verbinden (Conways Game of Life)

Slight

Cadet 2nd Year
Registriert
Juni 2015
Beiträge
19
Hallo,

ich muss für die Uni Conways Game of Life programmieren und habe ein paar Probleme damit.
Ich möchte zwei Arrays von verschiedenen Typen miteinander verbinden. Ich habe vier Klassen, Frame, Cell, Simulation und Main. Ich habe meine Codes mal hier hochgeladen:

www.dropbox.com/sh/vgwoc69sg42zbmv/AADoAjKXLFm0D5N-oYbEiiZoa?dl=0

Ich habe in der Klasse Frame einen Fehler, da wo ich eigentlich die zwei Arrays verbinden möchte. An dieser Stelle:
public void setJPanelArray()
{
Simulation sim = new Simulation();
this.jPanelArray = sim.getCells(); <- Das funktioniert leider nicht :(
}

Mein Prof meinte nämlich, ich brauche ein JPanel Array, ein Zellen Array und ein Array für die nächste Generation der Zelle. Bis jetzt habe ich aber nur ein Zellen Array vom Typ Cell: Cell[][] cells = new Cell[breite][höhe]; und ein JPanel Array vom Typ JPanel. Durch die Methode makeFrameWithLayout() erstelle ich aber bis jetzt leider nur ein Fenster mit JPanels die in ein JPanel Array abgelegt werden und die JPanels haben durchgehende die selbe Farbe (weiß=tot).

cgol.PNG

Ich soll und würde aber gerne die JPanel Arrays mit den Cell Arrays verbinden, damit die JPanels in dem Fenster auch verschiedene Farben bekommen. Dafür muss ich bestimmt irgendwie die Schleife in makeFrameWithLayout() und die Methode setJPanelArray() verändern aber ich weiß nicht wie.

Ich hoffe ihr könnt mir helfen, und falls sonst noch Fehler in meinem Code sind, würde ich mich freuen, wenn ihr mich aufklärt. Und wenn ihr weitere Infos braucht die ich vergessen habe, kann ich die auch noch posten.

Danke schon mal im Voraus! :)
 
Naja, einfache Antwort - geht nicht.

Das Problem ist eher die Modellierung. Warum soll es denn parallel zu den Cell-Objekten noch eine Sammlung JPanels geben, die nichts weiter als deren visuelle Repräsentation sind? Das muss doch eins sein, entweder durch Vererbung (Cell extends JPanel), was ich nicht so schön finde, dir aber vermutlich leichter fallen wird. Oder aber durch Komposition, wodurch du dann per getter auf das JPanel einer jeden Zelle zugreifen kannst.

Bei beiden Wegen hast du jedenfalls das von dir geschilderte Problem nicht, denn es gibt dann nur noch Cell-Arrays.

Fürs nächste Mal, würde ich empfehlen direkt von den schwergewichtigen und unflexiblen GUI-Komponenten weg zu gehen und mit paintComponent usw. zu arbeiten. Rechtecke zu zeichnen ist nun wirklich einfach.
 
Zuletzt bearbeitet: (typo)
Code:
this.jPanelArray = sim.getCells();
Geht natürlich nicht, da jPanelArray Objekte der Klasse JPanel erwartet, über getCells() aber Objekte der Klasse Cell zurück gibst.
Außerdem möchtest du ja auch nicht die JPanel-Objekte überschreiben, sondern nur ihre Hintergrundfarbe ändern.
Das geht über so eine Methode:
Code:
public void updatePanels() {
    Cell[][] cells = sim.getCells();
    for(int i = 0; i < breite; i++) {
        for(int j = 0; j < höhe; j++) {
            this.jPanelArray[i][j].setBackground(cells[i][j].getColor());
        }
    }
}
Dafür muss ein Objekt der Simulation-Klasse im Frame verfügbar sein und außerdem vorher noch mit setCells() initialisiert worden sein.
Des Weiteren hast du in der Cell-Klasse Color als static deklariert. Das static muss da weg, weil die Farbe ja von Zelle zu Zelle unterschiedlich sein soll und nicht immer gleich.

Edit:
Ein weiterer Fehler:
Code:
   public void makeFrameWithLayout() 
    {
        jFrame = new JFrame("Conways Game of Life");
        jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jFrame.setLayout(new GridLayout(breite, höhe));
        jFrame.setVisible(true);
                 
        for (int spalte = 0; spalte < breite; spalte++) 
        {
            for (int zeile = 0; zeile < höhe; zeile++) 
            {
                jPanelArray = new JPanel[breite][höhe]; // <------ Muss außerhalb der Schleifen stehen
                 
                jPanel = new JPanel();
                jPanelArray[spalte][zeile] = jPanel;
                jPanel.setBorder(new LineBorder(Color.BLACK));
                jPanel.setPreferredSize(new Dimension(Cell.size, Cell.size));
                jPanel.setBackground(Cell.color);
                jFrame.add(jPanel);
            }
        }
        jFrame.pack();
    }

Edit2:
Es gibt noch zwei weitere Fehler in deiner UpdateGen() Methode.
Folgende Zeilen müssen entfernt werden:
Code:
    int breite = 800 / Cell.size;
    int höhe = 680 / Cell.size;
    Cell[][] cells = new Cell[breite][höhe];
und am Ende die Schleife macht überhaupt nichts:
Code:
for(int spalte = 0;spalte < breite;spalte++)
{
    for(int zeile = 0;zeile < höhe;zeile++)
    {
         cells[spalte][zeile].getNextGen(); // <--- Hier passiert nichts
     }
}
 
Zuletzt bearbeitet:
Vielen Dank für die Antworten :)
Ich habe den Code jetzt bearbeitet, jedoch ist die Ausgabe die selbe. Ich habe das jetzt so verstanden, dass die Methode setJPanelArray() die Farbe des JPanels bestimmen soll. Diese Methode muss ja dann auch aufgerufen werden, damit die JPanels die Farbe aus der Klasse Cell durch die Klasse getColor() bekommen, das mache ich dann in der Main Klasse bevor makeFrameWithLayout() aufgerufen wird.
Eigentlich muss ja auch noch die Methode getJPanelArray() irgendwo aufgerufen werden, aber ich bin mir nicht sicher wo? In der Methode makeFrameWithLayout()?

Außerdem wird mir in der Zeile: this.jPanelArray[spalte][zeile].setBackground(cells[spalte][zeile].getColor()); in der Klasse Frame folgender Fehler angezeigt:

Exception in thread "main" java.lang.NullPointerException
at Frame.setJPanelArray(Frame.java:48)
at Main.main(Main.java:7)

Das heißt doch, dass bei setBackground(cells[spalte] kein Wert zurück kommt oder? Wie kann ich das beheben? Ich habe doch durch

Simulation sim = new Simulation();
sim.setCells();

in setJPanelArray in der Klasse Frame die Cells[][] cells mit Werten gefüllt, oder nicht?

Oder sollte ich die JPanelArrays besser ganz weg lassen?

www.dropbox.com/sh/vgwoc69sg42zbmv/AADoAjKXLFm0D5N-oYbEiiZoa?dl=0
 
Zuletzt bearbeitet:
Die JPanelArrays sind schon in Ordnung.
Code:
    public static void main(String[] args) 
    {
        Frame f = new Frame();
        f.setJPanelArray();
        f.makeFrameWithLayout();
    }
Du musst setJPanelArray() nach makeFrameWithLayout() aufrufen,
da du in makeFrameWithLayout() die Panels anlegst, auf die du in setJPanelArray() zugreifst.

Edit:
Die Methode getJPanelArray() brauchst du nicht.
 
Zuletzt bearbeitet:
@Tumbleweed dein Ratschlag mit der paintComponent Methode hat mich echt weitergebracht.
Ich hab den Code etwas umgeschrieben, und habe das JPanelArray entfernt und auch die Konstruktoren der Klassen benutzt. Ich habe auch versucht, die nextGen festzulegen, damit sich das Bild bewegt.
Hier ist der Link dazu: www.dropbox.com/sh/kzlf89pyye1xq8v/AACFqAYkWCeLa-832oN-nStDa?dl=0

Jetzt habe ich folgende Ausgabe: cgol.PNG

In der Main Klasse wollte ich eigentlich durch eine unendlich-Schleife die Bewegung der Zellen bzw. nächste Generation darstellen, das klappt aber noch nicht.
 
Zuletzt bearbeitet:
Slight schrieb:
In der Main Klasse wollte ich eigentlich durch eine unendlich-Schleife die Bewegung der Zellen bzw. nächste Generation darstellen, das klappt aber noch nicht.
Du hast aus meinem ersten Post den letzten Fehler noch nicht eingearbeitet.
Deine unendliche Schleife ist derzeit nur ein if, sollte wohl ein while sein.
 
Zuletzt bearbeitet:
Ich verstehe nicht wieso da nichts passiert, ich hab doch durch setNextGen() die nächste Generation festgelegt, dann müsste er mir doch eigentlich durch getNextGen die Werte zurück liefern und in cells[][] ablegen oder verstehe ich das falsch?
 
Schau dir noch mal an, was setNextGen() und getNextGen() machen und welchen Wert du in draw() abfragst.

Edit:
Code:
cells[spalte][zeile].getNextGen();
Du wählst über cells[spalte][zeile] die gewünschte Zelle aus und rufst dann auf dieser die Methode getNextGen() auf, welche den Wert von nextGen der Zelle zurück gibt.
Mit diesem zurück gegebenen Wert machst du dann aber nichts.
 
Zuletzt bearbeitet:
Vielen Dank für die hilfreichen Tipps, ich habs jetzt hinbekommen, alles funktioniert :)
 
Zurück
Oben