JavaScript Canvas 实现生命游戏:从 0 到 1 构建 100x100 网格交互式模拟器

发布时间:2026/11/4 16:13:57

JavaScript Canvas 实现生命游戏:从 0 到 1 构建 100x100 网格交互式模拟器 JavaScript Canvas 实现生命游戏从 0 到 1 构建 100x100 网格交互式模拟器生命游戏Game of Life是英国数学家约翰·康威在1970年提出的一种细胞自动机模型。它通过简单的规则模拟了生命的繁衍、死亡和演化过程。本文将带你从零开始使用原生JavaScript和Canvas API构建一个高性能的100x100网格生命游戏模拟器并深入探讨性能优化技巧。1. 生命游戏基础与规则解析生命游戏在一个二维网格上进行每个格子代表一个细胞细胞有两种状态存活1或死亡0。游戏的演化遵循以下四条简单规则孤单死亡如果一个存活细胞的邻居少于2个它在下一代将死亡稳定存活如果一个存活细胞有2或3个邻居它将保持存活过度拥挤如果一个存活细胞有超过3个邻居它在下一代将死亡繁殖如果一个死亡细胞恰好有3个邻居它在下一代将变为存活状态在JavaScript中我们可以用一个二维数组来表示细胞状态const grid Array(100).fill().map(() Array(100).fill(0));邻居指的是每个细胞周围8个相邻细胞上、下、左、右及四个对角线方向。计算邻居数量的函数可以这样实现function countNeighbors(grid, x, y) { let sum 0; const rows grid.length; const cols grid[0].length; for (let i -1; i 2; i) { for (let j -1; j 2; j) { if (i 0 j 0) continue; const row (x i rows) % rows; const col (y j cols) % cols; sum grid[row][col]; } } return sum; }注意这里使用了模运算处理边界条件使得网格在逻辑上是环状的即最左边的细胞与最右边的细胞相邻2. Canvas 基础实现Canvas API提供了强大的2D绘图能力非常适合实现生命游戏的图形渲染。以下是基础实现步骤2.1 初始化Canvas首先在HTML中添加Canvas元素canvas idgameCanvas width500 height500/canvas然后获取Canvas上下文并设置初始参数const canvas document.getElementById(gameCanvas); const ctx canvas.getContext(2d); const cellSize 5; // 每个细胞占5x5像素 const rows 100; const cols 100;2.2 绘制网格我们可以使用Canvas的fillRect方法绘制细胞function drawGrid(grid) { ctx.clearRect(0, 0, canvas.width, canvas.height); for (let i 0; i rows; i) { for (let j 0; j cols; j) { ctx.fillStyle grid[i][j] ? #000000 : #FFFFFF; ctx.fillRect(j * cellSize, i * cellSize, cellSize, cellSize); } } }2.3 实现游戏循环使用requestAnimationFrame实现游戏的主循环function gameLoop() { updateGrid(); drawGrid(grid); requestAnimationFrame(gameLoop); } function updateGrid() { const newGrid grid.map(arr [...arr]); for (let i 0; i rows; i) { for (let j 0; j cols; j) { const neighbors countNeighbors(grid, i, j); // 应用生命游戏规则 if (grid[i][j] 1) { newGrid[i][j] (neighbors 2 || neighbors 3) ? 1 : 0; } else { newGrid[i][j] neighbors 3 ? 1 : 0; } } } // 更新网格 for (let i 0; i rows; i) { for (let j 0; j cols; j) { grid[i][j] newGrid[i][j]; } } }3. 性能优化策略当网格尺寸增大到100x100时基础实现可能会遇到性能瓶颈。以下是几种有效的优化方法3.1 双缓冲技术直接在原网格上更新会导致闪烁效果且效率不高。双缓冲技术使用两个网格let currentGrid createEmptyGrid(); let nextGrid createEmptyGrid(); function updateGrid() { for (let i 0; i rows; i) { for (let j 0; j cols; j) { const neighbors countNeighbors(currentGrid, i, j); // 应用规则到nextGrid if (currentGrid[i][j] 1) { nextGrid[i][j] (neighbors 2 || neighbors 3) ? 1 : 0; } else { nextGrid[i][j] neighbors 3 ? 1 : 0; } } } // 交换网格 [currentGrid, nextGrid] [nextGrid, currentGrid]; }3.2 位运算优化使用位运算可以显著提升邻居计算速度function countNeighborsBitwise(grid, x, y) { let sum 0; const rows grid.length; const cols grid[0].length; // 使用位运算优化 sum grid[(x-1rows)%rows][(y-1cols)%cols] 1; sum grid[(x-1rows)%rows][y] 1; sum grid[(x-1rows)%rows][(y1)%cols] 1; sum grid[x][(y-1cols)%cols] 1; sum grid[x][(y1)%cols] 1; sum grid[(x1)%rows][(y-1cols)%cols] 1; sum grid[(x1)%rows][y] 1; sum grid[(x1)%rows][(y1)%cols] 1; return sum; }3.3 增量更新只更新发生变化的细胞区域而不是整个网格function drawChanges(grid, prevGrid) { for (let i 0; i rows; i) { for (let j 0; j cols; j) { if (grid[i][j] ! prevGrid[i][j]) { ctx.fillStyle grid[i][j] ? #000000 : #FFFFFF; ctx.fillRect(j * cellSize, i * cellSize, cellSize, cellSize); } } } }4. 交互功能实现一个完整的生命游戏模拟器需要提供用户交互功能4.1 鼠标交互允许用户通过点击来设置初始细胞状态canvas.addEventListener(click, (e) { const rect canvas.getBoundingClientRect(); const x Math.floor((e.clientX - rect.left) / cellSize); const y Math.floor((e.clientY - rect.top) / cellSize); grid[y][x] grid[y][x] ? 0 : 1; drawGrid(grid); });4.2 控制面板添加控制按钮和参数调节div classcontrols button idstartBtn开始/button button idstopBtn停止/button button idclearBtn清空/button button idrandomBtn随机/button label速度input typerange idspeed min10 max500/label /div对应的JavaScript控制逻辑let animationId null; let speed 100; document.getElementById(startBtn).addEventListener(click, () { if (!animationId) { gameLoop(); } }); document.getElementById(stopBtn).addEventListener(click, () { cancelAnimationFrame(animationId); animationId null; }); document.getElementById(clearBtn).addEventListener(click, () { grid.forEach(row row.fill(0)); drawGrid(grid); }); document.getElementById(randomBtn).addEventListener(click, () { for (let i 0; i rows; i) { for (let j 0; j cols; j) { grid[i][j] Math.random() 0.7 ? 1 : 0; } } drawGrid(grid); }); document.getElementById(speed).addEventListener(input, (e) { speed 510 - e.target.value; // 反转值使滑块右侧为更快 });4.3 预设模式添加一些著名的生命游戏模式如滑翔机、脉冲星等const patterns { glider: [ [0, 1, 0], [0, 0, 1], [1, 1, 1] ], blinker: [ [1, 1, 1] ], // 更多模式... }; function placePattern(grid, pattern, x, y) { for (let i 0; i pattern.length; i) { for (let j 0; j pattern[0].length; j) { const row (y i) % rows; const col (x j) % cols; grid[row][col] pattern[i][j]; } } }5. 高级主题与扩展5.1 Web Workers 多线程计算对于更大的网格可以将计算任务分配给Web Worker// main.js const worker new Worker(game-worker.js); worker.onmessage function(e) { grid e.data; drawGrid(grid); }; function startWorker() { worker.postMessage({ command: start, grid: grid, speed: speed }); } // game-worker.js self.onmessage function(e) { if (e.data.command start) { setInterval(() { const newGrid computeNextGeneration(e.data.grid); self.postMessage(newGrid); }, e.data.speed); } }; function computeNextGeneration(grid) { // 计算下一代... return newGrid; }5.2 着色器加速WebGL使用WebGL和GLSL着色器可以实现硬件加速// 创建WebGL上下文 const glCanvas document.createElement(canvas); const gl glCanvas.getContext(webgl); // 编写片元着色器 const fragmentShaderSource precision highp float; uniform sampler2D u_texture; uniform vec2 u_resolution; void main() { vec2 uv gl_FragCoord.xy / u_resolution; vec3 color texture2D(u_texture, uv).rgb; // 实现生命游戏规则的GLSL代码... gl_FragColor vec4(color, 1.0); } ;5.3 性能对比测试不同实现方式的性能对比方法100x100 FPS500x500 FPS内存使用基础实现302低双缓冲453中位运算605低WebWorker558高WebGL6060高5.4 保存与加载状态实现游戏状态的保存和加载功能function saveState() { const flatGrid grid.flat(); localStorage.setItem(gameState, JSON.stringify(flatGrid)); } function loadState() { const saved localStorage.getItem(gameState); if (saved) { const flatGrid JSON.parse(saved); for (let i 0; i rows; i) { for (let j 0; j cols; j) { grid[i][j] flatGrid[i * cols j]; } } drawGrid(grid); } }通过以上步骤我们构建了一个完整的、高性能的生命游戏模拟器。从基础实现到各种优化技巧这个项目不仅展示了Canvas的强大功能也体现了算法优化在前端开发中的重要性。
延伸阅读

