恒美微站 Logo 恒美微站
  • 首页
  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心
  • 联系我们

用 p5.js 复刻经典扫雷游戏:Minesweeper Coding Challenge 71 源码级实战解析

  • 首页
  • 资讯中心
  • /
  • 用 p5.js 复刻经典扫雷游戏:Minesweeper Coding Challenge 71 源码级实战解析

相关资讯

用 Git 版本控制管理架构决策记录(ADR):从 mkdir 到 Commit 的完整实战 2026/10/12 1:23:44
REA 完整导览:一条命令让编码 Agent 接入本地逆向工程 2026/10/12 1:23:44
Learn-Web-Hacking:Windows 本地认证机制与密码存储全解析(winlogon、lsass、SAM 与 SPNEGO) 2026/10/12 1:23:44

最新资讯

从达美乐第1405家门店看连锁餐饮扩张与单店运营全流程
新唐MCU的ISP(HID)工具详解:C#实现USB HID Bootloader通信
从标题到可落地方案:Selenium动态网页抓取项目拆解全流程
微信扫码登录Spring Boot实现:OAuth2.0授权回调与登录态封装全攻略
DS90UB947 Linux驱动实战:FPD-Link III串行器内核适配与设备树绑定
抖音式上下滑动视频的工程实现与性能避坑指南

今日推荐

Debian新手入门:从部署到日常操作的完整指南
MongoDB复制集扩缩容实战:从rs.add到选主事故复盘
条形码目标检测数据集实战:从YOLOv8训练到部署

本周热门

UE动画修改实战:从资产编辑到重定向与蒙太奇驱动
统计随机数生成器攻击下的KLJN安全密钥交换协议Matlab仿真
政务API安全治理:资产测绘、低代码编排与行标对标实践

本月精选

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证
2026 大模型集体涨价:用 Python 做企业 Token 成本测算与选型避坑(附配置)

用 p5.js 复刻经典扫雷游戏:Minesweeper Coding Challenge 71 源码级实战解析

