Game of Life

Developer_X

Top Contributor
Hi, ich habe irgendwie ein selstsames Problem.
Ich werte Boolen-Array-Array Daten aus, wegen Conways Game of Life, wenn ihrs kennt.

Doch irgendwie kommen ganz seltsame ergebnisse raus, und nichts funktioniert, warum?

Hier mal mein Code:
Java:
package main;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

@SuppressWarnings("serial")
public class GameOfLife extends JInternalFrame
{
//	Attributes
	Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
	boolean[][] originalUniverseArea, actualUniverseArea;
	
//	Constructor
	public GameOfLife()
	{
		setTitle("Conways Game of Life ");
		setSize(d.width/2,d.width/2);
		setClosable(true);
		setResizable(true);
		
		addComponents();
		
		setVisible(true);
		
		askInformation();
	}
	
//	Methods
	public void addComponents()
	{
		setLayout(new BorderLayout());
		
		JPanel mainPanel = new JPanel();
		add(mainPanel);
		mainPanel.setLayout(new BoxLayout(mainPanel,BoxLayout.Y_AXIS));
		
		JPanel panel = new JPanel()
		{
			public void paintComponent(Graphics gr)
			{
				Graphics2D g = (Graphics2D)gr;
				g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
			
				int width  = getSize().width;
				int height = getSize().height;
				
				if(actualUniverseArea!=null)
				{
					for(int y = 0;y<actualUniverseArea.length;y++)
					{
						for(int x = 0;x<actualUniverseArea.length;x++)
						{
							if(actualUniverseArea[x][y])
							{
								g.setPaint(new GradientPaint(0,0,new Color(0,255,0),0,height,new Color(0,100,0)));
							}
							else
							{
								g.setColor(Color.black);
							}
							g.fillRect(width/actualUniverseArea.length*x, height/actualUniverseArea.length*y, width/actualUniverseArea.length, height/actualUniverseArea.length);
						}
					}
					g.setColor(Color.darkGray);
					
					for(int x = 0;x<width;x+=width/actualUniverseArea.length)
						g.drawLine(x,0,x,height);
					for(int y = 0;y<height;y+=height/actualUniverseArea.length)
						g.drawLine(0,y,width,y);
				}
			}
		};
		mainPanel.add(panel,"Center");
		
		JMenuBar bar = new JMenuBar();
		mainPanel.add(bar,"South");
		
		JButton reset = new JButton("Reset");
		bar.add(reset);
		reset.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent arg0) 
			{
				reset();
				repaint();
			}
		});
		
		JButton next = new JButton("Nächster Schritt");
		bar.add(next);
		next.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent arg0) 
			{
				next();
				repaint();
			}
		});
	}
	
	public void askInformation()
	{
		//Custom button text
		Object[] options = {"10x10",
		                    "50x50",
		                    "100x100"};
		int n = JOptionPane.showOptionDialog(this,"Welche Feldgröße möchten Sie gerne haben?","Feldgrößen Abfrage",JOptionPane.YES_NO_CANCEL_OPTION,JOptionPane.QUESTION_MESSAGE,null, options, options[2]);
	
		if(n == 0)
		{
			originalUniverseArea = new boolean[10][10];
			actualUniverseArea   = new boolean[10][10];
		}
		else if(n==1)
		{
			originalUniverseArea = new boolean[50][50];
			actualUniverseArea   = new boolean[50][50];
		}
		else if(n==2)
		{
			originalUniverseArea = new boolean[100][100];
			actualUniverseArea   = new boolean[100][100];
		}
		else
		{
			setVisible(false);
		}
		
		final JDialog dialogFrame = new JDialog();
		dialogFrame.setTitle("Bitte Selektierte Kästchen angeben");
		
		JPanel dialog = new JPanel();
		dialog.setLayout(new BoxLayout(dialog,BoxLayout.Y_AXIS));
		dialogFrame.add(dialog);
		
		JPanel cbPanel = new JPanel();
		cbPanel.setLayout(new GridLayout(originalUniverseArea.length,originalUniverseArea.length));
		
		final JCheckBox[][] boxes = new JCheckBox[originalUniverseArea.length][originalUniverseArea.length];
		for(int x = 0;x<boxes.length;x++)
		{
			for(int y = 0;y<boxes.length;y++)
			{
				boxes[y][x] = new JCheckBox("",false);
				cbPanel.add(boxes[y][x]);
			}
		}
		dialog.add(new JScrollPane(cbPanel));
		
		JButton accept = new JButton("Bestätigen");
		dialog.add(accept);
		
		accept.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent arg0) 
			{
				dialogFrame.setVisible(false);
				
				for(int x = 0;x<originalUniverseArea.length;x++)
				{
					for(int y = 0;y<originalUniverseArea.length;y++)
					{
						originalUniverseArea[x][y] = boxes[x][y].isSelected();
						actualUniverseArea[x][y] = boxes[x][y].isSelected();
					}
				}
				
				repaint();
			}
		});
		
		dialogFrame.setSize(400, 420);
		dialogFrame.setVisible(true);
	}
	public void reset()
	{
		actualUniverseArea = originalUniverseArea;
	}
	
	public void next()
	{
		boolean[][] oldUniverseArea = actualUniverseArea;
		boolean[][] newUniverseArea = actualUniverseArea;
		
		for(int y = 1;y<actualUniverseArea.length-1;y++)
		{
			for(int x = 1;x<actualUniverseArea.length-1;x++)
			{
				int neighbours = 0;
				
				if(x==4&&y==4)
				{
					System.out.println(actualUniverseArea[x-1][y-1]+" "+actualUniverseArea[x][y-1]+" "+actualUniverseArea[x+1][y-1]);
					System.out.println(actualUniverseArea[x-1][y]+" "+actualUniverseArea[x][y]+" "+actualUniverseArea[x+1][y]);
					System.out.println(actualUniverseArea[x-1][y+1]+" "+actualUniverseArea[x][y+1]+" "+actualUniverseArea[x+1][y+1]);

				}
				
				if(neighbours==2)
				{
					if(oldUniverseArea[x][y])
						newUniverseArea[x][y] = true;
				}
				if(neighbours==3)
				{
					newUniverseArea[x][y] = true;
				}
				else
				{
					newUniverseArea[x][y] = false;
				}
			}
		}
		
		actualUniverseArea = newUniverseArea;
	}
}

