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の終わり