发布时间:2026/10/12 1:23:44
用 p5.js 复刻经典扫雷游戏:Minesweeper Coding Challenge 71 源码级实战解析 教程文档示例工程【免费下载链接】website-archiveArchive of the Coding Train website (first version)项目地址https://gitcode.com/gh_mirrors/we/website-archive点击查看免费下载导读本文基于 Coding TrainThe Coding Train网站归档仓库中的第 71 号编程挑战文档071-minesweeper.md及其配套源码完整拆解如何用 JavaScript 与 p5.js 库从零实现经典扫雷Minesweeper游戏。文中将覆盖二维数组与对象原型构建棋盘数据结构、随机布雷算法、相邻地雷计数、洪水填充Flood Fill自动展开、鼠标交互与游戏结束判定等核心环节并对照 Processing 移植版本给出跨语言实现要点。读完本文你将掌握一套可直接复制运行的 p5.js 扫雷实现并理解其背后的网格算法设计。挑战背景Coding Challenge #71该挑战发布于 2017 年 5 月 18 日视频编号为 71video_idLFU5ZlrR21E对应仓库为CC_071_minesweeper并配有 p5.js Web Editor 在线草图web_editor-mz-ePoqd。正如原文档所述In this challenge, I attempt to code the classic game Minesweeper in JavaScript with the p5.js library. This video builds on some previous tutorials related to the Prototypes and multi-dimensional arrays in JavaScript.即本挑战使用 p5.js 复刻经典扫雷游戏并建立在 JavaScript 的Prototype原型与二维数组2D Arrays两个前置教程的基础上——分别对应仓库中的 9.19-Prototypes-in-javascript.md 与 9.15-2d-arrays-in-javascript.md。因此本文既是一份扫雷实现指南也是二维数组与原型链在真实游戏项目中的综合演练。仓库中的完整实现分为两个版本p5.js 版本P5/sketch.js、P5/cell.js、P5/index.htmlProcessing 移植版本Processing/CC_071_minesweeper/CC_071_minesweeper.pde、Processing/CC_071_minesweeper/Cell.pde游戏规则与整体设计经典扫雷的规则可以概括为三条棋盘上随机埋设若干地雷本实现中以蜜蜂 bee代指地雷下文沿用源码命名翻开任意格子若该格是雷游戏结束若该格周围 8 个方向存在雷则显示周围雷的数量若周围没有雷则自动递归展开相邻格子玩家通过推理数字与雷的分布最终安全翻开所有非雷格子即获胜本实现未额外实现胜利判定与右键标雷属于基础版。本实现的整体设计非常精简由两部分构成棋盘管理层sketch.js创建二维数组网格、随机布雷、处理鼠标点击、触发游戏结束、驱动逐帧渲染格子对象层cell.js定义单个格子的状态坐标、尺寸、是否雷、是否已翻开、邻雷计数及其绘制、计数、展开行为。棋盘参数在 sketch.js 中集中定义参数值说明w20每个格子的像素边长createCanvas(401, 401)401×401画布尺寸20×20400 边长为 20 的格子留 1px 余量cols/rows由floor(width / w)计算实际网格为 20 列 × 20 行totalBees30总共埋设的地雷数量由于width为 401、w为 20cols floor(401 / 20) 20、rows 20因此棋盘实际是 20×20 400 个格子其中埋设 30 颗雷。数据结构二维数组 Cell 原型对象1. 二维数组工具函数sketch.js 定义了make2DArray用于创建一个cols × rows的二维数组function make2DArray(cols, rows) { var arr new Array(cols); for (var i 0; i arr.length; i) { arr[i] new Array(rows); } return arr; }这里采用外层数组的每个元素再嵌套一个数组的方式形成grid[i][j]的访问结构其中i为列索引水平方向、j为行索引垂直方向。这正是二维数组教程9.15-2d-arrays-in-javascript.md中演示的经典模式。2. Cell 构造函数与原型方法cell.js 定义了Cell构造函数采用 ES5 的原型链Prototype风格——这是本挑战特意演示的 JavaScript 语言特性function Cell(i, j, w) { this.i i; this.j j; this.x i * w; this.y j * w; this.w w; this.neighborCount 0; this.bee false; this.revealed false; }每个格子维护如下状态属性含义i/j格子在网格中的列 / 行索引x/y格子在画布上的像素坐标由索引乘以格子尺寸得到w格子边长neighborCount周围 8 个格子中的地雷数量雷格子记为 -1bee是否为地雷revealed是否已被翻开所有行为方法通过Cell.prototype挂载到原型上包括show、countBees、contains、reveal、floodFill这正是原型教程9.19-Prototypes-in-javascript.md中所讲的通过 prototype 为自定义对象附加方法的实际应用。初始化流程网格创建与随机布雷setup() 完成整个棋盘的初始化分为三步第一步创建网格function setup() { createCanvas(401, 401); cols floor(width / w); rows floor(height / w); grid make2DArray(cols, rows); for (var i 0; i cols; i) { for (var j 0; j rows; j) { grid[i][j] new Cell(i, j, w); } } ... }通过嵌套for循环为每个网格位置grid[i][j]实例化一个Cell。第二步随机布雷无重复选取技巧布雷的关键在于每个位置最多只能埋一颗雷。源码采用了一个优雅的技巧先把所有坐标[i, j]放进一个options数组然后每次随机取出一个下标、放置地雷后立即用splice将该坐标从候选中删除// Pick totalBees spots var options []; for (var i 0; i cols; i) { for (var j 0; j rows; j) { options.push([i, j]); } } for (var n 0; n totalBees; n) { var index floor(random(options.length)); var choice options[index]; var i choice[0]; var j choice[1]; // Deletes that spot so its no longer an option options.splice(index, 1); grid[i][j].bee true; }这种候选池 随机下标 删除已选项的做法等价于从 400 个格子中无放回地抽取 30 个作为雷位避免了重复布雷导致地雷数量不足的隐患。第三步计算所有格子的邻雷数for (var i 0; i cols; i) { for (var j 0; j rows; j) { grid[i][j].countBees(); } }邻域计数countBees 的实现与边界处理cell.js 中的countBees遍历以当前格子为中心的 3×3 邻域xoff、yoff均取 -1、0、1统计其中bee true的格子数量Cell.prototype.countBees function() { if (this.bee) { this.neighborCount -1; return; } var total 0; for (var xoff -1; xoff 1; xoff) { var i this.i xoff; if (i 0 || i cols) continue; for (var yoff -1; yoff 1; yoff) { var j this.j yoff; if (j 0 || j rows) continue; var neighbor grid[i][j]; if (neighbor.bee) { total; } } } this.neighborCount total; };实现要点雷格子的计数约定为 -1方便后续reveal逻辑判断该格是否触发洪水填充同时避免把雷自身计入数字边界守卫if (i 0 || i cols) continue;与if (j 0 || j rows) continue;确保位于棋盘边缘的格子不会越界访问grid这是二维数组遍历中最常见的易错点。渲染show 方法与状态可视化cell.js 的show方法负责绘制每个格子未翻开的格子只画边框翻开的格子根据状态显示内容Cell.prototype.show function() { stroke(0); noFill(); rect(this.x, this.y, this.w, this.w); if (this.revealed) { if (this.bee) { fill(127); ellipse(this.x this.w * 0.5, this.y this.w * 0.5, this.w * 0.5); } else { fill(200); rect(this.x, this.y, this.w, this.w); if (this.neighborCount 0) { textAlign(CENTER); fill(0); text(this.neighborCount, this.x this.w * 0.5, this.y this.w - 6); } } } };未翻开仅描边矩形stroke(0)noFill()呈现待探索状态翻开的雷灰色填充 在格子中心绘制椭圆表示地雷翻开的非雷格浅灰填充fill(200)并在neighborCount 0时居中绘制数字neighborCount 0的格子留白。在 draw() 中每帧先background(255)清屏再通过双重循环调用每个格子的show()function draw() { background(255); for (var i 0; i cols; i) { for (var j 0; j rows; j) { grid[i][j].show(); } } }核心算法reveal 与 floodFill 洪水填充这是扫雷体验的灵魂——点击一个邻雷数为 0 的格子时应自动连锁展开一大片无雷区域。cell.js 的reveal负责翻开当前格子并在neighborCount 0时触发floodFillCell.prototype.reveal function() { this.revealed true; if (this.neighborCount 0) { // flood fill time this.floodFill(); } };cell.js 的floodFill遍历 3×3 邻域对每个未翻开的邻居递归调用reveal从而形成深度优先的连锁展开Cell.prototype.floodFill function() { for (var xoff -1; xoff 1; xoff) { var i this.i xoff; if (i 0 || i cols) continue; for (var yoff -1; yoff 1; yoff) { var j this.j yoff; if (j 0 || j rows) continue; var neighbor grid[i][j]; // Note the neighbor.bee check was not required. // See issue #184 if (!neighbor.revealed) { neighbor.reveal(); } } } };两个值得注意的实现细节递归终止条件floodFill只对!neighbor.revealed的格子调用reveal已被翻开的格子会被跳过从而保证递归必然终止不会无限循环源码注释明确说明不需要判断 neighbor 是否为雷issue #184由于reveal只在neighborCount 0时才触发floodFill而雷格子的neighborCount被置为 -1因此雷格子永远不会作为floodFill的发起者自然也不会被 0 值区域递归展开。这一注释是仓库源码中留给我们理解算法正确性的关键线索。这种中心格为 0 时向四周扩散的算法正是原文档 links 中引用的Flood fill洪水填充算法在扫雷场景下的应用——常用于图像处理与连通区域标记这里是它在网格游戏中的典型落地。交互与胜负判定mousePressed 与 gameOversketch.js 通过 p5.js 的mousePressed回调实现点击翻开function mousePressed() { for (var i 0; i cols; i) { for (var j 0; j rows; j) { if (grid[i][j].contains(mouseX, mouseY)) { grid[i][j].reveal(); if (grid[i][j].bee) { gameOver(); } } } } }命中检测依赖 cell.js 的contains方法Cell.prototype.contains function(x, y) { return x this.x x this.x this.w y this.y y this.y this.w; };即鼠标坐标落在格子像素矩形范围内即视为点击该格。若点中地雷则调用 gameOver() 把整个棋盘全部置为revealed true将所有地雷位置公开展示function gameOver() { for (var i 0; i cols; i) { for (var j 0; j rows; j) { grid[i][j].revealed true; } } }注意点击事件采用遍历全部格子逐个做矩形命中测试的朴素实现。对于 20×20 400 个格子的规模这种方式完全够用若棋盘规模大幅增大可以改用由鼠标坐标直接反推格子索引floor(mouseX / w)的 O(1) 命中方式作为优化方向。运行方式与文件组织p5.js 版本的入口页面是 P5/index.html它通过 CDN 引入 p5.js 并依次加载两个脚本!DOCTYPE html html head script typetext/javascript srchttps://cdn.jsdelivr.net/npm/p51.4.1/lib/p5.min.js/script script typetext/javascript srchttps://cdn.jsdelivr.net/npm/p51.4.1/lib/addons/p5.sound.min.js/script script typetext/javascript srcsketch.js/script script typetext/javascript srccell.js/script /head body /body /html运行方式有两种本地运行将index.html、sketch.js、cell.js三个文件放在同一目录用浏览器直接打开index.html或通过本地静态服务器如python -m http.server访问脚本加载顺序为sketch.js先于cell.js两者均使用全局变量与全局函数协作在线编辑在 p5.js Web Editor 中打开草图web_editor-mz-ePoqd即可在线运行与修改。由于本项目主要依赖 CDN 上的 p5.js 1.4.1运行时需要网络环境加载 p5 库代码本身使用 ES5 语法var、构造函数 原型方法不依赖 ES6 特性兼容性良好。Processing 移植版本对照仓库还提供了与 p5.js 版逻辑完全对应的 Processing 移植版Processing/CC_071_minesweeper/CC_071_minesweeper.pde主程序包含setup、gameOver、mousePressed、draw其中文件头部注释写明Originally written using p5.jsProcessing/CC_071_minesweeper/Processing/CC_071_minesweeper/Cell.pdeCell类定义含show、countBees、contains、reveal、floodFill。两个版本的核心差异在于语言层面的映射概念p5.js 版Processing 版网格声明var grid;make2DArray(cols, rows)Cell[][] grid;对象定义function Cell(...)Cell.prototype.methodclass Cell { ... }布雷候选池var options []options.splice(index, 1)ArrayListint[] optionsoptions.remove(index)画布createCanvas(401, 401)size(401, 401)随机random(n)random(n)可以看出Processing 版几乎是一比一的直译相同的 20×20 网格、30 颗雷、相同的neighborCount -1雷格约定、相同的递归floodFill逻辑连不需要检查 neighbor.beeissue #184的注释都保留了下来。这对于理解同一套游戏逻辑如何在不同语言/框架间移植是极好的对照材料。前置知识与延伸学习原文档明确指出本挑战建立在以下两个前置教程之上二者在仓库中均有对应页面9.15-2d-arrays-in-javascript.md讲解 JavaScript 二维数组的创建、初始化与嵌套 for 循环遍历——本挑战的make2DArray与双重循环正是其直接应用9.19-Prototypes-in-javascript.md讲解如何通过 prototype 为对象附加方法、原型链与原型式继承——本挑战的Cell.prototype.show等五个方法即是原型用法的示范。此外仓库中还有相关的延伸主题可供继续探索例如 9.24-inheritance-with-prototype.md 讨论了基于原型的继承而 162-self-avoiding-walk.md 等挑战文档中也把本挑战列为相关视频引用。扫雷中用到的邻域遍历与洪水填充思想在迷宫生成如 010.1-maze-dfs-p5.md等网格类挑战中同样频繁出现。社区贡献与扩展方向原文档的contributions字段记录了社区围绕该挑战产出的丰富变体这些实现覆盖了多种语言与玩法扩展可作为进一步学习与改写的灵感来源以下仅列举代表性方向不包含外部链接玩法变体TypeScript 带颜色移植版、3D 扫雷、基于六边形的 HexSweeper、把地雷替换成无害小精灵的 Trollsweeper、扩展版 Beesweeper 等语言变体Processing.py、Python PyGame、Unity3D 等不同技术栈的复刻实现界面与交互变体Mine-Buddy、带 UI 控制的实现、在线可玩版本等。对于想在本实现基础上继续扩展的读者仓库源码也指明了几个自然的改进点增加右键标雷与胜利判定、用坐标反推优化命中检测、增加地雷数量/棋盘尺寸的可调参数、引入倒计时与剩余雷数显示等——这些都可以在不改变现有Cell数据结构的前提下增量实现。小结本挑战以不到 200 行代码p5.js 版两文件合计约 170 行完整复现了扫雷的核心玩法二维数组 原型对象建模棋盘、候选池随机布雷、3×3 邻域计数、0 值触发的递归洪水填充以及点击交互与全局翻盘的游戏结束判定。从 sketch.js 与 cell.js 的源码出发再对照 Processing 移植版即可把网格算法 对象原型这套组合拳灵活迁移到任意类似的棋盘类游戏中去。赞分享教程文档示例工程【免费下载链接】website-archiveArchive of the Coding Train website (first version)项目地址https://gitcode.com/gh_mirrors/we/website-archive点击查看免费下载相关推荐用 Processing 复刻经典游戏 PongCoding Challenge 67 源码级实战解析用 Processing 复刻经典游戏 PongCoding Challenge 67 源码级实战解析 在这篇技术指南中我们将以 Coding Train教程文档示例工程用 p5.js 复刻 Agar.io 基础游戏机制Coding Challenge 32.1 全解析用 p5.js 复刻 Agar.io 基础游戏机制Coding Challenge 32.1 全解析 这篇技术指南围绕 Coding TrainThe Co教程文档示例工程探秘经典用Rust重构的扫雷游戏——minesweeper-rs探秘经典用Rust重构的扫雷游戏—— minesweeper rs 1、项目介绍 在快速发展的编程世界中复古游戏的魅力依然不减。 minesweeper r上一篇如何快速解决 Nix Software Center 常见问题终极故障排除指南下一篇SiYuan 图片 OCR 完整指南粘贴图片后文字直接可搜索创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

关于恒美微站

恒美微站专注于为个体商户、工作室提供极简自助建站服务,让每个人都能轻松拥有专业网站。

快速链接

  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心

服务项目

  • 可视化建站
  • 拖拽编辑
  • 主题定制
  • SEO 优化
  • 网站托管

联系方式

  • 📍 地址:北京市朝阳区建国路 88 号
  • 📞 电话:400-888-8888
  • ✉️ 邮箱:info@hmyw.cn
  • 🕐 时间:周一至周日 9:00-18:00

© 2024 恒美微站 hmyw.cn 版权所有 | 京 ICP 备 12345678 号