Wenn ich aber jetzt um die Stelle 4 einstelle, dass alle nachbarn(also alle 8) true sind, und die stelle 4|4 auch true ist, dann wird leider nur folgendes ausgegeben
false false false
false true true
false true true

Warum?
Das widerspricht doch jeglicher Logik, bitte kann mir einer helfen?

Danke,
m.f.G. Developer_X
 
S

SlaterB

Gast
was hindert dich, mit System.out.println alle 'Logik' nachzuprüfen, die deiner Meinung nach vorhanden sein soll?
ich sehe kaum eingebaute Logik, daher kann man auch wenig wirklich als falsch betrachten

Zeile 200 bis 212 hängen von der Variablen neighbours ab, die ist aber immer 0?
wenn neighbours 2 wäre, dann würde Zeile 203 vielleicht ausgeführt, das Ergebnis von Zeile 211 aber immer überschrieben,

mit
> boolean[][] oldUniverseArea = actualUniverseArea;
legst du übrigens keine Kopie an wie du vielleicht denkst, sondern beide Variablen enthalten dasselbe Array,
Änderungen in einem sind automatisch auch im anderen, weil beide dasselbe sind,

---

anfangs hast du noch zwei Arrays
> originalUniverseArea = new boolean[10][10];
> actualUniverseArea = new boolean[10][10];

mit
> public void reset() {
> actualUniverseArea = originalUniverseArea;
> }
wären beide ebenso dieselben

---------


fange mit möglichst kleinen Feldern an, z.B. 3x3 oder 4x4, vielleicht hat sogar 2x2 schon sinnvolles Verhalten?
und dann führe dein angefangenes Logging konsequent bis in alle Details durch, du brauchst eine Programmausgabe der Form:

Situation vor der Runde:
x o o x
o o o x
o x o o
o o o o
ändere Feld 0/0 aufgrund Regel .. und Nachbarn .. von x auf o
ändere Feld 1/0 aufgrund Regel .. und Nachbarn .. von o auf x
usw.
Situation nach der Runde:
x o o x
o o o x
o x o o
o o o o
evtl. ist es leichter, statt Koordinaten x/y die Felder 0-15 durchzunummerieren
 
Zuletzt bearbeitet von einem Moderator:

Developer_X

Top Contributor
was hindert dich, mit System.out.println alle 'Logik' nachzuprüfen, die deiner Meinung nach vorhanden sein soll?
ich sehe kaum eingebaute Logik, daher kann man auch wenig wirklich als falsch betrachten

