生命代码自动机

元胞自动机python代码_Python实现元胞自动机(康威生命游戏) 元胞自动机是很常用的传播/交通模型,因此写下这篇文章,以后忘了可以再翻看元胞自动机元胞自动机又被称为康威生命游戏,是英国数学家约翰·何顿·康威在1970年发明的细胞自动机。它最初于1970年10月在《科学美国人》杂志上马丁·葛登能的“数学游戏”专栏出现元胞自动机是一个零玩家游戏。他包括一个二维矩形世界,这个世界中的每个方格居住着一个活着的或死了的细胞。一个细胞在下一时刻的生死取决于相邻八个方格中或... 阅读详情

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>简化的生命自动机</title>
    <style>
        /* 样式优化 - 右侧紧凑控制面板 */
        body {
            margin: 0;
            padding: 0;
            background-color: black;
            font-family: Arial, sans-serif;
            color: #e6e6e6;
            width: 100vw;
            height: 100vh;
            overflow: hidden;
            position: relative;
        }
        
        /* 画布样式 - 占据大部分空间 */
        canvas {
            position: fixed;
            top: 0;
            left: 0;
            width: calc(100vw - 300px); /* 留出右侧控制面板空间 */
            height: 100vh;
            background-color: black;
            z-index: 0;
        }
        
        /* 右侧控制面板 */
        .control-panel {
            position: fixed;
            top: 0;
            right: 0;
            width: 280px;
            height: 100vh;
            background-color: rgba(10, 10, 20, 0.95);
            border-left: 1px solid rgba(74, 124, 255, 0.3);
            z-index: 10;
            padding: 10px;
            overflow-y: auto;
            box-sizing: border-box;
        }
        
        /* 标题样式 */
        h1 {
            margin: 0 0 10px 0;
            font-size: 16px;
            text-align: center;
            color: #4a7cff;
            padding-bottom: 5px;
            border-bottom: 1px solid rgba(74, 124, 255, 0.3);
        }
        
        /* 按钮基础样式 - 紧凑化 */
        button {
            padding: 4px 8px;
            margin: 2px 0;
            cursor: pointer;
            background-color: rgba(22, 33, 62, 0.5);
            color: white;
            border: 1px solid rgba(74, 124, 255, 0.3);
            border-radius: 3px;
            font-size: 12px;
            transition: background-color 0.2s;
            width: 100%;
            box-sizing: border-box;
        }
        
        button:hover {
            background-color: rgba(74, 124, 255, 0.3);
        }
        
        /* 控制区域样式 - 紧凑化 */
        .compact-section {
            margin-bottom: 10px;
            padding: 5px;
            background-color: rgba(15, 20, 30, 0.5);
            border-radius: 3px;
            border: 1px solid rgba(74, 124, 255, 0.2);
        }
        
        /* 描述文本样式 */
        .axis-description {
            font-size: 11px;
            line-height: 1.2;
            margin-bottom: 8px;
            padding: 5px;
            background-color: rgba(15, 20, 30, 0.5);
            border-radius: 3px;
        }
        
        /* 颜色选择器样式 - 紧凑化 */
        .color-selector {
            font-size: 12px;
            margin-bottom: 8px;
        }
        
        .color-option-container {
            display: inline-flex;
            align-items: center;
            margin-right: 5px;
            margin-bottom: 5px;
            font-size: 11px;
        }
        
        .color-option {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            margin-right: 3px;
            cursor: pointer;
            border: 1px solid #fff;
        }
        
        /* 输入框样式 - 紧凑化 */
        input[type="number"] {
            padding: 4px;
            border: 1px solid rgba(74, 124, 255, 0.3);
            border-radius: 3px;
            background-color: rgba(26, 26, 46, 0.5);
            color: #ffffff;
            font-size: 12px;
            width: 60px;
        }
        
        /* 标签样式 */
        label {
            font-size: 12px;
            margin-right: 5px;
        }
        
        /* 按钮组样式 */
        .button-group {
            display: grid;
            grid-template-columns: 1fr 1fr;
            gap: 5px;
            margin-bottom: 8px;
        }
        
        /* 全局数量控制样式 */
        .global-count-control {
            display: flex;
            align-items: center;
            gap: 5px;
            margin-bottom: 8px;
            font-size: 11px;
        }
        
        /* 滚动条样式优化 */
        .control-panel::-webkit-scrollbar {
            width: 4px;
        }
        
        .control-panel::-webkit-scrollbar-track {
            background: rgba(10, 10, 20, 0.5);
        }
        
        .control-panel::-webkit-scrollbar-thumb {
            background: rgba(74, 124, 255, 0.5);
            border-radius: 2px;
        }
        
        /* 球类型控制器容器样式 */
        .ball-type-controls-container {
            max-height: 200px;
            overflow-y: auto;
            margin-top: 5px;
        }
        
        /* 减少文本间距 */
        p, span {
            margin: 0;
            padding: 0;
        }
        .generator-header {
            font-size: 18px;
            font-weight: bold;
            margin-bottom: 15px;
            text-align: center;
        }
        .generator-controls {
            display: flex;
            gap: 15px;
            align-items: center;
            justify-content: center;
            flex-wrap: wrap;
        }
        
        /* 球类型控制器容器 */
        .ball-type-controls {
            width: 500px;
            margin-top: 20px;
            display: flex;
            flex-direction: column;
            gap: 15px;
        }
        
        /* 轴线控制器样式 */
        .axis-controller {
            background-color: rgba(22, 33, 62, 0.2);
            border: 2px solid rgba(15, 52, 96, 0.2);
            border-radius: 4px;
            position: relative;
            padding: 15px;
            height: 80px;
            width: 500px;
            margin: 0 auto;
        }
        .axis-controller-header {
            position: absolute;
            top: 10px;
            left: 20px;
            right: 20px;
            font-weight: bold;
            display: flex;
            align-items: center;
            gap: 8px;
        }
        .controller-color-indicator {
            width: 20px;
            height: 20px;
            border-radius: 50%;
            border: 2px solid #333;
        }
        .count-control {
            margin-left: auto;
            display: flex;
            align-items: center;
            gap: 5px;
        }
        .count-control input {
            width: 60px;
            padding: 5px;
            border: 1px solid #0f3460;
            border-radius: 4px;
            background-color: #1a1a2e;
            color: #e6e6e6;
        }
        .force-controls {
            margin-left: 180px;
            margin-top: 20px;
            display: flex;
            flex-wrap: wrap;
            gap: 15px;
        }
        .force-control-label {
            font-weight: bold;
        }
        .force-control-item {
            display: flex;
            align-items: center;
            gap: 5px;
        }
        .force-color-indicator {
            width: 16px;
            height: 16px;
            border-radius: '50%';
            border: 1px solid #333;
        }
        .force-control-item input {
            width: 60px;
            padding: 3px;
            border: 1px solid #0f3460;
            border-radius: 3px;
            background-color: #1a1a2e;
            color: #e6e6e6;
        }
        .color-selector {
            display: flex;
            gap: 10px;
            align-items: center;
            flex-wrap: wrap;
        }
        .color-option-container {
            display: flex;
            align-items: center;
            cursor: pointer;
            padding: 5px;
            border-radius: 4px;
            transition: background-color 0.2s;
        }
        .color-option-container:hover {
            background-color: rgba(255, 255, 255, 0.1);
        }
        .color-option {
            width: 30px;
            height: 30px;
            border-radius: 50%;
            cursor: pointer;
            border: 3px solid transparent;
            transition: transform 0.1s;
            margin-right: 5px;
        }
        .color-option:hover {
            transform: scale(1.1);
        }
        .color-option.selected {
            border-color: #e6e6e6;
        }
        .number-control {
            display: flex;
            align-items: center;
            gap: 10px;
        }
        .number-control label {
            white-space: nowrap;
        }
        .number-control input {
            width: 60px;
            padding: 5px;
            border: 1px solid #0f3460;
            border-radius: 4px;
            background-color: #1a1a2e;
            color: #e6e6e6;
        }
        .add-balls-btn {
            background-color: #0f3460;
        }
        .add-balls-btn:hover {
            background-color: #0a2644;
        }
        
        /* 错误诊断区域 */
        .diagnostics-container {
            margin: 10px 0;
            padding: 10px;
            background-color: rgba(15, 52, 96, 0.2);
            border: 1px solid rgba(15, 52, 96, 0.2);
            border-radius: 4px;
            min-height: 20px;
            font-family: Arial, sans-serif;
            font-size: 14px;
            z-index: 1;
            position: relative;
        }
    </style>