更多相关文章

2026/11/4 15:43:32

离线语音识别芯片|智能离线语音SoC芯片语音识别方案

在智能硬件快速普及的当下,语音交互已成为设备智能化的核心配置。相较于传统依赖云端传输的在线语音方案,离线语音识别芯片凭借无需联网、响应极速、隐私性强的优势,成为各类终端设备的优选核心器件。英尚微电子代理的智芯科AT600系列智能离线…

2026/10/30 21:12:09

跨境电商分销直销系统:多语言融合的全球销售引擎

1. 引言:跨境电商分销与直销的数字化融合在全球电商市场持续扩张的背景下,跨境电商企业面临着渠道多元化、市场本地化与运营效率提升的多重挑战。传统的单一销售模式已难以满足全球化竞争需求,分销(Distribution)与直销…

2026/10/31 0:04:54

lv lü (AI)

视频:20260713-203024 (不懂就问AI)公共资源或者图标被个体或企业独占会有什么后果(商标流氓) 老祖宗的审美在线的,要爱护自己的文化,要充满自信。 下面这个茅厕取自朋友圈,挺好的。一个人、企业…

2026/11/5 13:55:19

GD32E10x官方例程入门:从GPIO点灯到串口调试

简介:这份GD32E10x系列官方例程面向嵌入式硬件与单片机开发者,基于ARM Cortex-M3内核,汇集兆易创新GD32E10x的示例代码,适合工业控制、消费电子、通信设备等场景的学习、验证与二次开发。压缩包共935个文件,约11.16MB&…

