Conway's Game of Life実装


このゲームは?

ケンブリッジの数学者ジョンコンウェイによって発明されて、Game of Life「日本語:ライフゲーム」は「ゼロプレーヤー」セルオートマトンゲームです。生きることや、死ぬことや、増殖することができる細胞の集まりからなります。

それについての詳細はこちら:https://ja.wikipedia.org/wiki/ライフゲーム

哲学的およびその他の科学的意義はさておき「やっぱりこのポイントも面白いと思うですけれども」、プログラミングの高度な概念を学びたいとき、新しい方法で実装すると、いい勉強になると思っています。

コーディングプロセス

他の言語をテストしてみたかったですが、JavaFX Vanillaを使うことを決めました。

細胞はライフゲームの重要な要素です。

細胞の生活状態:

1) 生きている 「1で表す」
2) 死んでいる 「0で表す」

隣の細胞の生活状態に基づいて、ルールに従っている:

1) 隣細胞は2つ以下生きているなら:死ぬ
2) 2つか3つの隣細胞が住んでいるなら:生き続ける
3) 隣細胞は3つ以上生きているなら:死ぬ
4) 死んだ細胞は正確に3つの隣があったら:生きる細胞になる

僕の実装は:

cell.java
public void update() {
    int active_neighbors = countLivingNeighbors();
    if(active_neighbors == 3) turnAlive();
    else if(this.getStatus() == 1 && (active_neighbors < 2 || active_neighbors > 3)) turnDead();
}

隣の細胞をチェックするコード:

cell.java
private int getNeighbor(int x, int y) {
    if(POSX + x < 0 ||POSY +  y < 0 || POSX + x >= this.map.size() || POSY + y >= this.map.get(0).size()) 
        return 0;

    return this.map.get(POSX + x).get(POSY + y).getStatus();
}

このコードで、範囲外の細胞は死んだ細胞であると仮定する。

ユーザーインターフェース

JavaFXの技術を使って:

グリッドを書くコード

private void drawGrid(Group root) {
    for(int x = 0; x < loopsize; x ++) {
        ArrayList<Cell> row = new ArrayList<>();
        for (int y = 0; y < loopsize; y ++) {
            Cell rect = new Cell(gridmap, x, y,x * CELLSIZE, y * CELLSIZE, CELLSIZE - 1,CELLSIZE - 1);
            rect.setStroke(Color.GHOSTWHITE);
            rect.setStrokeWidth(1);
            row.add(rect);
            root.getChildren().add(rect);
        }
        gridmap.add(row);
    }
    update();
}

このコードで、セルタイプの2Dアレイリストで、ボードを設定する

アニメーションコード

time = new AnimationTimer() {
    long old_time = -1;
    @Override
    public void handle(long now) {
        if(old_time == -1) old_time = now / 1000000;
        long new_time = now / 1000000;
        if( (new_time - old_time) > TIMER_SPEED ) {
            update();
            TIMELINE++;
            updateTitle();
            old_time = now / 1000000;
        }
    }
};

タイマースピードはナノ秒で測定して、様々な計算が必要

スペースバーのキーコントロール

scene.addEventFilter(KeyEvent.KEY_PRESSED, ke -> {
    if (ke.getCode() == KeyCode.SPACE) {
        if(running) {
            running = false;
            time.stop();
            RUNNING_STATUS = STOPPED_STRING;
            updateTitle();
        }
        else {
            running = true;
            time.start();
            RUNNING_STATUS = RUNNING_STRING;
            updateTitle();
        }

        ke.consume(); // <-- stops passing the event to next node
    }
});

完成

で、それで、実装をできました!

やってみたら
レポシトリーがこちら: https://gitlab.com/bananasinmyear/game-of-life

振り返り

このプロジェクトはコードすることが楽しかった!
色々な問題を遭遇したとき、新しい解決策を考えて、
いい練習だと思います!
ずっと改善したいと思っています!

開発したい改善特徴:

死の崩壊の遅れ
メモリ管理効率
UIボターン

お楽しみに!