Zeile 200 bis 212 hängen von der Variablen neighbours ab, die ist aber immer 0?
wenn neighbours 2 wäre, dann würde Zeile 203 vielleicht ausgeführt, das Ergebnis von Zeile 211 aber immer überschrieben,

mit
> boolean[][] oldUniverseArea = actualUniverseArea;
legst du übrigens keine Kopie an wie du vielleicht denkst, sondern beide Variablen enthalten dasselbe Array,
Änderungen in einem sind automatisch auch im anderen, weil beide dasselbe sind,

---

anfangs hast du noch zwei Arrays
> originalUniverseArea = new boolean[10][10];
> actualUniverseArea = new boolean[10][10];

mit
> public void reset() {
> actualUniverseArea = originalUniverseArea;
> }
wären beide ebenso dieselben

---------


fange mit möglichst kleinen Feldern an, z.B. 3x3 oder 4x4, vielleicht hat sogar 2x2 schon sinnvolles Verhalten?
und dann führe dein angefangenes Logging konsequent bis in alle Details durch, du brauchst eine Programmausgabe der Form:


evtl. ist es leichter, statt Koordinaten x/y die Felder 0-15 durchzunummerieren

Danke dass du mir das gesagt hast mit der Kopie, ich hatte gedacht dass dadurch eine Kopie erstellt wird, egal.

Noch was,
ich habe ne Game Logik schon reinprogrammiert, sie hier aber nicht gezeigt, weil sie nicht richtig funktioniert, weil irgendetwas mit der abfrage nicht stimmt, wenn ich aber die umliegenden Felder ausgeben lasse und so, passieren leider diese Fehler,
Ich habe jetzt die Sachen so geändert, dass ein komplett neues Array erstellt wird, und alle Elemente mit hilfe einer Schleife einen Wert zugeordnet bekommen.

Jetzt funktionierts auch, jetzt muss ich nur noch die Regeln ausbauen und voilà!

Danke dir, ich bin gar nicht auf die Idee gekommen, dass z.B. reset so sein muss:
Java:
	public void reset()
	{
		for(int i = 0;i<actualUniverseArea.length;i++)
		{
			for(int t = 0;t<actualUniverseArea.length;t++)
			{
				actualUniverseArea[i][t] = originalUniverseArea[i][t];
			}
		}
	}

Danke sehr, m.f.G. Developer_X

Und ein schönes Halloween!
 

Developer_X

Top Contributor
Ich habe jetzt mal die Game Logik ausgebaut, doch sie funktioniert leider nicht wie gewünscht, bestes beispiel, >>Gleiter<<, wenn ihr sowas kennt:

010
001
111

Mein Code macht auch Fehler bei solchen Figuren:

111
111
111