2026/11/5 13:50:18

基于Django的运维平台实战:资产、发布、巡检、告警一体化

简介:这份资源是一套基于Django框架开发的运维平台源码,面向具备Python基础、希望了解Web运维系统实现思路的开发者与运维人员,可用于学习主机管理、服务监控、日志查看、任务调度、权限控制、资源统计、脚本执行与故障告警等常见运维模块的落…

2026/11/5 13:25:11

基于ADS122U04IPWR与STM32F427ZI的工业测温方案设计

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/5 13:20:10

Dubbo服务下线实时告警:基于ZooKeeper Watch的轻量级监控方案

简介:这是一套面向Java分布式系统运维与开发人员的Dubbo服务高可用监控解决方案,聚焦于Provider异常下线的实时感知与告警响应。资源通过Zookeeper监听机制实现服务状态变更捕获,结合邮件通知模块,在不侵入原有Dubbo代码的前提下&…

2026/11/5 13:20:10

SSM超市管理系统源码解析:从分层架构到本地部署与业务修改

简介:这份资源是面向高校计算机专业学生与Java初学者的一套SSM框架课程设计完整项目,围绕超市管理场景,帮助读者完成从框架整合到业务模块落地的实战练习,适合作为毕业设计或课程作业的参考方案。压缩包共792个文件,约…

2026/11/5 13:20:10

SSM超市管理系统实战:从课设跑通到二次开发全解析

简介:这份资源是面向高校计算机相关专业学生与Java入门开发者的SSM课程设计参考项目,围绕超市管理场景,解决商品、库存、销售等业务模块从设计到落地的实践需求,适合作为课程作业、毕业设计原型或SSM框架练手案例。压缩包共792个文…

2026/11/4 12:38:23

面向复杂光照与角度的宠物面部识别鲁棒性增强策略

在智慧养宠时代,基于视觉的宠物身份识别技术正逐步从实验室走向家庭应用。然而,与配合度高的人类不同,宠物是典型的“非合作生物识别对象”——它们不会主动配合摄像头调整姿态,更无法控制光照环境。实际应用中,我们常…

2026/11/4 21:04:25

SSM电子书店源码全解析:结构、原理、部署与排错实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/5 0:02:07

多智能体协作系统架构设计与实践优化

1. 多智能体协作系统的时代背景2017年Transformer架构的诞生彻底改变了人工智能的发展轨迹。当行业还沉浸在单一大模型带来的性能突破时,Anthropic的研究团队已经将目光投向了更前沿的领域——如何让多个智能体通过协作产生超越单体能力的系统智能。这就像交响乐团中…

2026/11/5 0:02:07

大模型系统性入门实战指南:从原理到部署微调的全链路路线

提到大模型的系统性入门,我先说个结论:这事真不难,难的是资料太散、路线太多,今天这个框架明天那个工具,新人很容易在“收藏夹吃灰”和“教程看到一半放弃”之间反复横跳。市面上关于大模型的内容少说有几十万篇&#…

2026/11/5 0:02:07

鸿蒙文件系统沙箱机制解析与开发实践

1. 鸿蒙文件系统沙箱机制深度解析作为一名从Android转向鸿蒙开发的工程师,我深刻体会到文件系统访问是迁移过程中最先遇到的"拦路虎"。在Android上运行良好的文件读写代码,在鸿蒙真机环境却频频出现文件写入后神秘消失或直接抛出权限拒绝错误的…

2026/11/4 12:38:23

面向复杂光照与角度的宠物面部识别鲁棒性增强策略

在智慧养宠时代,基于视觉的宠物身份识别技术正逐步从实验室走向家庭应用。然而,与配合度高的人类不同,宠物是典型的“非合作生物识别对象”——它们不会主动配合摄像头调整姿态,更无法控制光照环境。实际应用中,我们常…

2026/11/4 21:04:25

SSM电子书店源码全解析:结构、原理、部署与排错实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