使用js模拟《生命的游戏》数学模型

生命游戏(Game of Life)

生命游戏是由数学家约翰·康威(John Conway)于1970年发明的一种零玩家游戏。它是一种细胞自动机,通过简单的规则模拟生命的演变过程。尽管被称为“游戏”,但生命游戏实际上是一种数学模型,它使用简单的规则来模拟细胞在二维网格上的演变。

生命游戏在一个无限的二维网格上进行,每个网格上的单元格可以处于存活或死亡状态。每一代都根据一组规则演变,这些规则基于每个细胞周围的邻居细胞的状态。生命游戏的规则如下:

  1. 活细胞周围邻居少于2个时,活细胞死亡(模拟死亡的孤独)。
  2. 活细胞周围邻居大于3个时,活细胞死亡(模拟过度拥挤)。
  3. 活细胞周围邻居为2或3个时,活细胞继续存活。
  4. 死细胞周围邻居正好为3个时,死细胞复活。

这些规则简单而规律,但在演变的过程中,它们可以产生出复杂和看似随机的图案。生命游戏不需要任何玩家干预,演变是完全由初始状态决定的。这使得生命游戏成为探讨复杂系统和自组织现象的有趣工具。

这款游戏不仅在数学领域产生了深远的影响,还吸引了各行各业人士的兴趣,成为了复杂系统和人工生命研究的一个典型例子。通过这个简单的模型,玩家可以观察到各种复杂的模式和结构,它们类似于现实世界中生物体的生长、繁殖和死亡等现象。

// 定义格子的行数和列数
    const rows = 130;
    const cols = 280;

    // 创建二维数组表示格子状态,0表示死亡,1表示存活
    let grid = createGrid(rows, cols);

    // 初始化格子状态
    initializeGrid();

    // 创建格子的DOM元素并添加到页面
    const gridContainer = document.getElementById("grid");
    for (let i = 0; i < rows; i++) {
        for (let j = 0; j < cols; j++) {
            const cell = document.createElement("div");
            cell.className = "cell";
            cell.dataset.row = i;
            cell.dataset.col = j;
            cell.addEventListener("click", toggleCellState);
            gridContainer.appendChild(cell);
        }
        gridContainer.appendChild(document.createElement("br"));
    }

    // 输出初始状态
    renderGrid();

    // 演化一定次数
    const generations = 100000;
    let currentGeneration = 0;
    let intervalId;

    // 创建一个rows x cols大小的二维数组
    function createGrid(rows, cols) {
        let grid = new Array(rows);
        for (let i = 0; i < rows; i++) {
            grid[i] = new Array(cols).fill(0);
        }
        return grid;
    }

    // 初始化格子状态,随机设置一些细胞为存活状态
    function initializeGrid() {
        for (let i = 0; i < rows; i++) {
            for (let j = 0; j < cols; j++) {
                grid[i][j] = Math.random() < 0.5 ? 0 : 1;
            }
        }
    }

    // 渲染当前格子状态
    function renderGrid() {
        const cells = document.querySelectorAll(".cell");
        cells.forEach(cell => {
            const row = parseInt(cell.dataset.row);
            const col = parseInt(cell.dataset.col);
            cell.style.backgroundColor = grid[row][col] ? "black" : "white";
        });
    }

    // 点击格子时切换细胞状态
    function toggleCellState(event) {
        const row = parseInt(event.target.dataset.row);
        const col = parseInt(event.target.dataset.col);
        grid[row][col] = grid[row][col] ? 0 : 1;
        renderGrid();
    }

    // 开始演化
    function startEvolution() {
        intervalId = setInterval(evolve, 20); // 每次延迟一秒
        document.getElementById("pauseResumeBtn").textContent = "暂停";
    }

    // 暂停演化
    function pauseEvolution() {
        clearInterval(intervalId);
        document.getElementById("pauseResumeBtn").textContent = "恢复";
    }

    // 切换暂停和恢复状态
    function togglePauseResume() {
        var txt = document.getElementById("pauseResumeBtn").textContent;
        console.log(111, txt);
        if (txt == '暂停') {
            pauseEvolution();
        } else {
            startEvolution();
        }
    }

    // 演化一代
    function evolve() {
        let newGrid = createGrid(rows, cols);
        for (let i = 0; i < rows; i++) {
            for (let j = 0; j < cols; j++) {
                let neighbors = countNeighbors(i, j);
                if (grid[i][j] === 1) {
                    // 存活细胞规则
                    if (neighbors < 2 || neighbors > 3) {
                        newGrid[i][j] = 0; // 存活细胞周围存活细胞少于2个或多于3个,死亡
                    } else {
                        newGrid[i][j] = 1; // 其他情况保持存活状态
                    }
                } else {
                    // 死亡细胞规则
                    if (neighbors === 3) {
                        newGrid[i][j] = 1; // 死亡细胞周围有3个存活细胞,复活
                    } else {
                        newGrid[i][j] = 0; // 其他情况保持死亡状态
                    }
                }
            }
        }
        grid = newGrid;
        renderGrid();
    }

    // 计算某个细胞周围存活细胞的数量
    function countNeighbors(x, y) {
        let count = 0;
        for (let i = -1; i <= 1; i++) {
            for (let j = -1; j <= 1; j++) {
                if (i === 0 && j === 0) continue;
                let newX = x + i;
                let newY = y + j;
                if (newX >= 0 && newX < rows && newY >= 0 && newY < cols && grid[newX][newY] === 1) {
                    count++;
                }
            }
        }
        return count;
    }

    // 绑定按钮点击事件
    document.getElementById("pauseResumeBtn").addEventListener("click", togglePauseResume);

演示地址:https://zjun2.github.io/SortingComparison/生命的游戏.html

github仓库地址:https://github.com/zjun2/SortingComparison

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容