I am making Conway's Game of Life using Java Swing. I am using a 2D arrays of buttons to paint the cells. The problem I have right now is that I implemented a button which will clear the pattern or patterns drew manually o randomly and also while the timer is running. I want to clear or restart the 2D array of buttons but when I try to draw it doesn't work.
Here I have the Action Listeners for each button
//Starts the timer
Starter.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
timer.start();
cells = new JButton[size][size];
}
});
//Stops the timer
Stop.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
timer.stop();
}
});
//Clears de buttons which are painted
clear.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
for(int i = 0; i < size; i ){
for(int j = 0; j < size; j ){
if(Univers[i][j]){
cells[i][j].setBackground(Color.BLACK);
}
}
}
Arrays.fill(cells, null);
}
});
All the code:
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
import javax.swing.*;
public class GameOfLife extends JFrame{
int size=15;
int time=0;
boolean Univers[][];
JButton cells[][];
//int countentry=0;
//List<boolean[][]> Record;
JComboBox combobox;
public GameOfLife() {
//Record = new ArrayList<>();
setPreferredSize(new Dimension(600, 600));
pack();
setLayout(null);
/*combobox= new JComboBox();
combobox.addItem("Records");
combobox.addItem(time "s");
*/
Random rnd=new Random();
Univers=new boolean[size][size];
cells=new JButton[size][size];
JPanel UniversPanel=new JPanel();
UniversPanel.setBounds(0,0,500,500);
UniversPanel.setLayout(new GridLayout(size,size));
////////////////////////////////////////////////////////////
//manual cell adding
MouseListener mouseListener = new MouseListener(){
@Override
public void mouseClicked(MouseEvent e) { }
@Override
public void mouseReleased(MouseEvent e) { }
@Override
public void mousePressed(MouseEvent e) { }
@Override
public void mouseExited(MouseEvent e) { }
@Override
public void mouseEntered(MouseEvent e) {
JButton ch = (JButton) e.getSource();
//System.out.println(ch.getLocation(getLocation()));
int sizegrid = UniversPanel.getSize(getSize()).width / size;
int i = (ch.getLocation(getLocation()).x) / sizegrid;
int z = (ch.getLocation(getLocation()).y) / sizegrid;
//System.out.println("x= " i);
//System.out.println("y= " z);
if (!Univers[z][i] && SwingUtilities.isLeftMouseButton(e)) {
Univers[z][i] = true;
cells[z][i].setBackground(Color.GREEN);
}
if(Univers[z][i] && SwingUtilities.isRightMouseButton(e)) {
Univers[z][i]=false;
cells[z][i].setBackground(Color.BLACK);
}
}
};
///////////////////////////////////////////////////////////////////
for(int x=0;x<size;x ) {
for(int y=0;y<size;y ) {
/*if((x==0 && y==1 )|| (x==1 && y==1) || (x==2 && y==1)) {
Univers[x][y]=true;
}else {
Univers[x][y]=false;
}*/
Univers[x][y]=false;
//Univers[x][y]=rnd.nextInt(100)<20;
JButton btn=new JButton();
if(Univers[x][y]) {
btn.setBackground(Color.GREEN);
}else {
btn.setBackground(Color.BLACK);
}
UniversPanel.add(btn);
cells[x][y]=btn;
}
}
//Record.add(Univers);
//countentry =1;
//System.out.print(Record.size());
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
int delay=100;//milliseconds
//int Timeup=5000/delay;
Timer timer=new Timer(delay,new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
boolean[][] tempUnivers=new boolean[size][size];
//countentry =1;
for(int x=0;x<size;x ) {
for(int y=0;y<size;y ) {
int count=Neigbours(x,y);
if(Univers[x][y]) {
if(count<2) {
tempUnivers[x][y]=false;
}
if(count==3 ||count==2) {
tempUnivers[x][y]=true;
}
if(count>3) {
tempUnivers[x][y]=false;
}
}else{
if(count==3)
tempUnivers[x][y]=true;
}
}
}
Univers=tempUnivers;
//Record.add(Univers);
//System.out.print(Record.size());
for(int x=0;x<size;x ) {
for(int y=0;y<size;y ) {
if(Univers[x][y]) {
cells[x][y].setBackground(Color.GREEN);
}else {
cells[x][y].setBackground(Color.BLACK);
}
}
}
/* if(countentry==Timeup) {
time =5;
combobox.addItem(time "s");
countentry=0;
}
*/
}
});
for(int x=0;x<size;x ) {
for(int y=0;y<size;y ) {
cells[x][y].addMouseListener(mouseListener);
}
}
//Slider
/*JPanel PanelSlider =new JPanel();
PanelSlider.setLayout(new GridLayout(0,2));
PanelSlider.setBounds(0,510,300,50);
JSlider slider = new JSlider(0,5,0);
slider.setPaintTrack(true);
slider.setPaintTicks(true);
slider.setPaintLabels(true);
slider.setMajorTickSpacing(1);
slider.setMinorTickSpacing(1/10);
slider.setBounds(51, 88, 277, 52);
PanelSlider.add(combobox);
PanelSlider.add(slider);
*/
//Buttons
JPanel PanelButton =new JPanel();
PanelButton.setLayout(new GridLayout(0,3));
PanelButton.setBounds(0,510,200,50);
JButton Starter=new JButton("Start");
PanelButton.add(Starter);
JButton Stop=new JButton("Stop");
PanelButton.add(Stop);
JButton clear = new JButton("Clear");
PanelButton.add(clear);
//Starts the timer
Starter.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
timer.start();
cells = new JButton[size][size];
}
});
//Stops the timer
Stop.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
timer.stop();
}
});
//Clears de buttons which are painted
clear.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
for(int i = 0; i < size; i ){
for(int j = 0; j < size; j ){
if(Univers[i][j]){
cells[i][j].setBackground(Color.BLACK);
}
}
}
Arrays.fill(cells, null);
}
});
//add(PanelSlider);
add(UniversPanel);
add(PanelButton);
setLocationRelativeTo(null);
setVisible(true);
}
int Neigbours(int i, int z) {
int count=0;
for(int x=i-1;x<=i 1;x ) {
for(int y=z-1;y<=z 1;y ) {
try {
if(Univers[x][y]) {
count ;
}
}catch(Exception e){
//System.out.println(e);
}
}
}
if(Univers[i][z])
count--;
return count;
}
public static void main(String[] args) {
new GameOfLife();
}
//Slider info https://docs.oracle.com/javase/tutorial/uiswing/components/slider.html
//Manual insert void ActionPerformed(ActionEvent ae){add jbutton ch = (Jbutton) ae.getSource();}
}
CodePudding user response:
Please read the comment within the code to follow the changes made in the code and the recommendations:
import java.awt.*;
import java.awt.event.MouseEvent;
import javax.swing.*;
import javax.swing.event.MouseInputAdapter;
public class GameOfLife extends JFrame{
//declare constants
private final int BOARD_SIZE=15,
ANIMATION_DELAY=100;//milliseconds;
private final Cell cells[][];
public GameOfLife() {
//setPreferredSize(new Dimension(600, 600)); let layout manager work out the size derived from children
//setLayout(null); avoid using null layouts and seting bounds manually
cells=new Cell[BOARD_SIZE][BOARD_SIZE];
JPanel universPanel=new JPanel();
//universPanel.setBounds(0,0,500,500); let the layout manager set bounds
universPanel.setLayout(new GridLayout(BOARD_SIZE,BOARD_SIZE));
//initialize all cells
for(int x=0;x<BOARD_SIZE;x ) {
for(int y=0;y<BOARD_SIZE;y ) {
Cell cell=new Cell();
universPanel.add(cell);
cells[x][y]=cell;
}
}
//move the animation code to a method for better readability
Timer timer=new Timer(ANIMATION_DELAY,e -> animate());
//Buttons
JPanel panelButton =new JPanel();
panelButton.setLayout(new GridLayout(0,3));
//panelButton.setBounds(0,510,200,50); let the layout manager set bounds
JButton starter=new JButton("Start");
panelButton.add(starter);
JButton stop=new JButton("Stop");
panelButton.add(stop);
JButton clear = new JButton("Clear");
panelButton.add(clear);
//Starts the timer
starter.addActionListener(e -> timer.start());
//Stops the timer
stop.addActionListener(e -> timer.stop());
//Resets all cells
clear.addActionListener(e -> {
for(int i = 0; i < BOARD_SIZE; i ){
for(int j = 0; j < BOARD_SIZE; j ){
cells[i][j].setUniverse(false);
}
}
//Arrays.fill(cells, null); no need to set to null.
});
//add(PanelSlider);
//add to apropriate BorderLayout positions
add(universPanel, BorderLayout.CENTER);
add(panelButton, BorderLayout.SOUTH);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack(); //pack after you added all components
setVisible(true);
}
private void animate(){
for(int x1=0;x1<BOARD_SIZE;x1 ) {
for(int y1=0;y1<BOARD_SIZE;y1 ) {
int count=numberOfNeigboursAround(x1,y1);
if(cells[x1][y1].isUniverse()) {
if(count<2) {
cells[x1][y1].setUniverse(false);
}else if//process next if only if previous one was false
(count==3 ||count==2) {
cells[x1][y1].setUniverse(true);
}else if(count>3) {
cells[x1][y1].setUniverse(false);
}
}else if(count==3) {
cells[x1][y1].setUniverse(true);
}
}
}
}
private int numberOfNeigboursAround(int x, int y) {
int count=0;
for(int xIndex=x-1;xIndex<=x 1;xIndex ) {
for(int yIndex=y-1;yIndex<=y 1;yIndex ) {
//make sure index is valid
if(xIndex >= BOARD_SIZE || xIndex < 0 || yIndex >= BOARD_SIZE || yIndex < 0) {
continue;
}
//don't process center cell
if(xIndex == x&&yIndex ==y) {
continue;
}
if(cells[xIndex][yIndex].isUniverse()) {
count ;
}
}
}
return count;
}
public static void main(String[] args) {
new GameOfLife2();
}
}
//Introduce a Cell class with the needed properties. Since button functionality i snot
//use a JLabel can be used to represent a cell
class Cell extends JLabel{
private static Color BOARD = Color.BLACK, UNIVERSE = Color.GREEN, BORDER = Color.GRAY;
private static Dimension CELL_SIZE = new Dimension(30,30);
private boolean universe;
public Cell() {
super();
universe = false;
setOpaque(true);
setBorder(BorderFactory.createLineBorder(BORDER, 2));
setBackground(BOARD);
//add mouse listener. use MouseInputAdapter to implement only needed methods
addMouseListener( new MouseInputAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
mouseClicksHandler(e);
}
});
}
public boolean isUniverse() {
return universe;
}
public void setUniverse(boolean isUniverse) {
if (universe == isUniverse) return; //no change
universe = isUniverse;
setBackground(isUniverse ? UNIVERSE : BOARD);
repaint();
}
private void mouseClicksHandler(MouseEvent e){
if (SwingUtilities.isLeftMouseButton(e)) {
setUniverse(true);
}else //if first if is true no need to evaluate the second if
if( SwingUtilities.isRightMouseButton(e)) {
setUniverse(false);
}
}
//preferred size used by layout managers
@Override
public Dimension getPreferredSize() {
return CELL_SIZE;
}
}