bei der dritten Generation, was mache ich falsch, was stimmt mit der Game Logik nicht?
Danke für eure Antworten, m.f.G. Developer_X
Java:
	public void next()
	{
		boolean[][] newUniverseArea = new boolean[actualUniverseArea.length][actualUniverseArea.length];
		
		for(int i = 0;i<actualUniverseArea.length;i++)
		{
			for(int t = 0;t<actualUniverseArea.length;t++)
			{
				newUniverseArea[i][t] = false;
			}
		}
		
		for(int y = 0;y<actualUniverseArea.length;y++)
		{
			for(int x = 0;x<actualUniverseArea.length;x++)
			{
				int neighbours = 0;
				
				if(y==0&&x==0)
				{
					if(actualUniverseArea[x+1][y])
						neighbours++;
					if(actualUniverseArea[x+1][y+1])
						neighbours++;
					if(actualUniverseArea[x][y+1])
						neighbours++;
				}
				else if(y==actualUniverseArea.length-1&&x==actualUniverseArea.length-1)
				{
					if(actualUniverseArea[x-1][y])
						neighbours++;
					if(actualUniverseArea[x-1][y-1])
						neighbours++;
					if(actualUniverseArea[x][y-1])
						neighbours++;
				}
				else if(y<actualUniverseArea.length-1&&y>0&&x==actualUniverseArea.length-1)
				{
					if(actualUniverseArea[x-1][y])
						neighbours++;
					if(actualUniverseArea[x-1][y+1])
						neighbours++;
					if(actualUniverseArea[x][y+1])
						neighbours++;
					if(actualUniverseArea[x-1][y-1])
						neighbours++;
					if(actualUniverseArea[x][y-1])
						neighbours++;
				}
				else if(y==actualUniverseArea.length-1&&x<actualUniverseArea.length-1&&x>0)
				{
					if(actualUniverseArea[x-1][y])
						neighbours++;
					if(actualUniverseArea[x+1][y])
						neighbours++;
					if(actualUniverseArea[x-1][y-1])
						neighbours++;
					if(actualUniverseArea[x+1][y-1])
						neighbours++;
					if(actualUniverseArea[x][y-1])
						neighbours++;
				}
				else if(y>0&&y<actualUniverseArea.length-1&&x>0&&x<actualUniverseArea.length-1)
				{
					if(actualUniverseArea[x-1][y])
						neighbours++;
					if(actualUniverseArea[x+1][y])
						neighbours++;
					if(actualUniverseArea[x-1][y+1])
						neighbours++;
					if(actualUniverseArea[x+1][y+1])
						neighbours++;
					if(actualUniverseArea[x][y+1])
						neighbours++;
					if(actualUniverseArea[x-1][y-1])
						neighbours++;
					if(actualUniverseArea[x+1][y-1])
						neighbours++;
					if(actualUniverseArea[x][y-1])
						neighbours++;
				}
				else if(y>0&&y<actualUniverseArea.length-1&&x==0)
				{
					if(actualUniverseArea[x+1][y])
						neighbours++;
					if(actualUniverseArea[x+1][y+1])
						neighbours++;
					if(actualUniverseArea[x][y+1])
						neighbours++;
					if(actualUniverseArea[x+1][y-1])
						neighbours++;
					if(actualUniverseArea[x][y-1])
						neighbours++;
				}
				else if(y==0&&x>0&&x<actualUniverseArea.length-1)
				{
					if(actualUniverseArea[x-1][y])
						neighbours++;
					if(actualUniverseArea[x+1][y])
						neighbours++;
					if(actualUniverseArea[x-1][y+1])
						neighbours++;
					if(actualUniverseArea[x+1][y+1])
						neighbours++;
					if(actualUniverseArea[x][y+1])
						neighbours++;
				}
				else if(y==0&&x==actualUniverseArea.length-1)
				{
					if(actualUniverseArea[x-1][y])
						neighbours++;
					if(actualUniverseArea[x-1][y+1])
						neighbours++;
					if(actualUniverseArea[x][y+1])
						neighbours++;
				}
				else if(x==0&&y==actualUniverseArea.length-1)
				{
					if(actualUniverseArea[x+1][y])
						neighbours++;
					if(actualUniverseArea[x+1][y-1])
						neighbours++;
					if(actualUniverseArea[x][y-1])
						neighbours++;
				}
				
				if(neighbours==2)
				{
					if(actualUniverseArea[x][y])
						newUniverseArea[x][y] = true;
				}
				if(neighbours==3)
				{
					newUniverseArea[x][y] = true;
				}
				else
				{
					newUniverseArea[x][y] = false;
				}
			}
		}
		
		for(int i = 0;i<actualUniverseArea.length;i++)
		{
			for(int t = 0;t<actualUniverseArea.length;t++)
			{
				actualUniverseArea[i][t] = newUniverseArea[i][t];
			}
		}
	}
 
G

Gast2

Gast
Was zur Hölle ist das für nen for-for-endlos-if-konstrukt :eek:

Teil dir das in logische Teile auf:
- eine Methode die dir zu einer Zelle die anzahl der lebenden Nachbarn gibt
- eine Methode die dein aktuelles Spielfeld hernimmt und für jede Zelle bestimmt ob sie weiterlebt oder stirbt (da rufst du dann deine neighbourmethode auf)
 
S

SlaterB

Gast
und ich bin immer noch für ein Log, außerdem fehlt eine main-Methode und ein gesetzes Test-Start-Array,
alles Dinge die dir das Problem quasi auf den Teller servieren,
und die ich ansonsten selber machen müsste um den Fehler zu finden,

durch schieres Denken ist das manchmal nicht zu machen,
Loggen und Testen ist dagegen reine Fleißarbeit, braucht keine Genialität/Kreativität

wobei: du hast immernoch denselben Fehler drin, den ich schon früher angekreidet hatte..
wenn neighbours 2 wäre, dann würde Zeile 203 vielleicht ausgeführt, das Ergebnis von Zeile 211 aber immer überschrieben,
das bezieht sich natürlich auf den älteren Code, aber man kann dort ja sehen was gemeint ist
 

