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

APP Java
スポンサーリンク

では「ランダム初期化から安定構造や振動構造を自動検出する」三次元ライフゲームの例題を作ってみましょう。


ポイント

  • ランダム初期化: 立方体のセルをランダムに生死状態にする。
  • シミュレーション: 一定ステップ進める。
  • 状態記録: 各ステップの状態を文字列化して保存。
  • 検出: 同じ状態が再出現したら「安定構造」または「振動構造」と判定。

コード例(Java)

import java.util.*;

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

    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
                }
            }
        }

        // 過去の状態を記録
        Map<String, Integer> seen = new HashMap<>();

        for (int step = 0; step < STEPS; step++) {
            System.out.println("Step " + step);
            printGrid(grid);

            String state = encode(grid);
            if (seen.containsKey(state)) {
                int prevStep = seen.get(state);
                int cycle = step - prevStep;
                if (cycle == 1) {
                    System.out.println("→ 安定構造(変化なし)を検出!");
                } else {
                    System.out.println("→ 振動構造(周期 " + cycle + ")を検出!");
                }
                break;
            }
            seen.put(state, step);

            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("---");
        }
    }

    static String encode(int[][][] grid) {
        StringBuilder sb = new StringBuilder();
        for (int z = 0; z < SIZE; z++) {
            for (int x = 0; x < SIZE; x++) {
                for (int y = 0; y < SIZE; y++) {
                    sb.append(grid[z][x][y]);
                }
            }
        }
        return sb.toString();
    }
}
Java

実行イメージ

  • ランダム初期化 → 進化を繰り返す。
  • 途中で同じ状態が再出現すると、
    • 周期=1 → 安定構造
    • 周期>1 → 振動構造

✅ まとめ

  • ランダム初期化からでも「安定構造」「振動構造」が自然に現れる。
  • 状態を文字列化して記録することで簡単に検出できる。
  • 周期を計算すれば「振動構造の周期」もわかる。

タイトルとURLをコピーしました