Conway's Game of Life for wonderfl
イギリスの数学者John Horton Conway博士が1970年に考案した
生命の誕生、進化、淘汰などのプロセスを簡易的なモデルで再現
したシミュレーションゲームである『ライフゲーム』を再現して
みました。
この『ライフゲーム』は単純に、セルが黒い時は「生」を、白い
時は「死」を表します。
生きているセルが死んだり、死んでいるセルから誕生するかは、
それぞれのセルの周囲にあるセル(合計8個)のセルによって
決まります。
ライフ進行(世代交代)によってセルが生きるか死ぬかの
法則(ルール?)は以下の通りです。
1. 現世代でセルが生きていて、周囲の生きているセルの数が1以下のとき
→ 次世代では過疎のため死にます。
2. 現世代でセルが生きていて、周囲の生きているセルの数が4以上のとき
→ 次世代では過密のため死にます。
3. 現世代でセルが生きていて、周囲の生きているセルの数が2または3のとき
→ 次世代でも生き残ります。
4. 現世代でセルが死んでいて、周囲の生きているセルの数が3のとき
→ 次世代で生が誕生します。
5. 現世代でセルが死んでいて、周囲の生きているセルの数が3でないとき
→ 次世代でも死んだままです。
この世代交代を繰り返す間に白黒のグリッドはいろんな模様に変化し
その中には有名なパターンもいくつかあるそうです。
と、書いておきながら実は僕もそこまで詳しくは知りませんので…
http://ja.wikipedia.org/wiki/ライフゲーム
でも参照してみて下さい。シンプルながら結構奥が深いです。
でもこれ、見た目シンプルなくせに激重いし、
それよりなにより、きちんとロジック通りに動いているかが心配です。
/**
* Copyright mousepancyo ( http://wonderfl.net/user/mousepancyo )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/m4jA
*/
/*
イギリスの数学者John Horton Conway博士が1970年に考案した
生命の誕生、進化、淘汰などのプロセスを簡易的なモデルで再現
したシミュレーションゲームである『ライフゲーム』を再現して
みました。
この『ライフゲーム』は単純に、セルが黒い時は「生」を、白い
時は「死」を表します。
生きているセルが死んだり、死んでいるセルから誕生するかは、
それぞれのセルの周囲にあるセル(合計8個)のセルによって
決まります。
ライフ進行(世代交代)によってセルが生きるか死ぬかの
法則(ルール?)は以下の通りです。
1. 現世代でセルが生きていて、周囲の生きているセルの数が1以下のとき
→ 次世代では過疎のため死にます。
2. 現世代でセルが生きていて、周囲の生きているセルの数が4以上のとき
→ 次世代では過密のため死にます。
3. 現世代でセルが生きていて、周囲の生きているセルの数が2または3のとき
→ 次世代でも生き残ります。
4. 現世代でセルが死んでいて、周囲の生きているセルの数が3のとき
→ 次世代で生が誕生します。
5. 現世代でセルが死んでいて、周囲の生きているセルの数が3でないとき
→ 次世代でも死んだままです。
この世代交代を繰り返す間に白黒のグリッドはいろんな模様に変化し
その中には有名なパターンもいくつかあるそうです。
と、書いておきながら実は僕もそこまで詳しくは知りませんので…
http://ja.wikipedia.org/wiki/ライフゲーム
でも参照してみて下さい。シンプルながら結構奥が深いです。
でもこれ、見た目シンプルなくせに激重いし、
それよりなにより、きちんとロジック通りに動いているかが心配です。
*/
package {
import flash.display.Sprite;
import flash.events.MouseEvent;
import flash.events.Event;
import flash.events.TimerEvent;
import flash.utils.Timer;
import com.bit101.components.*;
[SWF(width=465, height=465, backgroundColor=0xCFCFCF, frameRate=24)]
public class Main extends Sprite{
private var _w:int = stage.stageWidth;
private var _h:int = stage.stageHeight;
private var _rectList:Vector.<Rect> = new Vector.<Rect>();
private var _xNum:int = 45
private var _yNum:int = 40
private var _timer:Timer;
private var _interval:int;
private var _isGame:Boolean;
private var _startBtn:PushButton
private var _pauseBtn:PushButton
private var _label:Label
private var _radioBtn1:RadioButton;
private var _radioBtn2:RadioButton;
private var _radioBtn3:RadioButton;
private var _radioBtn4:RadioButton;
public function Main() {
_startBtn = new PushButton(this, 180, 425, "Life Game START", statLifeGame);
makeGrid(_xNum, _yNum, 7, 8)
//
_interval = 250
}
private function makeGrid(xNum:int, yNum:int, xOffset:int, yOffset:int):void{
for(var i:int=0; i<yNum; i++){
for(var j:int=0; j<xNum; j++){
var grid:Rect = new Rect(true, false)
addChild(grid)
grid.x = grid.width * j + xOffset
grid.y = grid.height * i + yOffset
grid.id = j + i * xNum
grid.addEventListener(MouseEvent.MOUSE_OVER, rectVisibleChange)
grid.addEventListener(MouseEvent.CLICK, rectVisibleChange)
}
}
for(i=0; i<yNum; i++){
for(j=0; j<xNum; j++){
var rect:Rect = new Rect(true, true)
addChild(rect)
rect.x = rect.width * j + xOffset
rect.y = rect.height * i + yOffset
rect.id = j + i * xNum
rect.mouseEnabled = false
rect.visible = false
_rectList.push(rect)
}
}
}
private function rectVisibleChange(e:MouseEvent):void{
if(e.type == "click"){
if(_rectList[e.target.id].visible == false){
_rectList[e.target.id].visible = _rectList[e.target.id].nextLiveFlg = true
}else{
_rectList[e.target.id].visible = _rectList[e.target.id].nextLiveFlg = false
}
return
}
if(e.buttonDown == true){
if(_rectList[e.target.id].visible == false){
_rectList[e.target.id].visible = _rectList[e.target.id].nextLiveFlg = true
}else{
_rectList[e.target.id].visible = _rectList[e.target.id].nextLiveFlg = false
}
}
}
private function statLifeGame(e:MouseEvent):void{
_timer = new Timer(_interval)
_timer.addEventListener(TimerEvent.TIMER, update)
_timer.start()
//
_startBtn.removeEventListener(MouseEvent.CLICK, statLifeGame)
_startBtn.visible = false
_pauseBtn = new PushButton(this, 180, 425, "PAUSE", pauseLifeGame);
_label = new Label(this, 350, 427, "Number of Life : 0");
_radioBtn1 = new RadioButton(this, 10, 413, "Interval : 0.10 sec", false, radioBtnSelect);
_radioBtn2 = new RadioButton(this, 10, 413+12, "Interval : 0.25 sec", true, radioBtnSelect);
_radioBtn3 = new RadioButton(this, 10, 413+12+12, "Interval : 0.50 sec", false, radioBtnSelect);
_radioBtn4 = new RadioButton(this, 10, 413+12+12+12, "Interval : 1.00 sec", false, radioBtnSelect);
}
private function pauseLifeGame(e:MouseEvent):void{
if(_pauseBtn.label == "PAUSE"){
_timer.stop()
_pauseBtn.label = "RESTART"
}else{
_timer.start()
_pauseBtn.label = "PAUSE"
}
}
private function radioBtnSelect(e:Event):void{
if(_timer){
_timer.stop()
_timer.removeEventListener(TimerEvent.TIMER, update)
_timer = null
}
switch(e.currentTarget){
case _radioBtn1:
_interval = 100
break;
case _radioBtn2:
_interval = 250
break;
case _radioBtn3:
_interval = 500
break;
case _radioBtn4:
_interval = 1000
break;
}
_timer = new Timer(_interval)
_timer.addEventListener(TimerEvent.TIMER, update)
if(_pauseBtn.label == "PAUSE") _timer.start()
}
private function update(e:TimerEvent):void{
var n:int
for(var i:int=0; i<_xNum * _yNum; i++){
_rectList[i].visible = _rectList[i].nextLiveFlg
if(_rectList[i].visible == true) n++
}
for(i=0; i<_xNum * _yNum; i++){
checkProp(_rectList[i])
}
_label.text = "Number of Life : "+n
}
private function checkProp(rect:Rect):void{
var checkNum:int
//
if(rect.id > _xNum && rect.id % _xNum != 0) checkNum += singleCheck(_rectList[rect.id - _xNum - 1])
if(rect.id > _xNum) checkNum += singleCheck(_rectList[rect.id - _xNum])
if(rect.id > _xNum && rect.id % _xNum != _xNum-1) checkNum += singleCheck(_rectList[rect.id - _xNum + 1])
if(rect.id > 0) checkNum += singleCheck(_rectList[rect.id - 1])
if(rect.id < _xNum * _yNum-1) checkNum += singleCheck(_rectList[rect.id + 1])
if(rect.id < _xNum * (_yNum-1) && rect.id % _xNum != 0) checkNum += singleCheck(_rectList[rect.id + _xNum - 1])
if(rect.id < _xNum * (_yNum-1)) checkNum += singleCheck(_rectList[rect.id + _xNum])
if(rect.id < _xNum * (_yNum-1)-1 && rect.id % _xNum != _xNum-1) checkNum += singleCheck(_rectList[rect.id + _xNum + 1])
//
if(rect.visible == true){
if(checkNum <= 1 || checkNum >= 4){
rect.nextLiveFlg = false
}else{
rect.nextLiveFlg = true
}
}else{
if(checkNum == 3){
rect.nextLiveFlg = true
}else{
rect.nextLiveFlg = false
}
}
//
function singleCheck(r:Rect):int{
if(r.visible){
return 1
}else{
return 0
}
}
}
}
}
//
import flash.display.Sprite;
import flash.display.Shape;
class Rect extends Sprite{
private var _id:int
public var nextLiveFlg:Boolean
public function Rect(isLine:Boolean, isFill:Boolean){
var sh:Shape = new Shape()
if(isLine) sh.graphics.lineStyle(0,0xC0C0C0)
if(isFill){
sh.graphics.beginFill(0)
}else{
sh.graphics.beginFill(0xFFFFFF)
}
sh.graphics.drawRect(0, 0, 10, 10)
sh.graphics.endFill()
addChild(sh)
}
public function set id(n:int):void{
_id = n
}
public function get id():int{
return _id
}
}