Developer_X

Top Contributor
Meine Methode macht das ja auch.

Es wird bei jeder Zelle geguckt, wie viele Nachbarn sieh hat, denn eine Zelle am Rand hat nicht die gleiche Anzahl an Nachbarn, wie eine mitten im Geschehen oder an einer Ecke, daher die If-Konstrukte,
leider funktioniert das ganze aber nicht wie es soll, weshalb?
 

Developer_X

Top Contributor
und ich bin immer noch für ein Log, außerdem fehlt eine main-Methode und ein gesetzes Test-Start-Array,
alles Dinge die dir das Problem quasi auf den Teller servieren,
und die ich ansonsten selber machen müsste um den Fehler zu finden,

durch schieres Denken ist das manchmal nicht zu machen,
Loggen und Testen ist dagegen reine Fleißarbeit, braucht keine Genialität/Kreativität

wobei: du hast immernoch denselben Fehler drin, den ich schon früher angekreidet hatte..

das bezieht sich natürlich auf den älteren Code, aber man kann dort ja sehen was gemeint ist

Das ist ja kaum zu glauben, wenn ich den Fehler behebe klappts, ein einfaches else vor das if, und schon klappts, danke euch allen,

!!!
M.f.G. Developer_X
 
G

Gast2

Gast
Es wird bei jeder Zelle geguckt, wie viele Nachbarn sieh hat, denn eine Zelle am Rand hat nicht die gleiche Anzahl an Nachbarn, wie eine mitten im Geschehen oder an einer Ecke, daher die If-Konstrukte,
leider funktioniert das ganze aber nicht wie es soll, weshalb?
Wie SlaterB schon geschrieben hat: mach Debugausgaben, lass dir loggen was passiert, dann findeste schon den fehler.
Ich würde den code trotzdem mal komplett über den Haufen werfen, wie willste den denn vernünftig warten?!
Zum Vergleich mal wie ich das damals umgesetzt hab:
Java:
    public void calculateNextGeneration() {
        ConwayGrid nextGen = grid.createEmpty();
        
        for (int i = 0; i < grid.getSize(); i++) {
            for (int j = 0; j < grid.getSize(); j++) {
                int livingNeighbours = grid.getLivingNeighboursCount(i, j);
                if (grid.getCellState(i, j)) {
                    // cell is alive, check rules
                    if (livingNeighbours == 2 || livingNeighbours == 3) {
                        nextGen.setCellState(i, j, true);
                    }
                } else {
                    // cell is dead
                    if (livingNeighbours == 3) {
                        nextGen.setCellState(i, j, true);
                    }
                }
            }
        }

        grid = nextGen;
        generationCounter++;
    }

Java:
    public int getLivingNeighboursCount(int x, int y) throws IllegalArgumentException {
        if (x >= getSize()) throw new IllegalArgumentException("x >= size");
        if (y >= getSize()) throw new IllegalArgumentException("y >= size");

        int counter = 0;
        for (int i = Math.max((x-1), 0); i <= Math.min((x+1), size-1); i++) {
            for (int j = Math.max((y-1), 0); j <= Math.min((y+1), size-1); j++) {
                if (!(i == x && j == y)) {
                    if (getCellState(i, j)) counter++;
                }
            }
        }
        return counter;
    }
 
Zuletzt bearbeitet von einem Moderator:
Ähnliche Java Themen
  Titel Forum Antworten Datum
X Game of Life Nachbarn zählen Java Basics - Anfänger-Themen 20
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
D Game of Life - Nachbarn zählen Java Basics - Anfänger-Themen 8
L Game of life in einem FensterVisualisieren Java Basics - Anfänger-Themen 2
D Game of Life Java Basics - Anfänger-Themen 14
L Wizzard-Game Java Basics - Anfänger-Themen 3
Jxhnny.lpz bouncing Ball (Brick-Breaker-Game) Java Basics - Anfänger-Themen 1
V Probleme Guessing Game Java Basics - Anfänger-Themen 8
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
H What is the Life Cycle of an Object Created Within/Outside of a Servlet? Will that item be destroyed after the session ends? Java Basics - Anfänger-Themen 1
B Erste Schritte Way of life ohne import - Habe Beispiel, macht Unfug Java Basics - Anfänger-Themen 21

Ähnliche Java Themen

Neue Themen


Oben