</head>
<body>
    <!-- 右侧控制面板 -->
    <div class="control-panel">
        <h1>控制面板</h1>
        
        <!-- 控制器说明 -->
        <div class="compact-section">
            <div class="axis-description">
                <strong>说明:</strong>
                - 球有空间隔断,不重叠<br>
                - 数字控制吸引力/斥力(-1到1)<br>
                - 正值吸引,负值排斥
            </div>
        </div>
        
        <!-- 颜色选择器 -->
        <div class="compact-section">
            <div class="color-selector">
                <span>颜色:</span><br>
                <div class="color-option-container">
                    <div class="color-option" style="background-color: #FF6B6B;" data-color="#FF6B6B"></div>
                    <span>红</span>
                </div>
                <div class="color-option-container">
                    <div class="color-option" style="background-color: #4ECDC4;" data-color="#4ECDC4"></div>
                    <span>青</span>
                </div>
                <div class="color-option-container">
                    <div class="color-option" style="background-color: #FFE66D;" data-color="#FFE66D"></div>
                    <span>黄</span>
                </div>
                <div class="color-option-container">
                    <div class="color-option" style="background-color: #1A535C;" data-color="#1A535C"></div>
                    <span>深</span>
                </div>
                <div class="color-option-container">
                    <div class="color-option" style="background-color: #FF9F1C;" data-color="#FF9F1C"></div>
                    <span>橙</span>
                </div>
                <div class="color-option-container">
                    <div class="color-option" style="background-color: #7B2CBF;" data-color="#7B2CBF"></div>
                    <span>紫</span>
                </div>
            </div>
        </div>
        
        <!-- 全局数量控制 -->
        <div class="compact-section">
            <div class="global-count-control">
                <label for="globalCountInput">数量:</label>
                <input type="number" id="globalCountInput" min="1" max="1000" value="10">
            </div>
        </div>
        
        <!-- 速度控制 -->
        <div class="compact-section">
            <div class="speed-control">
                <label for="speedSlider">速度倍率: <span id="speedDisplay">1x</span></label>
                <input type="range" id="speedSlider" min="1" max="50" value="1" style="width: 100%;">
            </div>
        </div>
        
        <!-- 边界控制 -->
        <div class="compact-section">
            <div class="boundary-control">
                <label for="boundaryType">边界类型:</label>
                <select id="boundaryType" style="width: 100%; margin-top: 5px; padding: 4px; border: 1px solid rgba(74, 124, 255, 0.3); border-radius: 3px; background-color: rgba(26, 26, 46, 0.5); color: #ffffff; font-size: 12px;">
                    <option value="none">无边界</option>
                    <option value="circle">培养皿边界</option>
                    <option value="square">方形边界</option>
                </select>
            </div>
        </div>
        
        <!-- 操作按钮组 -->
        <div class="compact-section">
            <div class="button-group">
                <button id="addBallsBtn">添加球</button>
                <button id="globalRandomBtn">随机参数</button>
            </div>
            <div class="button-group">
                <button id="startBtn">开始</button>
                <button id="pauseBtn">暂停</button>
            </div>
            <button id="resetBtn">重置</button>
        </div>
        
        <!-- 球类型控制器容器 -->
        <div class="compact-section">
            <div class="ball-type-controls-container">
                <div id="ballTypeControls" class="ball-type-controls">
                    <!-- 控制器将动态添加到这里 -->
                </div>
            </div>
        </div>
    </div>
    
    <!-- 画布 - 占据大部分空间 -->
    <canvas id="canvas"></canvas>
    
    <script>
        // 获取Canvas和控制按钮
        const canvas = document.getElementById('canvas');
        const ctx = canvas.getContext('2d');
        
        // 设置画布尺寸
        function setupCanvas() {
            // 计算可用宽度(减去右侧控制面板的宽度)
            const controlPanelWidth = 300; // 与CSS中保持一致
            const availableWidth = window.innerWidth - controlPanelWidth;
            
            // 设置画布尺寸
            canvas.width = availableWidth;
            canvas.height = window.innerHeight;
            
            // 设置画布样式
            canvas.style.width = `${availableWidth}px`;
            canvas.style.height = '100%';
        }
        
        setupCanvas();
        
        // 添加窗口大小变化事件监听器,自动调整画布尺寸
        window.addEventListener('resize', setupCanvas);
        
        const startBtn = document.getElementById('startBtn');
        const pauseBtn = document.getElementById('pauseBtn');
        const resetBtn = document.getElementById('resetBtn');
        const addBallsBtn = document.getElementById('addBallsBtn');
        const colorOptions = document.querySelectorAll('.color-option');
        const ballTypeControls = document.getElementById('ballTypeControls');
        
        // 模拟状态
        const simulationState = {
            isRunning: false,
            balls: [],
            ballTypes: {}, // 存储不同颜色球的参数
            selectedColor: '#FF6B6B', // 默认选中红色
            // 视图相关状态
            viewOffset: { x: 0, y: 0 },
            viewScale: 1.0, // 视图缩放比例
            isDragging: false,
            lastMousePos: { x: 0, y: 0 },
            // 速度控制
            speedMultiplier: 1, // 速度倍率 (1-50倍)
            // 边界设置
            boundaryType: 'none', // none, circle, square
            boundaryRadius: 1000, // 圆形边界半径(初始设为明显大于页面加载时的视域)
            boundarySize: { width: 2000, height: 1600 } // 方形边界大小(初始设为明显大于页面加载时的视域)
        };
        
        // 基础状态变量
        let animationId = null;

        // 球类定义
        class Ball {
            constructor(x, y, color, type) {
                this.x = typeof x === 'number' && !isNaN(x) ? x : 0;
                this.y = typeof y === 'number' && !isNaN(y) ? y : 0;
                this.vx = 0;
                this.vy = 0;
                this.radius = 2;
                this.color = color || '#FFFFFF';
                this.type = type || 'default';
            }
            
            draw() {
                try {
                    if (typeof ctx !== 'undefined' && ctx) {
                        ctx.beginPath();
                        const x = typeof this.x === 'number' && !isNaN(this.x) ? this.x : 0;
                        const y = typeof this.y === 'number' && !isNaN(this.y) ? this.y : 0;
                        const radius = typeof this.radius === 'number' && !isNaN(this.radius) && this.radius > 0 ? this.radius : 2;
                        
                        ctx.arc(x, y, radius, 0, Math.PI * 2);
                        ctx.fillStyle = this.color || '#FFFFFF';
                        ctx.fill();
                        ctx.closePath();
                    }
                } catch (error) {
                    console.error('Ball.draw() 方法执行失败:', error);
                }
            }
            
            update() {
                try {
                    const vx = typeof this.vx === 'number' && !isNaN(this.vx) ? this.vx : 0;
                    const vy = typeof this.vy === 'number' && !isNaN(this.vy) ? this.vy : 0;
                    
                    // 只更新位置,不进行边界检测
                    this.x = (typeof this.x === 'number' && !isNaN(this.x) ? this.x : 0) + vx;
                    this.y = (typeof this.y === 'number' && !isNaN(this.y) ? this.y : 0) + vy;
                    
                    // 移除边界碰撞检测,让小球可以自由移动
                } catch (error) {
                    console.error('Ball.update() 方法执行失败:', error);
                }
            }
        }

        // 为颜色选择器添加事件监听
        colorOptions.forEach(option => {
            option.addEventListener('click', () => {
                colorOptions.forEach(opt => opt.classList.remove('selected'));
                option.classList.add('selected');
                simulationState.selectedColor = option.getAttribute('data-color');
            });
        });
        
        // 为全局数量控制添加事件监听器
        const globalCountInput = document.getElementById('globalCountInput');
        if (globalCountInput) {
            // 更新全局数量的函数
            function updateAllBallTypesCount(count) {
                try {
                    count = parseInt(count) || 1;
                    // 确保数量在有效范围内
                    count = Math.max(1, Math.min(1000, count));
                    globalCountInput.value = count;
                    
                    // 更新所有球类型的数量
                    if (simulationState && simulationState.ballTypes) {
                        for (var typeId in simulationState.ballTypes) {
                            if (simulationState.ballTypes.hasOwnProperty(typeId)) {
                                simulationState.ballTypes[typeId].defaultCount = count;
                            }
                        }
                    }
                } catch (error) {
                    console.error('更新全局数量时出错:', error);
                }
            }
            
            // 输入框变化时更新
            globalCountInput.addEventListener('change', function() {
                updateAllBallTypesCount(this.value);
            });
            

        }
        
        // 为全局一键随机按钮添加事件监听器
        const globalRandomBtn = document.getElementById('globalRandomBtn');
        if (globalRandomBtn) {
            globalRandomBtn.addEventListener('click', function() {
                try {
                    // 遍历所有球类型
                    for (var typeId in simulationState.ballTypes) {
                        if (simulationState.ballTypes.hasOwnProperty(typeId)) {
                            var randomForces = {};
                            // 为每个目标球类型生成随机力参数
                            for (var otherTypeId in simulationState.ballTypes) {
                                if (simulationState.ballTypes.hasOwnProperty(otherTypeId)) {
                                    // 生成-1到1之间的随机数,保留一位小数
                                    var randomValue = (Math.random() * 2 - 1).toFixed(1);
                                    randomForces[otherTypeId] = parseFloat(randomValue);
                                }
                            }
                            // 更新simulationState中的力参数
                            simulationState.ballTypes[typeId].forces = randomForces;
                        }
                    }
                    
                    // 更新所有控制器的UI显示
                    if (window.forceControllers) {
                        window.forceControllers.forEach(controller => {
                            try {
                                controller.update();
                            } catch (error) {
                                console.error('更新力场控制器时出错:', error);
                            }
                        });
                    }
                } catch (error) {
                    console.error('生成全局随机力参数时出错:', error);
                }
            });
        }
        
        // 默认选中第一个颜色
        colorOptions[0].classList.add('selected');

        // 获取颜色的中文名称
        function getColorName(color) {
            var colorNames = {
                '#FF6B6B': '红色',
                '#4ECDC4': '青色',
                '#FFE66D': '黄色',
                '#45B7D1': '蓝色',
                '#96CEB4': '绿色',
                '#FFEAA7': '黄色',
                '#DDA0DD': '紫色',
                '#FFA07A': '橙色',
                '#1A535C': '深青色',
                '#FF9F1C': '橙色',
                '#7B2CBF': '紫色',
                '#F08080': '浅红色',
                '#000000': '黑色',
                '#FFFFFF': '白色'
            };
            return colorNames[color] || color;
        }
        
        // 创建新的球类型控制器
        function createBallTypeController(color) {
            try {
                if (!color || typeof color !== 'string') {
                    console.error('无效的颜色参数:', color);
                    return;
                }
                
                if (!simulationState) {
                    console.error('模拟状态未初始化');
                    return;
                }
                
                if (!ballTypeControls || ballTypeControls.nodeType !== Node.ELEMENT_NODE) {
                    console.error('球类型控制器容器不存在');
                    return;
                }
                
                var typeId = color;
                
                if (!simulationState.ballTypes) {
                    simulationState.ballTypes = {};
                }
                
                if (simulationState.ballTypes[typeId]) {
                    return;
                }
                
                // 创建新的球类型参数
                simulationState.ballTypes[typeId] = {
                    color: color,
                    defaultCount: 10,
                    forces: {}
                };
                
                // 创建控制器HTML
                var controller = document.createElement('div');
                controller.className = 'axis-controller';
                controller.setAttribute('data-type-id', typeId);
                
                var safeColor = color.replace(/"/g, '&quot;');
                var safeTypeId = typeId.replace(/"/g, '&quot;').replace(/[#]/g, '');
                var colorName = getColorName ? getColorName(color) : '未知颜色';
                var safeColorName = colorName.replace(/"/g, '&quot;');
                
                controller.innerHTML = 
                    '<div class="axis-controller-header">' +
                        '<div class="controller-color-indicator" style="background-color: ' + safeColor + ';" data-type-id="' + safeTypeId + '" data-color="' + safeColor + '"></div>' +
                        '<span>' + safeColorName + '</span>' +
                        '<button class="delete-color-btn" title="删除此颜色" style="background: none; border: none; color: red; cursor: pointer; font-size: 16px; margin-left: auto; position: relative; z-index: 10;">×</button>' +
                    '</div>' +
                    '<div class="force-controls" style="position: relative; z-index: 20;">' +
                        '<div class="force-inputs" id="force-inputs-' + safeTypeId + '">' +
                        '</div>' +
                    '</div>';
                
                // 添加到容器
                try {
                    ballTypeControls.appendChild(controller);
                } catch (appendError) {
                    console.error('将控制器添加到容器失败:', appendError);
                    return;
                }
                
                // 使用全局数量控制,不再需要单独的数量输入事件监听
                
                // 为删除按钮添加事件监听
                var deleteBtn = controller.querySelector('.delete-color-btn');
                if (deleteBtn) {
                    deleteBtn.addEventListener('click', function() {
                        try {
                            // 从simulationState中删除该颜色类型
                            if (simulationState && simulationState.ballTypes && simulationState.ballTypes[typeId]) {
                                delete simulationState.ballTypes[typeId];
                                
                                // 从其他颜色类型的forces中移除对此颜色的引用
                                for (var otherTypeId in simulationState.ballTypes) {
                                    if (simulationState.ballTypes.hasOwnProperty(otherTypeId) && 
                                        simulationState.ballTypes[otherTypeId].forces && 
                                        simulationState.ballTypes[otherTypeId].forces[typeId] !== undefined) {
                                        delete simulationState.ballTypes[otherTypeId].forces[typeId];
                                    }
                                }
                                
                                // 更新所有控制器的forceInputs
                                for (var otherTypeId in simulationState.ballTypes) {
                                    if (simulationState.ballTypes.hasOwnProperty(otherTypeId)) {
                                        var otherSafeTypeId = otherTypeId.replace(/"/g, '&quot;').replace(/[#]/g, '');
                                        var otherController = document.querySelector('.axis-controller[data-type-id="' + otherSafeTypeId + '"]');
                                        if (otherController) {
                                            // 重新创建作用力输入框
                                            var recreateForceInputs = function(otherTypeId) {
                                                var otherSafeTypeId = otherTypeId.replace(/"/g, '&quot;').replace(/[#]/g, '');
                                                var forceInputsContainer = document.getElementById('force-inputs-' + otherSafeTypeId);
                                                if (!forceInputsContainer) return;
                                                
                                                forceInputsContainer.innerHTML = '';
                                                
                                                for (var otherOtherTypeId in simulationState.ballTypes) {
                                                    if (simulationState.ballTypes.hasOwnProperty(otherOtherTypeId)) {
                                                        var otherOtherColorName = getColorName ? getColorName(otherOtherTypeId) : '未知颜色';
                                                        var otherOtherSafeTypeId = otherOtherTypeId.replace(/"/g, '&quot;').replace(/[#]/g, '');
                                                         
                                                        var forceControlItem = document.createElement('div');
                                                        forceControlItem.className = 'force-control-item';
                                                        forceControlItem.style.display = 'flex';
                                                        forceControlItem.style.alignItems = 'center';
                                                        forceControlItem.style.gap = '5px';
                                                        forceControlItem.style.minWidth = '150px';
                                                         
                                                        var forceLabel = document.createElement('label');
                                                        forceLabel.htmlFor = 'force-' + otherSafeTypeId + '-to-' + otherOtherSafeTypeId;
                                                        forceLabel.style.display = 'flex';
                                                        forceLabel.style.alignItems = 'center';
                                                        forceLabel.style.gap = '5px';
                                                        forceLabel.style.fontSize = '12px';
                                                         
                                                        var colorIndicator = document.createElement('div');
                                                        colorIndicator.className = 'force-color-indicator';
                                                        colorIndicator.style.width = '16px';
                                                        colorIndicator.style.height = '16px';
                                                        colorIndicator.style.borderRadius = '50%';
                                                        colorIndicator.style.backgroundColor = otherOtherTypeId;
                                                        colorIndicator.style.border = '1px solid #333';
                                                         
                                                        var labelText = document.createTextNode('对' + otherOtherColorName + ':');
                                                         
                                                        forceLabel.appendChild(colorIndicator);
                                                        forceLabel.appendChild(labelText);
                                                        
                                                        var forceInput = document.createElement('input');
                                                        forceInput.type = 'number';
                                                        forceInput.id = 'force-' + otherSafeTypeId + '-to-' + otherOtherSafeTypeId;
                                                        forceInput.min = '-1';
                                                        forceInput.max = '1';
                                                        forceInput.step = '0.1';
                                                        forceInput.value = simulationState.ballTypes[otherTypeId].forces[otherOtherTypeId] || '0';
                                                        forceInput.style.width = '45px';
                                                        forceInput.style.padding = '3px';
                                                        forceInput.style.border = '1px solid #0f3460';
                                                        forceInput.style.borderRadius = '3px';
                                                        
                                                        // 添加事件监听
                                                        (function(otherTypeId, otherOtherTypeId) {
                                                            forceInput.addEventListener('change', function() {
                                                                try {
                                                                    var forceValue = parseFloat(this.value) || 0;
                                                                    if (simulationState && simulationState.ballTypes && simulationState.ballTypes[otherTypeId]) {
                                                                        simulationState.ballTypes[otherTypeId].forces = simulationState.ballTypes[otherTypeId].forces || {};
                                                                        simulationState.ballTypes[otherTypeId].forces[otherOtherTypeId] = forceValue;
                                                                    }
                                                                } catch (error) {
                                                                    console.error('处理力输入变化时出错:', error);
                                                                }
                                                            });
                                                        })(otherTypeId, otherOtherTypeId);
                                                         
                                                        forceControlItem.appendChild(forceLabel);
                                                        forceControlItem.appendChild(forceInput);
                                                        forceInputsContainer.appendChild(forceControlItem);
                                                    }
                                                }
                                            };
                                            recreateForceInputs(otherTypeId);
                                        }
                                    }
                                }
                                
                                // 从DOM中移除控制器
                                controller.remove();
                                
                                // 清除画布上的所有小球
                                simulationState.balls = [];
                                // 直接开始新的渲染循环即可,不需要generateBalls函数
                            }
                        } catch (error) {
                            console.error('删除颜色时出错:', error);
                        }
                    });
                }
                
                // 创建作用力输入框
                function createForceInputs() {
                    var forceInputsContainer = document.getElementById('force-inputs-' + safeTypeId);
                    if (!forceInputsContainer) return;
                    
                    // 设置容器样式,使其能随label增多而变宽,并且label之间更紧凑
                    forceInputsContainer.style.display = 'flex';
                    forceInputsContainer.style.flexWrap = 'wrap';
                    forceInputsContainer.style.justifyContent = 'flex-start';
                    forceInputsContainer.style.gap = '5px'; // 减小间距使其更紧凑
                    forceInputsContainer.style.width = 'auto'; // 让容器宽度自适应内容
                    
                    forceInputsContainer.innerHTML = '';
                    
                    for (var otherTypeId in simulationState.ballTypes) {
                        if (simulationState.ballTypes.hasOwnProperty(otherTypeId)) {
                            var otherColorName = getColorName(otherTypeId);
                            var otherSafeTypeId = otherTypeId.replace(/"/g, '&quot;').replace(/[#]/g, '');
                            
                            var forceControlItem = document.createElement('div');
                            forceControlItem.className = 'force-control-item';
                            forceControlItem.style.display = 'flex';
                            forceControlItem.style.alignItems = 'center';
                            forceControlItem.style.gap = '5px';
                            // 移除固定宽度限制,让容器能随label增多而变宽
                            forceControlItem.style.minWidth = '150px'; // 保留最小宽度以确保可用性
                            
                            var forceLabel = document.createElement('label');
                            forceLabel.htmlFor = 'force-' + safeTypeId + '-to-' + otherSafeTypeId;
                            forceLabel.style.display = 'flex';
                            forceLabel.style.alignItems = 'center';
                            forceLabel.style.gap = '5px';
                            forceLabel.style.fontSize = '12px';
                            
                            var colorIndicator = document.createElement('div');
                            colorIndicator.className = 'force-color-indicator';
                            colorIndicator.style.width = '16px';
                            colorIndicator.style.height = '16px';
                            colorIndicator.style.borderRadius = '50%';
                            colorIndicator.style.backgroundColor = otherTypeId;
                            colorIndicator.style.border = '1px solid #333';
                            
                            var labelText = document.createTextNode('对' + otherColorName + ':');
                            
                            forceLabel.appendChild(colorIndicator);
                            forceLabel.appendChild(labelText);
                            
                            var forceInput = document.createElement('input');
                            forceInput.type = 'number';
                            forceInput.id = 'force-' + safeTypeId + '-to-' + otherSafeTypeId;
                            forceInput.min = '-1';
                            forceInput.max = '1';
                            forceInput.step = '0.1';
                            forceInput.value = simulationState.ballTypes[typeId].forces[otherTypeId] || '0';
                            // 减小input宽度使其更紧凑
                            forceInput.style.width = '45px';
                            forceInput.style.padding = '3px';
                            forceInput.style.border = '1px solid #0f3460';
                            forceInput.style.borderRadius = '3px';
                            forceInput.style.backgroundColor = '#1a1a2e';
                            forceInput.style.color = '#e6e6e6';
                            
                            forceInput.addEventListener('change', function(otherTypeId) {
                                return function() {
                                    var value = parseFloat(this.value);
                                    if (!isNaN(value)) {
                                        value = Math.max(-1, Math.min(1, value));
                                        this.value = value;
                                        simulationState.ballTypes[typeId].forces[otherTypeId] = value;
                                    } else {
                                        this.value = '0';
                                        simulationState.ballTypes[typeId].forces[otherTypeId] = 0;
                                    }
                                };
                            }(otherTypeId));
                            
                            forceControlItem.appendChild(forceLabel);
                            forceControlItem.appendChild(forceInput);
                            
                            forceInputsContainer.appendChild(forceControlItem);
                        }
                    }
                }
                
                createForceInputs();
                
                if (!window.forceControllers) {
                    window.forceControllers = [];
                }
                window.forceControllers.push({
                    typeId: typeId,
                    update: createForceInputs
                });
            } catch (error) {
                console.error('创建球类型控制器时出错:', error);
            }
        }
        
        // 当添加新球类型时,更新所有力场控制器
        function onBallTypeAdded(typeId) {
            if (window.forceControllers) {
                window.forceControllers.forEach(controller => {
                    try {
                        controller.update();
                    } catch (error) {
                        console.error('更新力场控制器时出错:', error);
                    }
                });
            }
            
            if (typeId && simulationState.ballTypes[typeId] && simulationState.ballTypes[typeId].forces) {
                var newTypeParams = simulationState.ballTypes[typeId];
                for (var existingTypeId in simulationState.ballTypes) {
                    if (simulationState.ballTypes.hasOwnProperty(existingTypeId)) {
                        if (!newTypeParams.forces[existingTypeId]) {
                            newTypeParams.forces[existingTypeId] = 0;
                        }
                    }
                }
            }
        }

        // 添加球的函数 - 在全局作用域中定义
        function addBalls(color, count) {
            var problemsDiagnostics = document.getElementById('problems_and_diagnostics');
            console.log('addBalls函数被调用,参数:', {color, count});
            
            try {
                if (!color || typeof color !== 'string') {
                    var errorMsg = '无效的颜色参数: ' + color;
                    console.error(errorMsg);
                    if (problemsDiagnostics) {
                        problemsDiagnostics.innerHTML = '<span style="color: red;">错误: ' + errorMsg + '</span>';
                    }
                    return;
                }
                
                count = parseInt(count);
                if (isNaN(count) || count <= 0) {
                    var errorMsg = '无效的数量参数: ' + count;
                    console.error(errorMsg);
                    if (problemsDiagnostics) {
                        problemsDiagnostics.innerHTML = '<span style="color: red;">错误: ' + errorMsg + '</span>';
                    }
                    return;
                }
                
                var typeId = color;
                console.log('使用typeId:', typeId);
            
                if (!simulationState) {
                    console.error('模拟状态未初始化');
                    if (problemsDiagnostics) {
                        problemsDiagnostics.innerHTML = '<span style="color: red;">错误: 模拟状态未初始化</span>';
                    }
                    return;
                }
                
                if (!simulationState.ballTypes) {
                    simulationState.ballTypes = {};
                }
                
                if (!simulationState.balls) {
                    simulationState.balls = [];
                }
                
                // 创建球类型控制器(如果不存在)
                if (!simulationState.ballTypes[typeId]) {
                    try {
                        console.log('创建球类型控制器:', typeId);
                        createBallTypeController(color);
                    } catch (createError) {
                        var errorMsg = '创建球类型控制器失败: ' + createError.message;
                        console.error(errorMsg);
                        if (problemsDiagnostics) {
                            problemsDiagnostics.innerHTML = '<span style="color: red;">错误: ' + errorMsg + '</span>';
                        }
                        return;
                    }
                }
                
                // 生成球
                console.log('开始生成', count, '个球');
                const centerX = canvas.width / 2;
                const centerY = canvas.height / 2;
                const ballRadius = 2;
                
                // 初始化边界大小(确保大于初始视域)
                if (simulationState.boundaryRadius === 0 || simulationState.boundarySize.width === 0) {
                    initializeBoundarySize();
                }
                
                // 生成真正均匀分布的点
                function generateUniformPointInCircle(radius, centerX, centerY) {
                    // 使用Math.sqrt确保面积上的均匀分布,避免中心密集
                    const r = Math.sqrt(Math.random()) * (radius - ballRadius);
                    const angle = Math.random() * Math.PI * 2;
                    return {
                        x: centerX + Math.cos(angle) * r,
                        y: centerY + Math.sin(angle) * r
                    };
                }
                
                function generateUniformPointInSquare(width, height, centerX, centerY) {
                    // 线性均匀分布
                    const halfWidth = (width / 2) - ballRadius;
                    const halfHeight = (height / 2) - ballRadius;
                    return {
                        x: centerX + (Math.random() * 2 - 1) * halfWidth,
                        y: centerY + (Math.random() * 2 - 1) * halfHeight
                    };
                }
                

                
                function generateUniformPointNoBoundary() {
                    // 无边界时,在较大区域内均匀分布
                    const distributionWidth = canvas.width * 3; // 进一步扩大分布范围
                    const distributionHeight = canvas.height * 3;
                    return {
                        x: centerX + (Math.random() * 2 - 1) * distributionWidth,
                        y: centerY + (Math.random() * 2 - 1) * distributionHeight
                    };
                }
                
                // 空间分区算法确保在整个边界内均匀分布
                function generateSpatialPartitionedPoints(count) {
                    const points = [];
                    const maxAttempts = 10000; // 防止无限循环
                    let attempts = 0;
                    
                    // 根据边界类型确定分区数量
                    const partitions = Math.max(5, Math.ceil(Math.sqrt(count / 10)));
                    
                    // 计算每个分区的目标点数
                    const targetPointsPerPartition = Math.ceil(count / (partitions * partitions));
                    
                    // 为每个分区生成点
                    for (let px = 0; px < partitions; px++) {
                        for (let py = 0; py < partitions; py++) {
                            // 计算当前分区的点数量
                            const pointsInThisPartition = Math.min(targetPointsPerPartition, count - points.length);
                            if (pointsInThisPartition <= 0) break;
                            
                            // 根据边界类型计算分区边界
                            let partitionMinX, partitionMaxX, partitionMinY, partitionMaxY;
                            
                            switch(simulationState.boundaryType) {
                                case 'circle':
                                    // 圆形边界的分区
                                    const angleStart = (px / partitions) * Math.PI * 2;
                                    const angleEnd = ((px + 1) / partitions) * Math.PI * 2;
                                    const radiusStart = (py / partitions) * simulationState.boundaryRadius;
                                    const radiusEnd = ((py + 1) / partitions) * simulationState.boundaryRadius;
                                    
                                    // 在环形扇区生成点
                                    for (let i = 0; i < pointsInThisPartition; i++) {
                                        const r = radiusStart + Math.random() * (radiusEnd - radiusStart);
                                        const angle = angleStart + Math.random() * (angleEnd - angleStart);
                                        const x = centerX + Math.cos(angle) * r;
                                        const y = centerY + Math.sin(angle) * r;
                                        points.push({ x, y });
                                    }
                                    break;
                                    
                                case 'square':
                                    // 方形边界的分区
                                    const halfWidth = simulationState.boundarySize.width / 2;
                                    const halfHeight = simulationState.boundarySize.height / 2;
                                    
                                    partitionMinX = centerX - halfWidth + (px / partitions) * simulationState.boundarySize.width;
                                    partitionMaxX = centerX - halfWidth + ((px + 1) / partitions) * simulationState.boundarySize.width;
                                    partitionMinY = centerY - halfHeight + (py / partitions) * simulationState.boundarySize.height;
                                    partitionMaxY = centerY - halfHeight + ((py + 1) / partitions) * simulationState.boundarySize.height;
                                    
                                    // 在分区内生成点
                                    for (let i = 0; i < pointsInThisPartition; i++) {
                                        const x = partitionMinX + Math.random() * (partitionMaxX - partitionMinX);
                                        const y = partitionMinY + Math.random() * (partitionMaxY - partitionMinY);
                                        points.push({ x, y });
                                    }
                                    break;
                                    

                                    
                                default:
                                    // 无边界时使用方形分区
                                    partitionMinX = centerX - canvas.width * 1.5 + (px / partitions) * canvas.width * 3;
                                    partitionMaxX = centerX - canvas.width * 1.5 + ((px + 1) / partitions) * canvas.width * 3;
                                    partitionMinY = centerY - canvas.height * 1.5 + (py / partitions) * canvas.height * 3;
                                    partitionMaxY = centerY - canvas.height * 1.5 + ((py + 1) / partitions) * canvas.height * 3;
                                    
                                    for (let i = 0; i < pointsInThisPartition; i++) {
                                        const x = partitionMinX + Math.random() * (partitionMaxX - partitionMinX);
                                        const y = partitionMinY + Math.random() * (partitionMaxY - partitionMinY);
                                        points.push({ x, y });
                                    }
                            }
                        }
                        
                        // 检查是否已生成足够的点
                        if (points.length >= count) break;
                    }
                    
                    // 如果生成的点不足,补充生成
                    while (points.length < count && attempts < maxAttempts) {
                        let point;
                        switch(simulationState.boundaryType) {
                            case 'circle':
                                point = generateUniformPointInCircle(simulationState.boundaryRadius, centerX, centerY);
                                break;
                            case 'square':
                                point = generateUniformPointInSquare(simulationState.boundarySize.width, simulationState.boundarySize.height, centerX, centerY);
                                break;
                            default:
                                point = generateUniformPointNoBoundary();
                        }
                        points.push(point);
                        attempts++;
                    }
                    
                    return points;
                }
                
                // 直接使用空间分区算法生成均匀分布的点
                const points = generateSpatialPartitionedPoints(count);
                
                // 创建球
                for (let i = 0; i < points.length; i++) {
                    try {
                        const { x, y } = points[i];
                        var newBall = new Ball(x, y, color, typeId);
                        simulationState.balls.push(newBall);
                    } catch (ballError) {
                        console.error('创建单个球失败:', ballError);
                    }
                }
                
                console.log('球生成完成,当前球总数:', simulationState.balls.length);
                
                if (problemsDiagnostics) {
                    problemsDiagnostics.innerHTML = '';
                }
                
                if (typeof clearCanvas === 'function') {
                    clearCanvas();
                }
            } catch (error) {
                console.error('addBalls函数执行错误:', error);
                var errorMsg = '添加球函数执行失败: ' + error.message;
                if (problemsDiagnostics) {
                    problemsDiagnostics.innerHTML = '<span style="color: red;">错误: ' + errorMsg + '</span>';
                }
            }
        }
        
        // 确保函数在全局作用域中可用
        window.addBalls = addBalls;

        // 指数衰减力场计算函数 - 全局范围内力随距离指数衰减
        function calculateForce(ball1, ball2) {
            var dx = ball2.x - ball1.x;
            var dy = ball2.y - ball1.y;
            var distanceSq = dx * dx + dy * dy;
            
            // 如果距离太近,使用最小距离避免除零错误
            if (distanceSq < 1) {
                distanceSq = 1;
            }
            
            var distance = Math.sqrt(distanceSq);
            
            // 获取球类型参数
            var params1 = simulationState.ballTypes[ball1.type];
            var params2 = simulationState.ballTypes[ball2.type];
            
            if (!params1 || !params2) {
                return { fx: 0, fy: 0 };
            }
            
            // 用户设置的作用力
            var userForce1 = params1.forces && params1.forces[ball2.type] || 0;
            
            // 对同颜色球添加额外的吸引力,保持同色聚合特性
            var isSameColor = ball1.type === ball2.type;
            var forceStrength = 0;
            
            // 指数衰减力场核心逻辑:全局范围内力随距离指数衰减
            // 同颜色球的吸引力(除非用户明确设置了很强的排斥力)
            if (isSameColor && userForce1 > -0.5) {
                // 同色球的引力场 - 指数衰减模型
                var baseAttractionStrength = 800;
                var decayFactor = 0.015; // 控制衰减速度
                // 指数衰减公式:力 = 基础强度 * e^(-距离 * 衰减系数)
                forceStrength = baseAttractionStrength * Math.exp(-distance * decayFactor);
            } else {
                // 用户设置的力场,保持正值吸引、负值排斥的逻辑
                if (userForce1 !== 0) {
                    // 指数衰减力场:全局范围内力随距离指数衰减
                    var baseForceStrength = userForce1 > 0 ? 600 : 800;
                    var decayFactor = 0.02; // 控制衰减速度
                    // 指数衰减公式:力 = 基础强度 * e^(-距离 * 衰减系数)
                    forceStrength = (userForce1 > 0 ? 1 : -1) * baseForceStrength * Math.abs(userForce1) * Math.exp(-distance * decayFactor);
                }
            }
            
            // 计算力的分量,确保力的方向正确
            var fx = (dx / distance) * forceStrength;
            var fy = (dy / distance) * forceStrength;
            
            return { fx: fx, fy: fy };
        }

        // 空间隔断机制 - 结合圆形力场和硬性边界效果
        function maintainSeparation() {
            var balls = simulationState.balls;
            var hardBoundaryDistance = 6; // 硬性边界距离(空气墙)
            var repulsionDistance = 15; // 圆形力场斥力作用距离
            var maxRepulsionForce = 30; // 最大斥力强度
            
            for (var i = 0; i < balls.length; i++) {
                var ballA = balls[i];
                if (!ballA) continue;
                
                for (var j = i + 1; j < balls.length; j++) {
                    var ballB = balls[j];
                    if (!ballB) continue;
                    
                    var dx = ballB.x - ballA.x;
                    var dy = ballB.y - ballA.y;
                    var distance = Math.sqrt(dx * dx + dy * dy);
                    
                    // 1. 硬性边界 - 空气墙效果(绝对不可越过)
                    if (distance < hardBoundaryDistance && distance > 0) {
                        // 计算需要移动的距离,确保两球之间至少保持hardBoundaryDistance
                        var separation = hardBoundaryDistance - distance;
                        var unitX = dx / distance;
                        var unitY = dy / distance;
                        
                        // 直接调整位置,创建硬性边界效果
                        ballA.x -= unitX * separation * 0.5;
                        ballA.y -= unitY * separation * 0.5;
                        ballB.x += unitX * separation * 0.5;
                        ballB.y += unitY * separation * 0.5;
                        
                        // 额外增加速度调整,使碰撞更自然
                        var bounceFactor = 0.3;
                        ballA.vx -= unitX * bounceFactor;
                        ballA.vy -= unitY * bounceFactor;
                        ballB.vx += unitX * bounceFactor;
                        ballB.vy += unitY * bounceFactor;
                    }
                    // 2. 圆形力场斥力模型(在硬性边界之外,但在斥力范围内)
                    else if (distance >= hardBoundaryDistance && distance < repulsionDistance) {
                        // 计算斥力强度,基于距离的倒数平方关系,形成完美的圆形力场
                        // 从hardBoundaryDistance开始,距离越小,斥力越大
                        var relativeDistance = distance - hardBoundaryDistance;
                        var maxRelativeDistance = repulsionDistance - hardBoundaryDistance;
                        var forceFactor = 1 - (relativeDistance / maxRelativeDistance); // 0到1之间
                        var forceMagnitude = maxRepulsionForce * Math.pow(forceFactor, 2);
                        
                        // 计算单位方向向量
                        var unitX = dx / distance;
                        var unitY = dy / distance;
                        
                        // 计算斥力分量
                        var repulsionX = unitX * forceMagnitude;
                        var repulsionY = unitY * forceMagnitude;
                        
                        // 应用斥力(注意方向相反),增大斥力系数使效果更明显
                        ballA.vx = (ballA.vx || 0) - repulsionX * 0.0001;
                        ballA.vy = (ballA.vy || 0) - repulsionY * 0.0001;
                        ballB.vx = (ballB.vx || 0) + repulsionX * 0.0001;
                        ballB.vy = (ballB.vy || 0) + repulsionY * 0.0001;
                    }
                }
            }
        }

        // 清空画布
        function clearCanvas() {
            ctx.fillStyle = 'black';
            ctx.fillRect(0, 0, canvas.width, canvas.height);
        }
        
        // 简化的动画循环
        function animate() {
            try {
                if (!simulationState) {
                    animationId = requestAnimationFrame(animate);
                    return;
                }
                
                // 物理更新只在模拟运行时执行
                if (simulationState.isRunning) {
                    // 考虑速度倍率,可能需要执行多次物理更新
                    var speedMultiplier = simulationState.speedMultiplier || 1;
                    var updateSteps = Math.ceil(speedMultiplier);
                    var stepFactor = speedMultiplier / updateSteps;
                    
                    // 执行多次物理更新以实现快进效果
                    for (var step = 0; step < updateSteps; step++) {
                        if (Array.isArray(simulationState.balls)) {
                            var forces = [];
                            for (var i = 0; i < simulationState.balls.length; i++) {
                                forces[i] = { fx: 0, fy: 0 };
                            }
                            
                            var balls = simulationState.balls;
                            var ballA, ballB;
                            var force;
                            
                            // 简化的力计算:只考虑附近球体
                            for (var i = 0; i < balls.length; i++) {
                                ballA = balls[i];
                                if (!ballA) continue;
                                
                                for (var j = 0; j < balls.length; j++) {
                                    if (i === j) continue;
                                    
                                    ballB = balls[j];
                                    if (!ballB) continue;
                                    
                                    var dx = ballB.x - ballA.x;
                                    var dy = ballB.y - ballA.y;
                                    var distance = Math.sqrt(dx * dx + dy * dy);
                                    
                                    // 全局范围内计算相互作用,使用指数衰减模型
                                    force = calculateForce(ballA, ballB);
                                    if (force && typeof force.fx === 'number' && typeof force.fy === 'number') {
                                        forces[i].fx += force.fx;
                                        forces[i].fy += force.fy;
                                    }
                                }
                            }
                            
                            var balls = simulationState.balls;
                            var ball;
                            var maxSpeed = 4;
                            var speedLimitSq = maxSpeed * maxSpeed;
                            
                            for (var i = 0; i < balls.length; i++) {
                                ball = balls[i];
                                if (!ball) continue;
                                
                                if (forces[i]) {
                                    // 应用力并添加速度阻尼,考虑步长因子
                                    // 由于使用指数衰减模型,调整力的强度参数
                                    var forceMultiplier = 0.000005 * stepFactor;
                                    ball.vx = ((ball.vx || 0) * 0.97) + (forces[i].fx * forceMultiplier);
                                    ball.vy = ((ball.vy || 0) * 0.97) + (forces[i].fy * forceMultiplier);
                                }
                                
                                var vx = ball.vx || 0;
                                var vy = ball.vy || 0;
                                var speedSq = vx * vx + vy * vy;
                                
                                if (speedSq > speedLimitSq) {
                                    var factor = maxSpeed / Math.sqrt(speedSq);
                                    ball.vx = vx * factor;
                                    ball.vy = vy * factor;
                                }
                                
                                // 考虑步长因子更新位置
                                ball.x = (ball.x || 0) + ball.vx * stepFactor;
                                ball.y = (ball.y || 0) + ball.vy * stepFactor;
                                
                                // 应用边界碰撞检测
                                checkBoundaryCollision(ball);
                            }
                            
                            // 应用空间隔断机制
                            maintainSeparation();
                        }
                    }
                }
                
                // 无论模拟是否运行,都执行渲染,这样可以在开始前控制视图
                if (typeof clearCanvas === 'function') {
                    clearCanvas();
                }
                
                if (ctx && Array.isArray(simulationState.balls)) {
                    var viewOffset = simulationState.viewOffset || {x: 0, y: 0};
                    var offsetX = viewOffset.x || 0;
                    var offsetY = viewOffset.y || 0;
                    var viewScale = simulationState.viewScale || 1.0;
                    
                    ctx.save();
                    // 应用缩放变换
                    ctx.translate(offsetX + canvas.width / 2, offsetY + canvas.height / 2);
                    ctx.scale(viewScale, viewScale);
                    ctx.translate(-canvas.width / 2, -canvas.height / 2);
                    
                    var balls = simulationState.balls;
                    var ball;
                    for (var i = 0; i < balls.length; i++) {
                        ball = balls[i];
                        if (ball) {
                            ctx.beginPath();
                            ctx.arc(ball.x, ball.y, ball.radius || 2, 0, Math.PI * 2);
                            ctx.fillStyle = ball.color || '#ffffff';
                            ctx.fill();
                            ctx.closePath();
                        }
                    }
                    
                    // 绘制边界
                    drawBoundary();
                    
                    ctx.restore();
                }
            } catch (animateError) {
                console.error('动画循环执行失败:', animateError);
            }
            
            try {
                animationId = requestAnimationFrame(animate);
            } catch (requestError) {
                console.error('请求下一帧动画失败:', requestError);
                setTimeout(animate, 16);
            }
        }

        // 重置模拟
        function resetSimulation() {
            simulationState.isRunning = false;
            simulationState.balls = [];
            simulationState.viewOffset = { x: 0, y: 0 };
            simulationState.viewScale = 1.0;
            
            // 重置速度
            simulationState.speedMultiplier = 1;
            if (speedSlider) speedSlider.value = 1;
            if (speedDisplay) speedDisplay.textContent = '1x';
            
            // 初始化边界大小,确保大于初始视域
            initializeBoundarySize();
            
            // 如果是随机边界,重新生成
            if (simulationState.boundaryType === 'random') {
                generateRandomBoundary();
            }
            
            for (var typeId in simulationState.ballTypes) {
                if (simulationState.ballTypes.hasOwnProperty(typeId)) {
                    if (!simulationState.ballTypes[typeId].affinities) {
                        simulationState.ballTypes[typeId].affinities = [];
                    }
                }
            }
            
            clearCanvas();
            
            // 获取全局数量设置
            var globalCount = 10; // 默认值
            var globalCountInput = document.getElementById('globalCountInput');
            if (globalCountInput) {
                globalCount = parseInt(globalCountInput.value);
                if (isNaN(globalCount) || globalCount <= 0) {
                    globalCount = 10;
                }
                // 确保全局数量应用到所有球类型
                if (simulationState.ballTypes) {
                    for (var ballTypeId in simulationState.ballTypes) {
                        simulationState.ballTypes[ballTypeId].defaultCount = globalCount;
                    }
                }
            }
            
            for (var typeId in simulationState.ballTypes) {
                if (simulationState.ballTypes.hasOwnProperty(typeId)) {
                    var color = typeId;
                    // 使用全局设置的数量
                    var count = globalCount;
                    
                    if (typeof window.addBalls === 'function') {
                        window.addBalls(color, count);
                    } else {
                        var errorMsg = '添加球时出错: addBalls函数未定义';
                        console.error(errorMsg);
                        var problemsDiagnostics = document.getElementById('problems_and_diagnostics');
                        if (problemsDiagnostics) {
                            problemsDiagnostics.innerHTML = '<span style="color: red;">错误: ' + errorMsg + '</span>';
                        }
                    }
                }
            }
        }

        // 事件监听器
        startBtn.addEventListener('click', function() {
            simulationState.isRunning = true;
        });

        pauseBtn.addEventListener('click', function() {
            simulationState.isRunning = false;
        });

        resetBtn.addEventListener('click', resetSimulation);

        addBallsBtn.addEventListener('click', function() {
            try {
                if (!simulationState) {
                    console.error('模拟状态未初始化');
                    return;
                }
                
                var color = simulationState.selectedColor;
                if (!color) {
                    console.error('未选择颜色');
                    return;
                }
                
                var typeId = color;
                
                // 优先使用全局数量控制输入框的值
                var count = 10; // 默认值
                var globalCountInput = document.getElementById('globalCountInput');
                if (globalCountInput) {
                    count = parseInt(globalCountInput.value);
                    // 确保数量有效
                    if (isNaN(count) || count <= 0) {
                        count = 10;
                    }
                }
                
                // 将全局数量应用到所有球类型
                if (globalCountInput && simulationState.ballTypes) {
                    for (var ballTypeId in simulationState.ballTypes) {
                        simulationState.ballTypes[ballTypeId].defaultCount = count;
                    }
                }
                
                if (!isNaN(count) && count > 0) {
                    if (typeof window.addBalls === 'function') {
                        window.addBalls(color, count);
                    } else {
                        var errorMsg = '添加球时出错: addBalls函数未定义';
                        console.error(errorMsg);
                        var problemsDiagnostics = document.getElementById('problems_and_diagnostics');
                        if (problemsDiagnostics) {
                            problemsDiagnostics.innerHTML = '<span style="color: red;">错误: ' + errorMsg + '</span>';
                        }
                    }
                    
                    onBallTypeAdded(typeId);
                    
                    if (typeof clearCanvas === 'function') {
                        clearCanvas();
                        if (ctx && typeof ctx.save === 'function') {
                            ctx.save();
                            var offsetX = 0;
                            var offsetY = 0;
                            if (simulationState.viewOffset) {
                                offsetX = simulationState.viewOffset.x || 0;
                                offsetY = simulationState.viewOffset.y || 0;
                            }
                            ctx.translate(offsetX, offsetY);
                            if (Array.isArray(simulationState.balls)) {
                                for (var i = 0; i < simulationState.balls.length; i++) {
                                    var ball = simulationState.balls[i];
                                    if (ball && typeof ball.draw === 'function') {
                                        ball.draw();
                                    }
                                }
                            }
                            ctx.restore();
                        }
                    }
                }
            } catch (error) {
                console.error('添加球时出错:', error);
            }
        });

        // 视图拖动功能
        canvas.addEventListener('mousedown', function(e) {
            var rect = canvas.getBoundingClientRect();
            simulationState.isDragging = true;
            simulationState.lastMousePos = {
                x: e.clientX - rect.left,
                y: e.clientY - rect.top
            };
            e.preventDefault();
        });
        
        document.addEventListener('mousemove', function(e) {
            if (simulationState.isDragging) {
                var rect = canvas.getBoundingClientRect();
                var currentX = e.clientX - rect.left;
                var currentY = e.clientY - rect.top;
                
                var dx = currentX - simulationState.lastMousePos.x;
                var dy = currentY - simulationState.lastMousePos.y;
                
                simulationState.viewOffset.x += dx;
                simulationState.viewOffset.y += dy;
                
                simulationState.lastMousePos = { x: currentX, y: currentY };
            }
        });
        
        document.addEventListener('mouseup', function() {
            simulationState.isDragging = false;
        });
        
        document.addEventListener('mouseleave', function() {
            simulationState.isDragging = false;
        });
        
        // 边界类型选择事件监听
        const boundaryTypeSelect = document.getElementById('boundaryType');
        if (boundaryTypeSelect) {
            boundaryTypeSelect.addEventListener('change', function() {
                simulationState.boundaryType = this.value;
            });
        }
        
        // 滚轮缩放功能
        canvas.addEventListener('wheel', function(e) {
            e.preventDefault();
            
            var rect = canvas.getBoundingClientRect();
            var mouseX = e.clientX - rect.left;
            var mouseY = e.clientY - rect.top;
            
            // 缩放前的鼠标位置(世界坐标)
            var worldX = (mouseX - canvas.width / 2 - simulationState.viewOffset.x) / simulationState.viewScale + canvas.width / 2;
            var worldY = (mouseY - canvas.height / 2 - simulationState.viewOffset.y) / simulationState.viewScale + canvas.height / 2;
            
            // 计算缩放因子
            var scaleFactor = e.deltaY > 0 ? 0.9 : 1.1;
            var newScale = simulationState.viewScale * scaleFactor;
            
            // 限制缩放范围
            newScale = Math.max(0.1, Math.min(5.0, newScale));
            simulationState.viewScale = newScale;
            
            // 调整偏移量,使鼠标指向的点在缩放后保持不变
            simulationState.viewOffset.x = mouseX - canvas.width / 2 - (worldX - canvas.width / 2) * newScale;
            simulationState.viewOffset.y = mouseY - canvas.height / 2 - (worldY - canvas.height / 2) * newScale;
        });
        
        // 速度控制事件监听
        const speedSlider = document.getElementById('speedSlider');
        const speedDisplay = document.getElementById('speedDisplay');
        
        if (speedSlider && speedDisplay) {
            speedSlider.addEventListener('input', function() {
                simulationState.speedMultiplier = parseInt(this.value);
                speedDisplay.textContent = simulationState.speedMultiplier + 'x';
            });
        }
        
        // 重置模拟时重置速度和缩放
        const originalResetSimulation = resetSimulation;
        resetSimulation = function() {
            originalResetSimulation();
            simulationState.speedMultiplier = 1;
            simulationState.viewScale = 1.0;
            if (speedSlider) speedSlider.value = 1;
            if (speedDisplay) speedDisplay.textContent = '1x';
        };
        
        // 边界碰撞检测函数
        function checkBoundaryCollision(ball) {
            if (!ball) return;
            
            const centerX = canvas.width / 2;
            const centerY = canvas.height / 2;
            const ballRadius = ball.radius || 2;
            
            switch(simulationState.boundaryType) {
                case 'circle':
                    // 圆形边界碰撞检测
                    const dx = ball.x - centerX;
                    const dy = ball.y - centerY;
                    const distance = Math.sqrt(dx * dx + dy * dy);
                    const maxDistance = simulationState.boundaryRadius - ballRadius;
                    
                    if (distance > maxDistance) {
                        // 计算碰撞后的反弹
                        const angle = Math.atan2(dy, dx);
                        ball.x = centerX + Math.cos(angle) * maxDistance;
                        ball.y = centerY + Math.sin(angle) * maxDistance;
                        
                        // 反弹速度计算
                        const normalX = dx / distance;
                        const normalY = dy / distance;
                        const dotProduct = ball.vx * normalX + ball.vy * normalY;
                        
                        ball.vx = (ball.vx - 2 * dotProduct * normalX) * 0.8; // 0.8是弹性系数
                        ball.vy = (ball.vy - 2 * dotProduct * normalY) * 0.8;
                    }
                    break;
                    
                case 'square':
                    // 方形边界碰撞检测
                    const halfWidth = simulationState.boundarySize.width / 2;
                    const halfHeight = simulationState.boundarySize.height / 2;
                    const leftBound = centerX - halfWidth + ballRadius;
                    const rightBound = centerX + halfWidth - ballRadius;
                    const topBound = centerY - halfHeight + ballRadius;
                    const bottomBound = centerY + halfHeight - ballRadius;
                    
                    // X方向碰撞
                    if (ball.x < leftBound) {
                        ball.x = leftBound;
                        ball.vx = -ball.vx * 0.8;
                    } else if (ball.x > rightBound) {
                        ball.x = rightBound;
                        ball.vx = -ball.vx * 0.8;
                    }
                    
                    // Y方向碰撞
                    if (ball.y < topBound) {
                        ball.y = topBound;
                        ball.vy = -ball.vy * 0.8;
                    } else if (ball.y > bottomBound) {
                        ball.y = bottomBound;
                        ball.vy = -ball.vy * 0.8;
                    }
                    break;
                    

                    

            }
        }
        
        // 检测线段与圆的碰撞
        function checkLineCircleCollision(p1, p2, ball) {
            const ballRadius = ball.radius || 2;
            
            // 计算线段向量
            const lineVecX = p2.x - p1.x;
            const lineVecY = p2.y - p1.y;
            
            // 计算球到线段起点的向量
            const circleToLineStartX = ball.x - p1.x;
            const circleToLineStartY = ball.y - p1.y;
            
            // 计算投影长度
            const lineLengthSq = lineVecX * lineVecX + lineVecY * lineVecY;
            const dotProduct = circleToLineStartX * lineVecX + circleToLineStartY * lineVecY;
            const projection = Math.max(0, Math.min(1, dotProduct / lineLengthSq));
            
            // 计算投影点
            const projectionX = p1.x + projection * lineVecX;
            const projectionY = p1.y + projection * lineVecY;
            
            // 计算球到投影点的距离
            const dx = ball.x - projectionX;
            const dy = ball.y - projectionY;
            const distance = Math.sqrt(dx * dx + dy * dy);
            
            if (distance <= ballRadius) {
                // 计算法线向量(单位向量)
                const normalX = dx / distance;
                const normalY = dy / distance;
                
                // 计算反弹后的速度
                const dotProductWithNormal = ball.vx * normalX + ball.vy * normalY;
                const reflectX = ball.vx - 2 * dotProductWithNormal * normalX;
                const reflectY = ball.vy - 2 * dotProductWithNormal * normalY;
                
                return { collided: true, normalX, normalY, reflectX, reflectY };
            }
            
            return { collided: false };
        }
        
        // 初始化边界大小,确保明显大于页面加载时的视域
        function initializeBoundarySize() {
            const centerX = canvas.width / 2;
            const centerY = canvas.height / 2;
            
            // 设置边界大小为初始视域的2倍,确保明显大于页面首次加载时的视域
            const boundaryMultiplier = 2.0;
            
            // 更新圆形边界半径
            const maxViewportSize = Math.max(canvas.width, canvas.height);
            simulationState.boundaryRadius = (maxViewportSize / 2) * boundaryMultiplier;
            
            // 更新方形边界大小
            simulationState.boundarySize = {
                width: canvas.width * boundaryMultiplier,
                height: canvas.height * boundaryMultiplier
            };
            

        }
        

        

        
        // 绘制边界
        function drawBoundary() {
            if (!ctx) return;
            
            ctx.save();
            ctx.strokeStyle = 'rgba(74, 124, 255, 0.7)';
            ctx.lineWidth = 2;
            
            const centerX = canvas.width / 2;
            const centerY = canvas.height / 2;
            
            switch(simulationState.boundaryType) {
                case 'circle':
                    // 绘制圆形边界
                    ctx.beginPath();
                    ctx.arc(centerX, centerY, simulationState.boundaryRadius, 0, Math.PI * 2);
                    ctx.stroke();
                    break;
                    
                case 'square':
                    // 绘制方形边界
                    const halfWidth = simulationState.boundarySize.width / 2;
                    const halfHeight = simulationState.boundarySize.height / 2;
                    ctx.strokeRect(
                        centerX - halfWidth,
                        centerY - halfHeight,
                        simulationState.boundarySize.width,
                        simulationState.boundarySize.height
                    );
                    break;
                    

                    

            }
            
            ctx.restore();
        }
        
        // 初始化动画循环
        animate();
    </script>
</body>
</html>

【元胞自动机】基于元胞自动机模拟生命演化、病毒感染等实例附matlab代码 ​元胞自动机,也叫细胞自动机,是一种离散模型。散布在规则格网(LatticeGrid)中的每一元胞(Cell)取有限的离散状态,遵循同样的作用规则,依据确定的局部规则作同步更新。大量元胞通过简单的相互作用而构成动态系统的演化。不同于一般的动力学模型,元胞自动机不是由严格定义的物理方程或函数确定,而是用一系列模型构造的规则构成。凡是满足这些规则的模型都可以算作是元胞自动机模型。因此,元胞自动机是一类模型的总称,或者说是一个方法框架。​clear;closeall;clc;​​​。......... 阅读详情

相关推荐

MATLAB算法实战应用案例精讲-【数模应用】元胞自动机生命游戏(附Java、Python、C语言、C++和MATLAB代码实现)

生命游戏生命游戏其实是一个零玩家游戏,它包括一个二维矩形世界,这个世界中的每个方格居住着一个活着的或死了的细胞。一个细胞在下一个时刻生死取决于相邻八个方格中活着的或死了的细胞的数量。如果相邻方格活着的细胞数量过多,这个细胞会因为资源匮乏而在下一个时刻死去;相反,如果周围活细胞过少,这个细胞会因太孤单而死去。实际中,你可以设定周围活细胞的数目怎样时才适宜该细胞的生存。如果这个数目设定过高,世界中的大部分细胞会因为找不到太多的活的邻居而死去,直到整个世界都没有生命;

qq_36130719的博客 1321

用生命游戏代码探索细胞自动机的魅力

这篇文章将带您进入令人着迷的细胞自动机世界。我们将研究并玩转一款经典的细胞自动机游戏——“生命游戏”(Game of Life)。通过介绍并解读一段C语言代码,我们将了解生命游戏的规则和演化过程。同时,我们还会添加一些代码注释,使代码更易读和理解。准备好一起探索细胞自动机的魅力吧!

cytingle 513

机器视觉:9点标定的原理与实现

标定就是将机器视觉处理得到的像素坐标转换成实际项目中使用到的毫米坐标。简单说即使看看实际单位距离内有几个像素,如下图所示,10mm的距离内有222个像素,那像素坐标和实际的毫米坐标就有个比例关系了。

m0_49968063的博客 1万+

c++ 45行代码实现 生命游戏-细胞自动机!!!

概念:自动运行的机器 大家知道细胞自动机这个东西吗?当年冯诺依曼发明了计算机,同时也提出了一个概念:有一种机器,只要人为事先设定好,便可以一直自行地执行下去。可惜他早逝,52岁便被癌症带往天堂,到真正实现就要到那个人了:约翰.康威。他发明了一款连他自己也想不到其影响的游戏,即生命游戏,现在就是我们的细胞自动机。接下来,来看一下ta的运行规则吧。 运行规则: 很简单,也很好理解: 这是一个只有细胞元的世界,每个细胞元占一格,且只有生与死两种状态; 现在时刻的状态由上一步骤决定; 状态变化的规则1:如果一个生

S_JH330206的博客 1067

Oracle 11g RAC 节点通信故障排查与修复指南

本文详细介绍了Oracle 11g RAC集群发生节点通信故障时的系统性排查与修复方法。当出现节点异常重启时,核心问题往往源于心跳网络中断。文章提供了从快速诊断、日志分析到六层深度检查的完整指南,并给出了针对网络配置、内核参数及Oracle已知Bug等常见根因的实战解决方案,帮助DBA快速恢复集群稳定。

weixin_29246195的博客 273

【Macbook-Latex安装部署教程】【Win-Texlive镜像下载】【简单易上手】MacTex+Vscode/Texstudio

该教程记录自己在mac()上安装部署Latex环境的经验,整个教程操作简单,配置要求少,易上手。教程分成三部分:Mactex下载与安装,Vscode插件下载与配置文件修改,Texstudio安装。

sunriseOvO的博客 2568

100行python代码实现细胞自动机(康威生命游戏)

用python实现细胞自动机(康威生命游戏)

weixin_49775731的博客 3507

vue:npm安装pnpm报错,npm ERR! code ENOTFOUND,npm ERR! syscall getaddrinfo,npm ERR! errno ENOTFOUND详细排查解决!

vue2 vue3,npm install -g pnpm 安装出现错误,安装pnpm及解决安装失败问题,解决 npm无法安装pnpm问题,npm 安装 pnpm 时 报错 npm ERR! code ENOTFOUND,pnpm无法安装报错,vue npm install -g pnpm安装报错,request to http://registry.cnpmjs.org/pnpm failed, reason: getaddrinfo ENOTFOUND registry.cnpmjs.org,安装pnp

✅ 精选推荐文章 3608

元胞自动机模型代码实现:从生命游戏到工业仿真

元胞自动机是一种基于局部规则、全局涌现的离散动力系统建模方法,其核心在于用简单状态更新机制刻画复杂时空演化过程。原理上依赖网格拓扑、邻居关系与状态转移规则三要素协同;技术价值体现在轻量级、可解释、易扩展,无需深度学习框架即可支撑多物理场耦合仿真。典型应用场景包括交通流建模、火灾蔓延模拟、晶圆缺陷传播等工程问题。本文聚焦‘元胞自动机’与‘模型代码实现’两大关键环节,提供可调试、可验证、支持异步调度与自定义拓扑的生产级Python实现框架,兼顾新手入门与科研落地需求。

weixin_29052717的博客 314

llama-factory微调qwen2.5-vl

使用llama-factory完成qwen2.5-vl微调

qq_44908396的博客 2933

一文读懂 SAP BTP Application Router 的 Resource Files:从 xs-app.json 到本地开发的默认设置

本文详解SAP BTP中Application Router的资源文件配置与本地开发实践。核心包括:xs-app.json定义路由规则与安全策略,package.json声明依赖与启动脚本,resources/存放静态资源,default-services.json和local-destinations.json用于本地模拟云服务。文章通过真实案例展示如何配置静态资源直出、反向代理后端服务,并强调本地开发时的注意事项与常见问题解决路径。关键配置均提供示例代码,帮助开发者快速实现业务应用的部署与联调。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 177

元胞自动机CA+生命游戏代码

1、元胞自动机 元胞自动机(Cellular Automaton,复数为Cellular Automata,简称CA,也有人译为细胞自动机、点格自动机、分子自动机或单元自动机)。是一时间和空间都离散的动力系统。散布在规则格网 (Lattice Grid)中的每一元胞(Cell)取有限的离散状态,遵循同样的作用规则,依据确定的局部规则作同步更新。大量元胞通过简单的相互作用而构成动态系统的演化。 ...

森的博客 2599

Python 爬虫实战:爬取豆瓣电影 Top250 完整数据

本文基于Python技术实现了豆瓣电影Top250榜单数据的合规爬取与分析。针对豆瓣电影页面的分页结构、反爬机制等特点,采用requests库获取数据,结合BeautifulSoup解析HTML节点,并通过正则表达式提取电影名称、评分、导演等核心字段。爬虫实现了随机User-Agent、请求间隔控制等反爬规避策略,严格遵守豆瓣社区使用规范。最终数据经清洗后存储为结构化Excel文件,并提供了数据可视化与增量更新方案。该方案为影视研究提供了可靠的数据获取方法,同时确保符合非商业使用、适度爬取等合规要求。

2503_91057718的博客 3460

细胞生命游戏c语言代码,细胞自动机之生命游戏

该楼层疑似违规已被系统折叠隐藏此楼查看此楼#include #include #include #define N 50#define M 50void tv_1(_Bool arr[][M]){for(int x=0;x{for(int y=0;y{putchar(arr[x][y]?'0':' ');}putchar(10);}}void tv_2(_Bool arr[][M]){for(i...

weixin_39528029的博客 169

uni-app - 刘海屏(Iphone X)底部横杠(——)白色区域块(安全距离处更改颜色)解决方案

场景:因为要做无tabbar页面,所以在配置文件中取消底部导航栏。取消后,iPhoneX(刘海屏)底部就出现如下图所示白色安全区域问题:这个问题,是因为uni-app默认会为iPhoneX(刘海屏)留出安全距离,这个安全距离的背景色就是白色。所以,如果你将页面颜色设置为其他颜色,就会与默认白色冲突。有2个不同的解决方案(原生占位),虽然原理是一样,但使用的场景不同,请根据您的需求来采纳。

🏆 前端领域优质创作者 1万+

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

c语言 细胞自动机(生命游戏)代码

#include <stdio.h> #include <stdlib.h> #include <windows.h> #include <time.h> int main(){ int i, j, k = 0, cal = 0, c=0; char map[57][75]; int l1[2000],r1[2000],l2[2000],r2[2000]; FILE *fl; char test[5]; srand((unsigned int

qq_21773503的博客 706

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

二维元胞自动机c语言代码,C语言借助EasyX实现的生命游戏源码

本文讲述C语言借助EasyX实现的生命游戏,具体操作流程如下:1.生命游戏内容:该游戏包括一个二维矩形世界,这个世界中的每个方格居住着一个活着的或死了的细胞。一个细胞在下一个时刻生死取决于相邻八个方格中活着的细胞的数量。如果一个细胞周围的活细胞数量多于 3 个,这个细胞会因为资源匮乏而在下一个时刻死去;如果一个位置周围有 3 个活细胞,则该位置在下一个时刻将诞生一个新的细胞;如果一个位置周围有 2...

weixin_29064103的博客 465

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

用Python实现元胞自动机:从生命游戏到交通流模拟(附完整代码)

本文详细介绍了如何使用Python实现元胞自动机,从经典的康威生命游戏到一维交通流模拟。通过搭建通用框架、应用向量化优化和Numba加速等技巧,文章提供了完整的代码示例,帮助读者理解复杂系统的涌现行为,并掌握高效的数学建模与仿真方法。

algae的博客 474

康威生命游戏/元胞自动机完整代码

【代码】康威生命游戏/元胞自动机完整代码。

weixin_63033294的博客 190

生命游戏代码_生命游戏Life Game(耿祥义讲解)

源代码:https://pan.baidu.com/s/1kd4v84NuCIzErHtr3RUYDA源代码带运行环境:https://pan.baidu.com/s/1j17xeqS_Lhswn7XpVkI66g生命游戏-Life Game● 生命游戏是英国数学家约翰·何顿·康威在1970年发明的细胞自动机。● 生命游戏属于二维细胞自动机的一种(又称二维元胞自动机) ○每一个格子都...

weixin_39928818的博客 693

生命游戏的简单实现(c++代码)

一、生命游戏生命游戏(Game of Life, 简称生命)是 John Conway 于 1970 年发明的生命游戏不是通常意义上的游戏,没有游戏者,也无所谓胜负生命游戏是一类特殊的细胞自动机一旦给定初始状态,之后的发展完全由规则确定生命充满了悬念!绝大多数情况下,不可能只根据初始状态(或称模式)判断未来的发展,只能按照游戏的规则运行下去实现起来还是非常有趣且简单的!!

Mr_Fmnwon的博客 3759

瘟疫建模前期调研之二——生命游戏

目录 原理简介 作品展示 代码演示 一、原理简介 1.生命游戏是什么? (1) 简单地来说,生命游戏其实是一个拓展的细胞自动机。如果不了解细胞自动机的话可以看我写的这个系列的第一篇文章。在之前的细胞自动机中,细胞的初始状态是一行细胞,而生成的细胞是它的下一代,而上一代的细胞我们是进行了保留的。所以上下代都显示在了屏幕上。 (2) 而生命游戏中,也分二维和三维,这里我以二维生命游戏举例:初始细胞...

Program_dancing的博客 1153

用Go实现生命游戏:从零开始构建细胞自动机模拟器(附完整代码解析)

本文详细介绍了如何使用Go语言从零开始构建生命游戏(Conway's Game of Life)模拟器,包括核心数据结构设计、状态更新、双缓冲技术、并行计算优化等关键实现步骤。通过完整的代码解析和性能优化技巧,帮助开发者掌握细胞自动机模拟的实现方法,并探讨了进一步扩展的方向。

9o8p7i6u5y的博客 433

【元胞自动机】元胞自动机图像处理【含Matlab源码 234期 】

元胞自动机图像处理 完整的代码,方可运行;可提供运行操作视频!适合小白!

订阅付费专栏Matlab(奶茶价版)或下载付费资源,可赠送奶茶价版付费专栏指定代码1份; 931
上一篇: 对销售和营销的思考
code_ent
博客等级 码龄4年 316粉丝 19原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值