Java | 三次元版ライフゲーム(セルオートマトン)

APP Java
スポンサーリンク

三次元版ライフゲーム(セルオートマトン)の例題

「ライフゲーム」は二次元の格子でよく知られていますが、三次元に拡張すると「立方体の中で細胞が生きたり死んだりする」シミュレーションになります。
初心者向けに、シンプルなルールで例題を作ってみましょう。


基本ルール(3D版の簡易ルール例)

  • 各セルは「生きている (1)」か「死んでいる (0)」の状態を持つ。
  • 各セルの 26近傍(上下左右前後+斜め方向すべて)を調べる。
  • 更新ルール(例):
    • 生きているセルは、近傍に 2〜3個の生きたセルがあれば生存、そうでなければ死ぬ。
    • 死んでいるセルは、近傍に ちょうど3個の生きたセルがあれば誕生する。

コード例(Java)

import java.util.Random;

public class LifeGame3D {
    static final int SIZE = 4; // 立方体の一辺の長さ
    static final int STEPS = 5; // シミュレーションのステップ数

    public static void main(String[] args) {
        int[][][] grid = new int[SIZE][SIZE][SIZE];
        Random rand = new Random();

        // 初期化(ランダムに生死を決める)
        for (int z = 0; z < SIZE; z++) {
            for (int x = 0; x < SIZE; x++) {
                for (int y = 0; y < SIZE; y++) {
                    grid[z][x][y] = rand.nextInt(2); // 0か1
                }
            }
        }

        // シミュレーション
        for (int step = 0; step < STEPS; step++) {
            System.out.println("Step " + step);
            printGrid(grid);
            grid = nextGeneration(grid);
        }
    }

    // 次世代を計算
    static int[][][] nextGeneration(int[][][] grid) {
        int[][][] newGrid = new int[SIZE][SIZE][SIZE];

        for (int z = 0; z < SIZE; z++) {
            for (int x = 0; x < SIZE; x++) {
                for (int y = 0; y < SIZE; y++) {
                    int neighbors = countNeighbors(grid, z, x, y);
                    if (grid[z][x][y] == 1) {
                        // 生存条件
                        newGrid[z][x][y] = (neighbors == 2 || neighbors == 3) ? 1 : 0;
                    } else {
                        // 誕生条件
                        newGrid[z][x][y] = (neighbors == 3) ? 1 : 0;
                    }
                }
            }
        }
        return newGrid;
    }

    // 近傍の生きたセル数を数える
    static int countNeighbors(int[][][] grid, int z, int x, int y) {
        int count = 0;
        for (int dz = -1; dz <= 1; dz++) {
            for (int dx = -1; dx <= 1; dx++) {
                for (int dy = -1; dy <= 1; dy++) {
                    if (dz == 0 && dx == 0 && dy == 0) continue; // 自分自身は除外
                    int nz = z + dz, nx = x + dx, ny = y + dy;
                    if (nz >= 0 && nz < SIZE && nx >= 0 && nx < SIZE && ny >= 0 && ny < SIZE) {
                        count += grid[nz][nx][ny];
                    }
                }
            }
        }
        return count;
    }

    // グリッドを表示(層ごとに出力)
    static void printGrid(int[][][] grid) {
        for (int z = 0; z < SIZE; z++) {
            System.out.println("Layer " + z + ":");
            for (int x = 0; x < SIZE; x++) {
                for (int y = 0; y < SIZE; y++) {
                    System.out.print(grid[z][x][y] == 1 ? "■ " : "□ ");
                }
                System.out.println();
            }
            System.out.println("---");
        }
    }
}
Java

出力イメージ(例)

Step 0
Layer 0:
■ □ ■ □
□ □ ■ ■
■ □ □ □
□ ■ □ ■
---
Layer 1:
...

解説

  • 三重ループで「層・行・列」を回して更新。
  • 近傍計算は 26方向をチェック。
  • ルールは二次元ライフゲームと同じだが、近傍が増えるのでダイナミクスが変わる。
  • 表示は層ごとに分けると理解しやすい。

応用アイデア

  • サイズを大きくして「立方体の進化」を観察する。
  • ゴール条件を設定して「安定構造」や「振動構造」を探す。
  • 可視化を工夫して「3D表示」や「アニメーション」にするとさらに面白い。
タイトルとURLをコピーしました