ライフゲームのJavaプログラム

ライフゲーム【Game of Life】は、イギリスの数学者ジョン・ホートン・コンウェイ(John Horton Conway)によって考案された、セル・オートマトンと呼ばれるモデルの一つです。

ライフゲームは、2次元の格子状の世界(通常は無限に広がる)で進行するシミュレーションゲームです。この世界は、セルと呼ばれる正方形の単位で構成されており、各セルは生死の状態を持ちます。

ライフゲームの進行は、以下のルールに基づいて行われます。

生存ルール【Survival rule】:

生きているセル(生セル)は、周囲に2つまたは3つの生セルがあれば次の世代でも生存する。
それ以外の場合は、次の世代では死滅する。
誕生ルール【Birth rule】:

死んでいるセル(死セル)は、周囲にちょうど3つの生セルがあれば次の世代で誕生する。
過疎ルール【Underpopulation rule】:

生セルが周囲に1つまたは0つの生セルしかない場合、次の世代で孤立し死滅する。
過密ルール【Overpopulation rule】:

生セルが周囲に4つ以上の生セルがある場合、次の世代で過密により死滅する。
これらのルールに従って、初期配置されたセルの状態から次々と世代が進みます。セルの状態は、周囲のセルの状態に基づいて更新され、生セルが生存するか死滅するかが決まります。

ライフゲームは、単純なルールにもかかわらず、非常に複雑なパターンや動きを生み出すことがあります。特定の初期状態によっては、安定したパターンや周期的な振る舞いを示すものもあります。また、いくつかの初期状態では、セルの配置が無限に広がるパターン(グライダーやスペースシップなど)が生まれることもあります。

ライフゲームは、数学的な研究対象としてだけでなく、コンピュータ科学や人工生命の分野での実験や視覚化にも利用されます。

<サンプルプログラム>

import java.util.Random;

public class GameOfLife {
    private static final int SIZE = 10; // フィールドのサイズ
    private static final int GENERATIONS = 100; // 世代数

    private boolean[][] currentGeneration; // 現在の世代
    private boolean[][] nextGeneration; // 次の世代

    public GameOfLife() {
        currentGeneration = new boolean[SIZE][SIZE];
        nextGeneration = new boolean[SIZE][SIZE];
        initializeField();
    }

    public void run() {
        for (int i = 0; i < GENERATIONS; i++) {
            System.out.println("Generation " + (i + 1) + ":");
            printField(currentGeneration);
            System.out.println();
            generateNextGeneration();
            swapGenerations();
        }
    }

    private void initializeField() {
        Random random = new Random();
        for (int i = 0; i < SIZE; i++) {
            for (int j = 0; j < SIZE; j++) {
                currentGeneration[i][j] = random.nextBoolean();
            }
        }
    }

    private void generateNextGeneration() {
        for (int i = 0; i < SIZE; i++) {
            for (int j = 0; j < SIZE; j++) {
                int liveNeighbors = countLiveNeighbors(i, j);
                nextGeneration[i][j] = (liveNeighbors == 3) || (liveNeighbors == 2 && currentGeneration[i][j]);
            }
        }
    }

    private int countLiveNeighbors(int row, int col) {
        int count = 0;
        for (int i = -1; i <= 1; i++) {
            for (int j = -1; j <= 1; j++) {
                if (i == 0 && j == 0) {
                    continue;
                }
                int neighborRow = (row + i + SIZE) % SIZE;
                int neighborCol = (col + j + SIZE) % SIZE;
                if (currentGeneration[neighborRow][neighborCol]) {
                    count++;
                }
            }
        }
        return count;
    }

    private void swapGenerations() {
        boolean[][] temp = currentGeneration;
        currentGeneration = nextGeneration;
        nextGeneration = temp;
    }

    private void printField(boolean[][] field) {
        for (int i = 0; i < SIZE; i++) {
            for (int j = 0; j < SIZE; j++) {
                System.out.print(field[i][j] ? "■" : "□");
            }
            System.out.println();
        }
    }

    public static void main(String[] args) {
        GameOfLife game = new GameOfLife();
        game.run();
    }
}

実行結果は各自確認ください。