Life Game written in Java Language



This program was written by SAWADA Takahiro. Permission to use, copy, modify, and distribute this software for NON-COMMERCIAL or COMMERCIAL purposes and without fee is hereby granted.
import java.applet.*;
import java.awt.*;

public class LifeGame extends Applet implements Runnable{
	final int sx = 80;		//横のセルの数
	final int sy = 80;		//縦のセルの数
	final int z = 6;		//画面表示の倍率
	final int ey = 40;		//操作表示部分
	final int RectSize = z-2;		//セルの描画サイズ
	final Color BackGroundColor = Color.darkGray;	//背景色
	final Color ForeGroundColor = Color.lightGray;	//前景色
	final Color ColorOfAliveCell = Color.blue;	//生きているセルの色
	final Color ColorOfVacantCell = Color.yellow;	//空のセルの色
	final boolean alive = true;		//セルの状態のフラグ
	final boolean dead = false;
	boolean cell[][] = new boolean [sx][sy];	//現在のセルの状況の配列
	boolean oldcell[][] = new boolean [sx][sy];	//前のセルの状況の配列
	byte cellcounter[][] = new byte [sx][sy];	//周りのセルの状況の配列
	double noudo = 0.3;		//初期画面でのセルの比率
	static int die = 1;		//周囲が少なくて死ぬ数
	static int unchange = 2;		//変化しない数
	static int reproduce = 3;		//セルが増える数
 	Thread th;			//スレッド
	boolean wait;			//待機状況かどうかを示すフラグ

	public void start(){
 		th = new Thread(this);
		th.start();
	}

	public void run(){
		while(th != null){	//スレッドが生きている限り
			Life();	//表示
			try{
				th.sleep(100);
			} catch(InterruptedException e){}
		}
	}

	public void stop(){
		th.stop();
		th = null;
	}

	public void init(){
		wait = true;		//スレッドの実行を押さえる
		for(int i = 0; i < sx; i++){	//セル情報の初期化
			for(int j = 0; j < sy; j++){
				cell[i][j] = oldcell[i][j]
					= ((Math.random() < noudo) ? alive : dead);
				cellcounter[i][j] = 0;
			}
		}
		resize(sx*z,sy*z+ey);	//画面サイズの設定
		setForeground(ForeGroundColor);	//前景色設定
		setBackground(BackGroundColor);
		setLayout(new BorderLayout());	//レイアウト形式指定
		Panel p = new Panel();	//コントロールを配置するパネル
		p.setLayout(new FlowLayout());	//コントロールの配置方式
		add("South", p);	//画面の一番下に表示
		p.add(new Button("run"));	//実行制御ボタンの設定
		p.add(new Button("stop"));
		p.add(new Button("continue"));
		Choice c = new Choice();	//ルール設定リストの設定
		c.addItem("normal");
		c.addItem("type 2");
		c.addItem("type 3");
		c.addItem("type 4");
		p.add(c);
		c = new Choice();	//セルの濃度設定リストの設定
		c.addItem("low");
		c.addItem("middle");
		c.addItem("high");
		p.add(c);
		wait = false;		//スレッドの動作の再開
	}

	public void paint(Graphics g){
		wait = true;		//スレッドでの書き直しを止める
		for(int i = 0; i < sx; i++){	//全てのセル領域に対して
			for(int j = 0; j < sy; j++){
				if(!cell[i][j]){//セルが空になっていれば
					g.setColor(ColorOfVacantCell);
					g.drawRect(i*z,j*z,RectSize,RectSize);
				} else {	//セルが生きていれば
				      	g.setColor(ColorOfAliveCell);
					g.drawRect(i*z,j*z,RectSize,RectSize);
				}
			}
		}
		wait = false;		//スレッドの動作再開の許可
	}

