Last week I was in course called to write a cellular automaton with pair programming. I had already wrote one in C using win32 APIs in last semester and I showed that C program to my partner. Although our work was not limited in java language we in fact had to rewrite cellular automaton in java due to later unit test course needing JUnit. I know C language has its unit test method but I just cannot risk my course with credit.
Finally I began to rewrite cellular automaton in java. Class cell was first wrote to manage a dual-division boolean group of squares map.
To access the daul-division group easily I made refresh method in class cell. It is boring to write such a complicated rule containing 8 branches and a dual-depth loop. It is not hard to understand but boring and annoying to impliment. My partner pointed out my mistakes in those messy branches, which showed a advantage of pair programming.
Later I followed course instructions and wrote a timer which I think to be unnecessary.
I share my code bellow. I won’t update this program anymore except my later unit test course requirements.
package life;
import java.util.Date;
import java.util.Random;
public class Cell {
private int colx=50;
private int rowy=50;
private boolean data[][]=new boolean[50][50];
//set or init data
public void setDate(boolean[][] data) throws Exception {
if(data==null||data.length==0||data[0].length==0) {
throw new Exception("Data exception");
}
this.data=data;
this.colx=data.length;
this.rowy=data[0].length;
}
//expose data
public boolean[][] getData(){
return data;
}
/**
* Get next generation data
*/
public void refresh() {
boolean[][] t=new boolean[colx][rowy];
for (int x=0;x<data.length;x++) {
for (int y=0;y<data[x].length;y++) {
int c=count(x,y);
if (data[x][y]) { //如果当前是活的
if (c == 2 || c == 3) { //周围有2或3个活的
t[x][y]= true; //下一轮继续活着
}
else { //周围活着的数量不是2或3
t[x][y]= false; //下一轮死亡
}
}
else { //如果当前是死的
if (c == 3) { //周围或者的数目是3
t[x][y]= true; //下一轮是活的
}
else { //周围或者的数目不是3
t[x][y]= false; //下一轮死亡
}
}
}
}
//set new data
data=t;
}
/**
* Count living cells around (x,y)
* @param x
* @param y
* @return The amount of living cells around x,y
*/
private int count(int x,int y) {
int ret=0;
if(x>=1&&y>=1&&x<data.length-1&&y<data[0].length-1) {
for(int a=x-1;a<=x+1;a++) {
for(int b=y-1;b<=y+1;b++) {
if(data[a][b]) {
ret++;
}
}
}
}else {
//add its self-value
if(x==0&&y==0) {
if(data[x+1][y]) {
ret++;
}
if(data[x+1][y+1]) {
ret++;
}
if(data[x][y+1]) {
ret++;
}
if(data[x][y]) {
ret++;
}
}else if (x==0&&y==data[0].length-1) {
if(data[x][y-1]) {
ret++;
}
if(data[x+1][y-1]) {
ret++;
}
if(data[x+1][y]) {
ret++;
}
if(data[x][y]) {
ret++;
}
}else if (x==data.length-1&&y==0) {
if(data[x-1][y]) {
ret++;
}
if(data[x-1][y+1]) {
ret++;
}
if(data[x][y+1]) {
ret++;
}
if(data[x][y]) {
ret++;
}
}else if (x==data.length-1&&y==data[0].length-1) {
if(data[x][y-1]) {
ret++;
}
if(data[x-1][y]) {
ret++;
}
if(data[x-1][y-1]) {
ret++;
}
if(data[x][y]) {
ret++;
}
}else if (x==0) {
for(int a=x;a<=x+1;a++) {
for(int b=y-1;b<=y+1;b++) {
if(data[a][b]) {
ret++;
}
}
}
}else if (x==data.length-1) {
for(int a=x-1;a<=x;a++) {
for(int b=y-1;b<=y+1;b++) {
if(data[a][b]) {
ret++;
}
}
}
}else if (y==0) {
for(int a=x-1;a<=x+1;a++) {
for(int b=y;b<=y+1;b++) {
if(data[a][b]) {
ret++;
}
}
}
}else if (y==data[0].length-1) {
for(int a=x-1;a<=x+1;a++) {
for(int b=y-1;b<=y;b++) {
if(data[a][b]) {
ret++;
}
}
}
}
}
if(data[x][y]) {
ret--;
}
return ret;
}
public void randmize() {
Random r=new Random(new Date().getTime());
for(int a=0;a<data.length;a++) {
for(int b=0;b<data[0].length;b++) {
data[a][b]=(r.nextInt()%6==0);
}
}
}
}
package life;
public class Timer {
private int ms=0;
public void setIntervalTimeMS(int ms) {
this.ms=ms;
}
public void start(Runnable r) {
new Thread(new Runnable() {
@Override
public void run() {
while(true) {
try {
r.run();
Thread.sleep(ms);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}).start();
}
}
package life;
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JButton;
public class Painter extends JButton{
/**
*
*/
private static final long serialVersionUID = 1096749829834574644L;
private Cell cell=null;
public Painter(Cell cell) {
this.cell=cell;
}
@Override
protected void paintComponent(Graphics g) {
g.setColor(Color.GREEN);
// TODO Auto-generated method stub
super.paintComponent(g);
boolean[][] data=cell.getData();
for(int a=0;a<data.length;a++) {
for(int b=0;b<data[0].length;b++) {
if(data[a][b]) {
g.fillRect(a*20, b*20, 20, 20);
}else {
g.drawRect(a*20, b*20, 20, 20);
}
}
}
}
}
package life;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
public class Frame extends JFrame {
/**
*
*/
private static final long serialVersionUID = -8830525594528670636L;
private Cell c;
private Painter p;
private Boolean paused = false;
private Timer t = null;
public Frame(int x, int y) {
// on close action
setDefaultCloseOperation(EXIT_ON_CLOSE);
setTitle("LifeCompute");
setLocationRelativeTo(null);
Point location = getLocation();
// add menu
addMenu();
c = new Cell();
try {
c.setDate(new boolean[x][y]);
// c.randmize();
setSize(x * 20 + 5, y * 20 + 33 + 28);
setResizable(false);
} catch (Exception e) {
// TODO Auto-generated catch block
JOptionPane.showMessageDialog(this, e.getMessage());
System.exit(-1);
}
p = new Painter(c);
p.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
synchronized (paused) {
paused = !paused;
if (paused) {
JOptionPane.showMessageDialog(Frame.this,
"Paused. \nClose this dialog and click again to continue.");
}
}
}
});
add(p);
setLocation(location.x - (getSize().width / 2), location.y - (getSize().height / 2));
}
private void addMenu() {
JMenuBar menu = new JMenuBar();
setJMenuBar(menu);
JMenu options = new JMenu("Begin");
menu.add(options);
JMenuItem arrow = options.add("Random");
arrow.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
c.randmize();
p.repaint();
if (t == null) {
t = new Timer();
t.setIntervalTimeMS(1000);
t.start(new Runnable() {
@Override
public void run() {
synchronized (paused) {
if (!paused) {
c.refresh();
p.repaint();
}
}
}
});
}
}
});
}
public static void main(String[] args) {
Frame f = new Frame(22, 22);
f.setVisible(true);
JOptionPane.showMessageDialog(f,
"You may click the squares to pause.\nClick Begin-Random to start a randomized condition.");
}
}
It runs like the image below.



