ライフゲーム

JavaScript 初心者の俺がライフゲームを実装してみました。

セルの生死は次のルールに従う。基本的な考えは「過疎状態でも過密状態でも生き残ることはできない」というものである。

誕生
死んでいるセルの周囲に3つの生きているセルがあれば次の世代では生きる(誕生する)。
維持
生きているセルの周囲に2つか3つの生きているセルがあれば次の世代でも生き残る。
死亡
上以外の場合には次の世代では死ぬ。

ライフゲーム - Wikipedia
<html>
<head>
<style type="text/css">
* { margin: 0; padding: 0; }
p { padding: 20px; font-size: 200%; }
</style>
<script type="text/javascript">
var lifegame = function() {
    var size = 15;
    var field;
    
    // フィールドの初期化
    var init = function() {
        field = new Array(size);
        for (var i = 0; i < size; i++) {
            field[i] = new Array(size);
            for (var j=0; j < size; j++) {
                // ランダムに設定。ここでは、黒セルの頻度を 1/3 に設定
                field[i][j] = (parseInt(Math.random() * 10) % 3 == 0) ? true : false;
            }
        }
    };
    
    // 次世代のフィールドを生成
    var next = function() {
        var nextField = new Array(size);
        for (var i = 0; i < size; i++) {
            nextField[i] = new Array(size);
            for (var j = 0; j < size; j++) {
                nextField[i][j] = birth(i, j) || keep(i, j);
            }
        }
        
        for (var i = 0; i < size; i++) {
            for (var j = 0; j < size; j++) {
                field[i][j] = nextField[i][j];
            }
        }
    };
    
    // 誕生するか?
    var birth = function(i, j) {
        if (field[i][j] == true) return false;
        var c = 0;
        for (var x = -1; x <= 1; x++) {
            if (i + x < 0 || i + x >= size) continue;
            for (var y = -1; y <= 1; y++) {
                if (j + y < 0 || j + y >= size || (x == 0 && y == 0)) continue;
                if (field[i+x][j+y] == true) c++;
            }
        }
        return (c == 3) ? true : false;
    };
    
    // 維持するか?
    var keep = function(i, j) {
        if (field[i][j] == false) return false;
        
        var c = 0;
        for (var x = -1; x <= 1; x++) {
            if (i + x < 0 || i + x >= size) continue;
            for (var y = -1; y <= 1; y++) {
                if (j + y < 0 || j + y >= size || (x == 0 && y == 0)) continue;
                if (field[i+x][j+y] == true) c++;
            }
        }
        return (c == 2 || c == 3) ? true : false;
    };
    
    // 描画用文字列を作成
    var createDrawBuffer = function() {
        var buf = "";
        for (var i = 0; i < size; i++) {
            for (var j = 0; j < size; j++) {
                buf += field[i][j] ? "■" : "□";
            }
            buf += "<br>";
        }
        return buf;
    };
    
    // public methods
    return {
        exec : function() {
            if (typeof(field) == "undefined") {
                init();
            } else {
                next();
            }
            document.getElementById("area").innerHTML = createDrawBuffer();
        }
    };
}();
</script>
</head>
<body onload="setInterval(lifegame.exec, '1000');">
<p id="area"></p>
</body>
</html>

とりあえずは動いてるけど、かなり無駄な処理が多いなぁ。