Created
April 14, 2020 09:43
-
-
Save shiracamus/aa06ee5097096fc3f59f7886359cc779 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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