	public void Life(){
		int i, j, i2, i9, j2, j9;
		byte counter;
		boolean status = alive;

		if(wait){return;}	//ほかの処理を優先する
		Graphics g = getGraphics();
		for(i = 0; i < sx; i++){	//全てのセルに対して
			for(j = 0; j < sy; j++){
				if(!cell[i][j]){//セルが空で
					if(oldcell[i][j]){//前は空でないなら書き直す
					     	g.setColor(ColorOfVacantCell);
						g.drawRect(i*z,j*z,RectSize,RectSize);
						oldcell[i][j] = dead;
					}
				} else {	//セルが生きていて
					if(!oldcell[i][j]){//前は空だったら書き直す
					      	g.setColor(Color.blue);//(セルの状況に変化がなければそのまま)
						g.drawRect(i*z,j*z,RectSize,RectSize);
						oldcell[i][j] = alive;
					}
					i2 = i-1;	//周辺のセルに、このセルが
					i9 = i+1;	//生きているという情報を渡す
					j2 = j-1;
					j9 = j+1;
					if(i2 < 0){i2 = sx-1;}
					else if(i9 >= sx){i9 = 0;}
					if(j2 < 0){j2 = sy-1;}
					else if(j9 >= sy){j9 = 0;}
					cellcounter[i2][j2]++;
					cellcounter[i2][j]++;
					cellcounter[i2][j9]++;
					cellcounter[i][j2]++;
					cellcounter[i][j9]++;
					cellcounter[i9][j2]++;
					cellcounter[i9][j]++;
					cellcounter[i9][j9]++;
				}
			}
		}
		for(i = 0; i < sx; i++){	//全てのセルに対して
			for(j = 0; j < sy; j++){
				counter = cellcounter[i][j];//周辺のセルの数に応じて次世代の姿を決める
				if(counter <= die){cell[i][j] = dead;}
				else if(counter <= unchange){}
				else if(counter <= reproduce){cell[i][j] = alive;}
				else {cell[i][j] = dead;}
				cellcounter[i][j] = 0;	//セル情報のクリア
			}
		}
	}

	public boolean mouseDrag(Event evt, int x, int y){//マウスのドラッグ
		return mouseDown(evt, x, y);	//mouseDownと同じ動作
	}

	public boolean mouseDown(Event evt, int x, int y){//マウスの押下
		int i = x/z, j = y/z;	//マウスのセル単位での現在位置

		if(!wait){return false;}
		if((i < sx)&&(j < sy)&&(i > 0)&&(j > 0)){//セルの領域に入っていれば
			Graphics g = getGraphics();//現在のスクリーンに
			g.setColor(ColorOfAliveCell);
			g.drawRect(i*z,j*z,RectSize,RectSize);//新しいセルを描く
			cell[i][j] = oldcell[i][j] = !cell[i][j];//セルの設定
		}
		return true;		//役には立たないが形だけ返す
	}

	public boolean action(Event e, Object arg) {
		if (e.target instanceof Choice) {//リストから選択されたか?
			if("low".equals(arg)){//"low"が選択されたか?
				noudo = 0.15;//セルの初期分布濃度設定
				init();
				repaint();//初期化・実行
			} else if("middle".equals(arg)){//"middle"が選択されたか?
				noudo = 0.25;
				init();
				repaint();//初期化・実行
			} else if("high".equals(arg)){//"high"が選択されたか?
				noudo = 0.50;
				init();
				repaint();//初期化・実行
			} else if("normal".equals(arg)){//普通のライフゲームの設定
				die = 1; unchange = 2; reproduce = 3;
			} else if("type 2".equals(arg)){
				die = 1; unchange = 3; reproduce = 5;
			} else if("type 3".equals(arg)){
				die = 1; unchange = 4; reproduce = 7;
			} else if("type 4".equals(arg)){
				die = 3; unchange = 3; reproduce = 8;
			}
		} else if (e.target instanceof Button) {//ボタンが押されたか?
			if ("run".equals(arg)) {//再初期化・再実行
				init();//初期化・実行
				repaint();//初期化・実行
			} else if ("stop".equals(arg)){	//一時停止
				wait = true;//実行状況のフラグ
			} else if ("continue".equals(arg)){//動作再開
				wait = false;
			}
		}
		return true;		//役には立たないが形だけ返す
	}
}				//LifeGame classの終わり