Skip to content

Instantly share code, notes, and snippets.

@shiracamus
Created April 14, 2020 09:43
Show Gist options
  • Save shiracamus/aa06ee5097096fc3f59f7886359cc779 to your computer and use it in GitHub Desktop.
Save shiracamus/aa06ee5097096fc3f59f7886359cc779 to your computer and use it in GitHub Desktop.
import java.awt.*;
import javax.swing.*;
class Life {
private static final String DEAD = "0";
private static final String ALIVE = "1";
private String state = DEAD;
public void dead() { state = DEAD; }
public void alive() { state = ALIVE; }
public void flip() { state = state == ALIVE ? DEAD : ALIVE; }
public boolean isDead() { return state == DEAD; }
public boolean isAlive() { return state == ALIVE; }
public String toString() { return state; }
}
class Map {
public final int height, width;
private final Life[][] lives;
private static final int[] DX = {1, 1, 0, -1, -1, -1, 0, 1};
private static final int[] DY = {0, 1, 1, 1, 0, -1, -1, -1};
public Map(int height, int width) {
this.height = height;
this.width = width;
lives = new Life[height][width];
for (int y = 0; y < height; y++)
for (int x = 0; x < width; x++)
lives[y][x] = new Life();
}
public Map clone() {
Map map = new Map(height, width);
for (int y = 0; y < height; y++)
for (int x = 0; x < width; x++)
if (isAlive(y, x))
map.alive(y, x);
return map;
}
public void print() {
for (var row: lives) {
for (var life: row)
System.out.print(life);
System.out.println();
}
System.out.println();
}
public void reset() {
for (var row: lives)
for (var life: row)
life.dead();
}
public void dead(int y, int x) { lives[y][x].dead(); }
public void alive(int y, int x) { lives[y][x].alive(); }
public void flip(int y, int x) { lives[y][x].flip(); }
public boolean isDead(int y, int x) { return !isAlive(y, x); }
public boolean isAlive(int y, int x) {
return 0 <= y && y < height && 0 <= x && x < width &&
lives[y][x].isAlive();
}
public int countNeighborAlives(int y, int x) {
int alives = 0;
for (int d = 0; d < DY.length; d++)
if (isAlive(y + DY[d], x + DX[d]))
alives++;
return alives;
}
}
class MapUI extends JPanel {
private final Map map;
private class LifeUI extends JButton {
private int y, x;
private static final int SIZE = 10;
public LifeUI(int y, int x) {
this.y = y;
this.x = x;
setPreferredSize(new Dimension(SIZE, SIZE));
addActionListener(event -> map.flip(y, x));
}
public void paint(Graphics g) {
setBackground(map.isAlive(y, x) ? Color.RED : Color.BLACK);
super.paint(g);
}
}
public MapUI(Map map) {
this.map = map;
setLayout(new GridLayout(map.height, map.width));
for (int y = 0; y < map.height; y++)
for (int x = 0; x < map.width; x++)
add(new LifeUI(y, x));
}
}
class LifeGameUI {
private final LifeGame game;
private final JFrame frame;
private final MapUI map;
private final JLabel generation;
static {
try {
UIManager.setLookAndFeel(
UIManager.getCrossPlatformLookAndFeelClassName());
} catch (Exception e) {
e.printStackTrace();
}
}
public LifeGameUI(LifeGame game) {
this.game = game;
frame = new JFrame("LifeGame");
frame.getContentPane().setBackground(Color.BLACK);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel north = new JPanel();
north.setPreferredSize(new Dimension(400, 100));
north.setLayout(null);
JButton startButton = new JButton("START");
startButton.setBounds(20, 20, 100, 20);
startButton.addActionListener(event -> game.start());
north.add(startButton);
JButton stopButton = new JButton("STOP");
stopButton.setBounds(20, 50, 100, 20);
stopButton.addActionListener(event -> game.stop());
north.add(stopButton);
JButton resetButton = new JButton("RESET");
resetButton.setBounds(150, 20, 100, 20);
resetButton.addActionListener(event -> game.reset());
north.add(resetButton);
generation = new JLabel("Generation : " + game.generation);
generation.setBounds(280, 20, 100, 20);
north.add(generation);
map = new MapUI(game.map);
frame.getContentPane().add(north, BorderLayout.NORTH);
frame.getContentPane().add(map, BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
}
public void view() {
generation.setText("Generation : " + game.generation);
map.repaint();
}
}
public class LifeGame {
public final Map map;
public int generation;
public boolean isStarted = false;
public LifeGame(Map map) {
this.map = map;
generation = 0;
}
public void reset() {
map.reset();
generation = 0;
}
public void nextGeneration() {
generation++;
Map last = map.clone();
for (int y = 0; y < map.height; y++) {
for (int x = 0; x < map.width; x++) {
int alives = last.countNeighborAlives(y, x);
if (last.isDead(y, x) && alives == 3)
map.alive(y, x);
else if (last.isAlive(y, x) && (alives == 2 || alives == 3))
map.alive(y, x);
else
map.dead(y, x);
}
}
}
public void start() {
isStarted = true;
}
public void stop() {
isStarted = false;
}
public static void main(String args[]) throws InterruptedException {
int height = 60;
int width = 60;
Map map = new Map(height, width);
// map.alive(2,0);map.alive(5,0);
// map.alive(2,1);map.alive(5,1);
// map.alive(0,2);map.alive(1,2);map.alive(3,2);map.alive(4,2);map.alive(6,2);map.alive(7,2);
// map.alive(2,3);map.alive(5,3);
// map.alive(2,4);map.alive(5,4);
// map.alive(0,5);map.alive(1,5);map.alive(3,5);map.alive(4,5);map.alive(6,5);map.alive(7,5);
// map.alive(2,6);map.alive(5,6);
// map.alive(2,7);map.alive(5,7);
// map.alive(7,7);map.alive(7,6);map.alive(7,5);
// map.alive(6,7);
// map.alive(5,6);
map.print();
var game = new LifeGame(map);
var ui = new LifeGameUI(game);
ui.view();
while (true) {
if (game.isStarted) {
game.nextGeneration();
map.print();
ui.view();
}
Thread.sleep(100);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment