さいどうにっき

趣味や日常などを不定期で書いていきます

JavaScriptでライフゲーム作った

こんばんは。

前回の更新から一週間経たずにまた更新です。実際短期間な。

タイトルにもある通り、JSでライフゲーム作りました。
コーディング欲が満たされてとても良いです。

縦横の長さを指定してボタンを押すと始まります。
停止ボタンを押すと止まります。そのうち再開ボタンつけたいです。

300x300まで動くことを確認済みです。1000x1000投げたら落ちました。
とある方が10万x10万とか投げてサーバに負担を与えようとしていましたが、ローカル実行なので自分の首締めるだけです。
圧倒的な自信がある方やマゾヒスト以外はやめましょう。

興味のある方は以下のURLへアクセスしてください。
ライフゲーム -roadagain.org-

今回の苦労話

  • HTML5canvasタグを初めて触りました。絵とか図形とか描けて便利です。
  • JSLintがいちいちうるさい。他人のコーディング規約を守らされるのとても辛いです。インクリメント使わせて。
  • Bracketsのライブプレビューがちょくちょく接続エラー吐きました。でもその後10秒くらいで何故か繋がる不思議。
  • 配列のコピーにconcatを使いましたが、シャローコピーだったので世代を進めるときおかしな挙動してました。

ちなみにソースコードはこんな感じです。
変数名おかしかったりしますがご容赦下さい。

var play;

function initcell(width, height) {
    'use strict';
    var elem = document.getElementById('cell');

    elem.width = width * 10;
    elem.height = height * 10;
}

function drawcell(x, y, cellstate) {
    'use strict';

    var cellbox = document.getElementById('cell').getContext('2d');

    cellbox.fillStyle = cellstate === true ? 'Lime' : 'Black';
    cellbox.fillRect(x * 10 - 10, y * 10 - 10, 10, 10);
}

function next(x, y, cell) {
    'use strict';

    var cnt,
        i,
        j;

    cnt = 0;
    for (i = -1; i <= 1; i += 1) {
        for (j = -1; j <= 1; j += 1) {
            if (cell[x + i][y + j] === true) {
                cnt += 1;
            }
        }
    }
    if (cell[x][y] === true) {
        cnt -= 1;
    }

    if (cnt === 3 && cell[x][y] === false) {
        drawcell(x, y, true);
        return true;
    } else if ((cnt < 2 || 3 < cnt) && cell[x][y] === true) {
        drawcell(x, y, false);
        return false;
    } else {
        return cell[x][y];
    }
}

function stopgameoflife() {
    'use strict';

    window.clearInterval(play);
}

function gameoflife() {
    'use strict';
    var width = Math.floor(document.format.width.valueAsNumber),
        height = Math.floor(document.format.height.valueAsNumber),
        cell,
        i,
        j;

    stopgameoflife();

    cell = [];
    for (i = 0; i < width + 2; i += 1) {
        cell[i] = [];
        cell[i][0] = cell[i][height + 1] = false;
    }
    for (j = 0; j < height + 2; j += 1) {
        cell[0][j] = cell[width + 1][j] = false;
    }
    for (i = 1; i <= width; i += 1) {
        for (j = 1; j <= height; j += 1) {
            cell[i][j] = (Math.random() >= 0.5);
        }
    }

    initcell(width, height);
    for (i = 1; i <= width; i += 1) {
        for (j = 1; j <= height; j += 1) {
            drawcell(i, j, cell[i][j]);
        }
    }

    play = window.setInterval(function () {
        var tmp,
            i,
            j;

        tmp = [];
        for (i = 0; i < width + 2; i += 1) {
            tmp[i] = [];
            for (j = 0; j < height + 2; j += 1) {
                tmp[i][j] = cell[i][j];
            }
        }

        for (i = 1; i <= width; i += 1) {
            for (j = 1; j <= height; j += 1) {
                tmp[i][j] = next(i, j, cell);
            }
        }
        for (i = 1; i <= width; i += 1) {
            for (j = 1; j <= height; j += 1) {
                cell[i][j] = tmp[i][j];
            }
        }
    }, 100);
}