vendredi 24 juin 2016

Game of Life problems with structure probably Swing related

I am currently trying to develop a game of life implementation. I managed to find solutions for nearly every problem, but I am struggling with the "patterns". Nearly everything I tried won't offer the correct patterns like the "blinker". I think that the GUI / Swing might be the reason for the wrong patterns due to a delay, but I am not sure about that or even a way to fix that. I am going to attach a screenshot of the static patterns and my current code. Any advice is appreciated. The implemented Strategy Interface only offers some Integers (3 = MAX, 2 = MIN). To get myself to work with interfaces. GameOfLifeFrame public class GameOfLifeFrame extends JFrame implements ActionListener{ private GameOfLifeBoard gameBoard; private GameOfLifeInterface gameInterface; private JPanel btnPanel; private JPanel jPanel; private JMenuBar jMenuBar; private JMenu jMenu; private JButton btnStart; private JButton btnStop; private JMenuItem jMenuItemStart; private JMenuItem jMenuItemStop; private JMenuItem jMenuItemReset; private JMenuItem jMenuItemExit; * Constructor */ public GameOfLifeFrame(){ initComponents(); } private void initComponents(){ gameBoard = new GameOfLifeBoard(); gameInterface = new GameOfLifeInterface(gameBoard); add(gameInterface); btnPanel = new JPanel(); jPanel = new JPanel(); setJMenu(); setButtons(); setTitle("Game of Life"); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setLocationByPlatform(true); Dimension minDim = new Dimension(500,500); Dimension prefDim = new Dimension(500,500); setMinimumSize(minDim); setPreferredSize(prefDim); add(jMenuBar, BorderLayout.PAGE_START); add(jPanel, BorderLayout.NORTH); add(btnPanel, BorderLayout.SOUTH); pack(); setVisible(true); } /** * private void setJMenu * Creates JMenu for GameOfLife Frame */ private void setJMenu(){ jMenuBar = new JMenuBar(); jMenu = new JMenu("Menü"); jMenuItemStart = new JMenuItem("Start"); jMenuItemStop = new JMenuItem("Stop"); jMenuItemReset = new JMenuItem("Zurücksetzen"); jMenuItemExit = new JMenuItem("Verlassen"); //Menu ActionListener jMenuItemStart.addActionListener(this); jMenuItemStop.addActionListener(this); jMenuItemReset.addActionListener(this); jMenuItemExit.addActionListener(this); //Adding MenuItem to Menu & Menu to MenuBar jMenu.add(jMenuItemStart); jMenu.add(jMenuItemStop); jMenu.add(jMenuItemReset); jMenu.add(jMenuItemExit); jMenuBar.add(jMenu); } /** * actionPerformed * get Action on GUI. Reaction depends on Buttons. * * @param e ActionEvent */ @Override public void actionPerformed(ActionEvent e){ if(e.getSource() == jMenuItemStart){ gameInterface.setActivity(true); if(btnStart.getText() == "Resume"){ btnStart.setText("Start"); } } else if(e.getSource() == jMenuItemStop){ gameInterface.setActivity(false); if(btnStart.getText() == "Start"){ btnStart.setText("Resume"); } } else if(e.getSource() == jMenuItemReset){ gameBoard.setGameBoard(gameBoard.clearGameBoard()); if(!(btnStart.getText() == "Start")){ btnStart.setText("Start"); } gameBoard.randomize(); } else if(e.getSource() == jMenuItemExit){ System.exit(0); } else if(e.getSource() == btnStart){ gameInterface.setActivity(true); if(btnStart.getText() == "Resume"){ btnStart.setText("Start"); } } else if(e.getSource() == btnStop){ gameInterface.setActivity(false); btnStart.setText("Resume"); } } /** * setButtons * sets Buttons Start and Stop and adds them to the Panel & ActionListener */ private void setButtons(){ btnStart = new JButton("Start"); btnStop = new JButton("Stop"); btnPanel.add(btnStart); btnPanel.add(btnStop); btnStart.addActionListener(this); btnStop.addActionListener(this); } /** * Main Method, creates an instance of GameOfLifeFrame(GameOfLifeBoard) * @param args Main Method */ public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { public void run() { new GameOfLifeFrame(); } }); } } GameOfLifeBoard public class GameOfLifeBoard implements Strategy { private boolean[][] gameBoard; public GameOfLifeBoard() { this.gameBoard = new boolean[ROW][COL]; for (int i = 0; i < gameBoard.length; i++) { for (int j = 0; j < gameBoard[i].length; j++) { gameBoard[i][j] = false; } } } /** * getGameBoard * @return gameBoard */ boolean[][] getGameBoard(){ return gameBoard; } /** * setGameBoard * @param boolArray two-dimensional Array */ void setGameBoard(boolean[][] boolArray){ for (int i = 0; i < boolArray.length; i++){ for (int j = 0; j < boolArray[i].length; j++){ gameBoard[i][j] = boolArray[i][j]; } } } /** * clearGameBoard clears the current gameBoard by setting all boolean to false * @return clGameBoard returns a blank gameBoard */ boolean[][] clearGameBoard(){ for (int i = 0; i < gameBoard.length; i++) { for (int j = 0; j < gameBoard[i].length; j++) { gameBoard[i][j] = false; } } return gameBoard; } /** * nextGeneration calculates the new Generation (gameBoard) * using the static variables 3 and 2 (MAX and MIN) from Strategy (interface) * by applying the rules from Strategy * * nextGeneration uses a temporary 2D boolean Array to replace the old Generation with the new Generation * by looping through the current gameBoard and replacing each cell with the new status of the cell * in the new generation */ void nextGeneration(){ boolean[][] newGen = new boolean[ROW][COL];; for (int i = 0; i < gameBoard.length; i++) { for (int j = 0; j < gameBoard[i].length; j++) { newGen[i][j] = gameBoard[i][j]; switch (getAliveNeighbourCells(i,j)){ case MAX: if(getCellState(i,j)){ newGen[i][j] = true; } else if(!getCellState(i,j)){ newGen[i][j] = true; } break; case MIN: if(getCellState(i,j)){ newGen[i][j] = true; } else if(!getCellState(i,j)){ newGen[i][j] = false; } break; default: newGen[i][j] = false; break; } } } for (int i = 0; i < gameBoard.length; i++) { for (int j = 0; j < gameBoard[i].length; j++) { gameBoard[i][j] = newGen[i][j]; } } } /** * randomize randomizes each cell on the gameBoard by setting it to true or false (25% true) */ void randomize(){ for(int i = 0; i < gameBoard.length; i++){ for(int j = 0; j < gameBoard[i].length; j++){ double d = Math.random(); if(d <= 0.25){ gameBoard[i][j] = true; } else{ gameBoard[i][j] = false; } } } } /** * getNeighbourCells, counts the surrounding cells next to the current cell * @param x delivers position of current cell * @param y delivers position of current cell * @return counter-1, because the loops count the current cell itself */ private int getAliveNeighbourCells(int x, int y) { int counter = 0; for (int i = x-1; i <= x + 1; i++) { for (int j = y-1; j <= y + 1; j++) { if(i >= 0 && i < gameBoard.length-1 && j >= 0 && j < gameBoard[i].length-1){ if(gameBoard[i][j]){ counter++; } } } } return counter; } /** * getCellState returns CellState of a specific cell on the gameBoard * @param i delivers position of current cell * @param j delivers position of current cell * @return gameBoard[i][j] returns current CellState on gameBoard at position [i][j] */ @Override public boolean getCellState(int i, int j) { return gameBoard[i][j]; } GameOfLifeInterface import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; public class GameOfLifeInterface extends JPanel implements ActionListener{ private Timer time = new Timer(150, this); private GameOfLifeBoard gameBoard; private boolean isActive; /** * GameOfLifeInterface randomizes the gameBoard * @param gameBoard gets randomized by GameOfLifeBoard.randomize */ public GameOfLifeInterface(GameOfLifeBoard gameBoard){ this.gameBoard = gameBoard; gameBoard.randomize(); } /** * paintComponent draws the current Generation (Dead Cell will be painted in white, Alive Cell in Black) * and restarts or stops the Timer time * @param graph Graphics */ public void paintComponent(Graphics graph){ super.paintComponent(graph); int iBox = 2; for (int i = 0; i < gameBoard.getGameBoard().length; i++) { for (int j = 0; j < gameBoard.getGameBoard()[i].length; j++) { graph.setColor(!gameBoard.getGameBoard()[i][j]? Color.WHITE : Color.BLACK); graph.fillRect(i * iBox, j * iBox, iBox, iBox); } } if(isActive){ time.restart(); } else{ time.stop(); repaint(); } } /** * setActivity sets private boolean: true or false * @param activity boolean stores decision of User (Buttons: Stop / Start) */ public void setActivity(boolean activity){ isActive = activity; } /** * actionPerformed if Timer time has past, the current Generation will be replaced with the new Generation * GameBoard gets repainted to show the new Generation * @param e ActionEvent */ @Override public void actionPerformed(ActionEvent e) { if(e.getSource().equals(time)){ gameBoard.nextGeneration(); repaint(); } } Interface Strategy public interface Strategy { int ROW = 500; int COL = 500; int MIN = 2; int MAX = 3; boolean getCellState(int i, int j); }

Aucun commentaire:

Enregistrer un commentaire