Skip to content

Instantly share code, notes, and snippets.

@subnomo
Created April 21, 2015 16:59
Show Gist options
  • Save subnomo/e103c5d724ddcfa94a34 to your computer and use it in GitHub Desktop.
Save subnomo/e103c5d724ddcfa94a34 to your computer and use it in GitHub Desktop.
Game of Life
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
public class GameOfLife extends JPanel implements ActionListener, Runnable {
static JFrame frame = new JFrame("Conway's Game of Life");
static boolean[][] darwin = new boolean[100][100];
static boolean[][] backupDarwin = new boolean[100][100];
Container container = new Container();
JButton stepButt = new JButton("Step");
JButton runButt = new JButton("Run");
JButton stopButt = new JButton("Stop");
JButton saveButt = new JButton("Save");
JButton loadButt = new JButton("Load");
public void paintComponent(Graphics g) {
for (int r = 0; r < 100; r++) {
for (int c = 0; c < 100; c++) {
if (darwin[r][c]) {
g.clearRect(c * 10, r * 10, 10, 10);
g.setColor(Color.black);
g.fillRect(c * 10, r * 10, 10, 10);
} else {
g.clearRect(c * 10, r * 10, 10, 10);
g.setColor(Color.lightGray);
g.drawRect(c * 10, r * 10, 10, 10);
}
}
}
}
public static void main(String[] args) {
new GameOfLife();
}
public GameOfLife() {
addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
click(e.getX(), e.getY());
}
});
container.add(stepButt);
container.add(runButt);
container.add(stopButt);
container.add(saveButt);
container.add(loadButt);
// Sets the size of the actual viewport (without borders)
frame.getContentPane().setPreferredSize(new Dimension(1001, 1027));
container.setLayout(new GridLayout(1, 3));
frame.add(container, BorderLayout.SOUTH);
stepButt.addActionListener(this);
runButt.addActionListener(this);
stopButt.addActionListener(this);
saveButt.addActionListener(this);
loadButt.addActionListener(this);
frame.pack();
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.getContentPane().add(this);
}
public static void click(int x, int y) {
// Checks if the user is clicking outside of the designated area
if (x > 1000 || y > 1000) {
System.out.println("User clicked outside of the arena.");
return;
}
int[] position = getPosition(x, y);
int row = position[0], column = position[1];
// Flips the living/dead state of cell
darwin[row][column] = !darwin[row][column];
frame.getContentPane().repaint();
}
public static int[] getPosition(int x, int y) {
int xLength = String.valueOf(x).length();
int yLength = String.valueOf(y).length();
// Gets the column that was clicked
int column = 0;
if (xLength == 4) {
column = 99;
} else if (xLength != 0) {
column = x / 10;
}
// Gets the row that was clicked
int row = 0;
if (yLength == 4) {
row = 99;
} else if (yLength != 0) {
row = y / 10;
}
return new int[]{row, column};
}
public static int[][] getNeighbors(int x, int y) {
int[] pos1 = new int[2];
int[] pos2 = new int[2];
int[] pos3 = new int[2];
int[] pos4 = new int[2];
int[] pos5 = new int[2];
int[] pos6 = new int[2];
int[] pos7 = new int[2];
int[] pos8 = new int[2];
// Starts with upper left corner and goes around clockwise
pos1[0] = x - 1;
pos1[1] = y - 1;
pos2[0] = x;
pos2[1] = y - 1;
pos3[0] = x + 1;
pos3[1] = y - 1;
pos4[0] = x + 1;
pos4[1] = y;
pos5[0] = x + 1;
pos5[1] = y + 1;
pos6[0] = x;
pos6[1] = y + 1;
pos7[0] = x - 1;
pos7[1] = y + 1;
pos8[0] = x - 1;
pos8[1] = y;
return new int[][]{pos1, pos2, pos3, pos4, pos5, pos6, pos7, pos8};
}
public static List getLivingNeighbors(int[][] neighbors) {
List<int[]> livingNeighbors = new ArrayList<int[]>();
// For each neighbor in the list of neighbors
for (int neighbor = 0; neighbor < 8; neighbor++) {
int[] coordinates = new int[2];
System.arraycopy(neighbors[neighbor], 0, coordinates, 0, 2);
if (coordinates[0] < 0) {
coordinates[0] += 100;
}
if (coordinates[1] < 0) {
coordinates[1] += 100;
}
if (coordinates[0] > 99) {
coordinates[0] -= 100;
}
if (coordinates[1] > 99) {
coordinates[1] -= 100;
}
if (darwin[coordinates[0]][coordinates[1]]) {
livingNeighbors.add(coordinates);
}
}
return livingNeighbors;
}
public static void step() {
// Stores all the cells that will be birthed/killed
List<int[]> pleaseLive = new ArrayList<int[]>();
List<int[]> pleaseDie = new ArrayList<int[]>();
// Loops through all cells
for (int r = 0; r < 100; r++) {
for (int c = 0; c < 100; c++) {
// If alive cell
if (darwin[r][c]) {
// If it has less than 2 living neighbors or more than 3, schedule its death
if (getLivingNeighbors(getNeighbors(r, c)).size() < 2) {
int[] coordinates = {r, c};
pleaseDie.add(coordinates);
} else if (getLivingNeighbors(getNeighbors(r, c)).size() > 3) {
int[] coordinates = {r, c};
pleaseDie.add(coordinates);
}
} else {
// If dead cell with 3 living neighbors, schedule its birth
if (getLivingNeighbors(getNeighbors(r, c)).size() == 3) {
int[] coordinates = {r, c};
pleaseLive.add(coordinates);
}
}
}
}
// Loop through schedules and birth/kill accordingly
for (int[] birth : pleaseLive) {
darwin[birth[0]][birth[1]] = true;
frame.getContentPane().repaint();
}
for (int[] die : pleaseDie) {
darwin[die[0]][die[1]] = false;
frame.getContentPane().repaint();
}
}
private volatile boolean stopRequested = false;
private int speed = 100;
@Override
public void run() {
try {
while (!stopRequested) {
step();
Thread.sleep(speed);
}
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
private boolean firstRun = true;
// Gets button clicks
@Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == stepButt) {
step();
} else if (e.getSource() == runButt) {
// If this is first run or stop is requested, spawn new thread
// Else, increase speed of simulation on click
if (firstRun || stopRequested) {
stopRequested = false;
firstRun = false;
new Thread(this).start();
} else {
if (speed > 0) speed -= 20;
}
} else if (e.getSource() == stopButt) {
stopRequested = true;
speed = 100;
} else if (e.getSource() == saveButt) {
for (int i = 0; i < 100; i++) {
System.arraycopy(darwin[i], 0, backupDarwin[i], 0, 100);
}
} else if (e.getSource() == loadButt) {
for (int i = 0; i < 100; i++) {
System.arraycopy(backupDarwin[i], 0, darwin[i], 0, 100);
}
frame.getContentPane().repaint();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment