JavaScript实现简易扫雷游戏:核心逻辑与递归算法详解
本文详解使用JavaScript实现简易扫雷游戏的完整流程。核心包括利用12x12二维数组处理边界,随机生成20个雷并计算周围数字,以及通过递归算法实现点击空白格自动展开区域。代码包含界面生成、触控事件监听及防越界逻辑,适合前端初学者理解游戏逻辑与DOM操作。
JavaScript实现简易扫雷游戏:核心逻辑与递归算法详解
本文分享了一个使用JavaScript编写的简易扫雷游戏示例代码,供读者参考学习。
游戏运行效果
游戏运行效果如下:

核心设计思路:随机布雷与递归展开
核心设计思路主要包含两个难点:首先是雷的随机分布。程序通过JavaScript动态生成一个10x10的表格,并设定生成20个雷。雷在数据中用数字9表示,而0到8则用于表示非雷格子的周围雷数。生成逻辑为:若某格为雷,则将其周围八个相邻格子的数值加1,从而完成雷区数据的初始化。其次是玩法逻辑,难点在于点击数字为0的格子时,需递归展开周围所有相连的0区域,因此采用递归算法实现这一功能。
界面生成逻辑
1、界面生成逻辑
//生成界面
function init() {
document.write("<table border='1px' rules='all' cellpadding='10px '> ")
for (var i = 1; i < 11; i++) {
document.write("<tr>");
for (var j = 1; j < 11; j++) {
document.write("<td class='game'>" + arr3[i][j] + "</td>");
}
document.write("</tr>");
}
document.write("</table>")
var t = document.getElementsByTagName('table')[0];
var td = document.getElementsByTagName('td');
for (var i = 0; i < td.length; i++) {
td[i].style.background='#ffffff';
td[i].style.opacity = '0';
td[i].style.transition = 'all 4s'
}
//样式添加
t.style.margin = '0px auto';
document.close()
}
二维数组边界处理与随机布雷
2、由于表格为10x10,但在计算每个格子周围数值时容易触及边界导致数组越界,因此定义一个12x12的二维数组来存储10x10表格对应的数值。雷的位置通过随机算法生成,总数设定为20个。
//初始化数组
function initarr() {
var arr = new Array(12);
for (var i = 0; i < 12; i++) {
arr[i] = new Array(12);
for (var j = 0; j < 12; j++) {
arr[i][j] = 0;
}
}
return arr;
}
//随机生成雷
function rangemine() {
var arr = initarr();
var num = 0;
for (var index = 0; index < 20; index++) {
while (true) {
var row = Math.floor(Math.random() * 10) + 1;
var col = Math.floor(Math.random() * 10) + 1;
if (arr[row][col] != 9) {
arr[row][col] = 9;
break;
}
}
}
return arr;
}
周围雷数计算逻辑
3、数值生成方法:遍历数组,若检测到某格为雷(值为9),则将其周围八个方向的格子数值加1,从而计算出每个非雷格子周围的雷数。
//生成每块所对应的数字
function num() {
var arr2 = rangemine();
for (var i = 1; i < 11; i++) {
for (var j = 1; j < 11; j++) {
if (arr2[i][j] >= 9) {
arr2[i][j + 1] += 1;
arr2[i][j - 1] += 1;
arr2[i - 1][j] += 1;
arr2[i + 1][j] += 1;
arr2[i - 1][j + 1] += 1;
arr2[i - 1][j - 1] += 1;
arr2[i + 1][j - 1] += 1;
arr2[i + 1][j + 1] += 1;
}
}
}
for (var i = 1; i < 11; i++) {
for (var j = 1; j < 11; j++) {
if (arr2[i][j] > 8) {
arr2[i][j] = 9;
}
}
}
return arr2;
}
移动端触控事件监听
4、事件监听:代码中添加了touch事件监听器。由于touch事件主要适用于移动端,若在PC端运行,需通过工具模拟移动端环境。
//添加监听器
function gostart() {
var t = document.getElementsByTagName('td');
for (var i = 0; i < t.length; i++) {
{
t[i].addEventListener('touchstart', start);
t[i].addEventListener('touchend', end);
}
}
}
gostart();
//开始函数
function start(e) {
console.log((e.touches[0]));
var a = e.touches[0];
}
//结尾函数
function end(e) {
var a = e.touches[0];
mix(e.srcElement.parentElement.rowIndex + 1, e.srcElement.cellIndex + 1, e.srcElement.parentElement);
/* startgame(e.srcElement.parentElement.rowIndex,e.srcElement.cellIndex,e.srcElement); */
}
递归算法实现自动展开
5、递归实现扫雷逻辑:当点击到周围没有雷(数值为0)的格子时,通过递归函数将其周围也是0的格子依次展示出来,实现自动展开效果。
//递归消除点到0块时显露出其他的块
function mix(x, y, e) {
var flag=0;
if (x > 0 && x < 11 && y > 0 && y < 11 && arr3[x][y] == 0) {
//防止无限递归
e.parentElement.rows[x - 1].cells[y - 1].style.opacity = 1;
e.parentElement.rows[x - 1].cells[y - 1].innerHTML="";
e.parentElement.rows[x - 1].cells[y - 1].style.background = '#a4eaff';
arr3[x][y] = 10;
mix(x, y + 1, e);
mix(x, y - 1, e);
mix(x + 1, y, e);
mix(x - 1, y, e);
mix(x + 1, y + 1, e);
mix(x - 1, y + 1, e);
mix(x + 1, y - 1, e);
mix(x - 1, y - 1, e);
} else if (x > 0 && x < 11 && y > 0 && y < 11 && arr3[x][y] > 0 && arr3[x][y] < 9) {
//颜色变红且透明度变为1
arr3[x][y]=-1;
e.parentElement.rows[x - 1].cells[y - 1].style.opacity = 1;
e.parentElement.rows[x - 1].cells[y - 1].style.backgroundColor = '#a4eaff';
//判断是否结束
for(var i=1;i<arr3.length-1;i++){
for(var j=1;j<arr3[i].length-1;j++){
if(arr3[i][j]!=-1||arr3[i][j]!=9){
flag=1;
break;
}
}
}
if(flag==0){
alert('成功');
}
return;
} else if (x > 0 && x < 11 && y > 0 && y < 11 && arr3[x][y] == 9) {
alert('你踩到地雷啦!!!');
arr3 = num();
//移除原来的表格
var s = document.getElementsByTagName('table')[0];
s.parentNode.removeChild(s);
init();
gostart();
}
}
完整代码实现
6、完整JavaScript代码实现如下:
function initarr() {
var arr = new Array(12);
for (var i = 0; i < 12; i++) {
arr[i] = new Array(12);
for (var j = 0; j < 12; j++) {
arr[i][j] = 0;
}
}
return arr;
}
//随机生成雷
function rangemine() {
var arr = initarr();
var num = 0;
for (var index = 0; index < 20; index++) {
while (true) {
var row = Math.floor(Math.random() * 10) + 1;
var col = Math.floor(Math.random() * 10) + 1;
if (arr[row][col] != 9) {
arr[row][col] = 9;
break;
}
}
}
return arr;
}
//生成每块所对应的数字
function num() {
var arr2 = rangemine();
for (var i = 1; i < 11; i++) {
for (var j = 1; j < 11; j++) {
if (arr2[i][j] >= 9) {
arr2[i][j + 1] += 1;
arr2[i][j - 1] += 1;
arr2[i - 1][j] += 1;
arr2[i + 1][j] += 1;
arr2[i - 1][j + 1] += 1;
arr2[i - 1][j - 1] += 1;
arr2[i + 1][j - 1] += 1;
arr2[i + 1][j + 1] += 1;
}
}
}
for (var i = 1; i < 11; i++) {
for (var j = 1; j < 11; j++) {
if (arr2[i][j] > 8) {
arr2[i][j] = 9;
}
}
}
return arr2;
}
var arr3 = num()
//生成界面
function init() {
document.write("<table border='1px' rules='all' cellpadding='10px '> ")
for (var i = 1; i < 11; i++) {
document.write("<tr>");
for (var j = 1; j < 11; j++) {
document.write("<td class='game'>" + arr3[i][j] + "</td>");
}
document.write("</tr>");
}
document.write("</table>")
var t = document.getElementsByTagName('table')[0];
var td = document.getElementsByTagName('td');
for (var i = 0; i < td.length; i++) {
td[i].style.background='#ffffff';
td[i].style.opacity = '0';
td[i].style.transition = 'all 4s'
}
//样式添加
t.style.margin = '0px auto';
document.close()
}
init();
//添加监听器
function gostart() {
var t = document.getElementsByTagName('td');
for (var i = 0; i < t.length; i++) {
{
t[i].addEventListener('touchstart', start);
t[i].addEventListener('touchend', end);
}
}
}
gostart();
//开始函数
function start(e) {
console.log((e.touches[0]));
var a = e.touches[0];
}
//结尾函数
function end(e) {
var a = e.touches[0];
mix(e.srcElement.parentElement.rowIndex + 1, e.srcElement.cellIndex + 1, e.srcElement.parentElement);
/* startgame(e.srcElement.parentElement.rowIndex,e.srcElement.cellIndex,e.srcElement); */
}
//递归消除点到0块时显露出其他的块
function mix(x, y, e) {
var flag=0;
if (x > 0 && x < 11 && y > 0 && y < 11 && arr3[x][y] == 0) {
//防止无限递归
e.parentElement.rows[x - 1].cells[y - 1].style.opacity = 1;
e.parentElement.rows[x - 1].cells[y - 1].innerHTML="";
e.parentElement.rows[x - 1].cells[y - 1].style.background = '#a4eaff';
arr3[x][y] = 10;
mix(x, y + 1, e);
mix(x, y - 1, e);
mix(x + 1, y, e);
mix(x - 1, y, e);
mix(x + 1, y + 1, e);
mix(x - 1, y + 1, e);
mix(x + 1, y - 1, e);
mix(x - 1, y - 1, e);
} else if (x > 0 && x < 11 && y > 0 && y < 11 && arr3[x][y] > 0 && arr3[x][y] < 9) {
//颜色变红且透明度变为1
arr3[x][y]=-1;
e.parentElement.rows[x - 1].cells[y - 1].style.opacity = 1;
e.parentElement.rows[x - 1].cells[y - 1].style.backgroundColor = '#a4eaff';
//判断是否结束
for(var i=1;i<arr3.length-1;i++){
for(var j=1;j<arr3[i].length-1;j++){
if(arr3[i][j]!=-1||arr3[i][j]!=9){
flag=1;
break;
}
}
}
if(flag==0){
alert('成功');
}
return;
} else if (x > 0 && x < 11 && y > 0 && y < 11 && arr3[x][y] == 9) {
alert('你踩到地雷啦!!!');
arr3 = num();
//移除原来的表格
var s = document.getElementsByTagName('table')[0];
s.parentNode.removeChild(s);
init();
gostart();
}
}
总结与不足
7、总结与不足
更多经典小游戏资源推荐
本次实现的扫雷游戏主要存在两个缺点:一是无法保证玩家第一次点击时不点到雷;二是尚未经过完整局测试,可能存在一些未发现的Bug。
更多有趣的经典小游戏实现专题,分享给大家:
C++经典小游戏汇总
python经典小游戏汇总
python俄罗斯方块游戏集合
JavaScript经典游戏 玩不停
java经典小游戏汇总
javascript经典小游戏汇总
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。
JavaScript异步发送HTTP请求时怎么优雅地处理错误
2026-11-05 17:10:44
5款主流JS在线运行工具对比:CodePen、JSFiddle与StackBlitz怎么选
2026-11-05 17:04:04
JavaScript入门书籍避坑:这些书不适合初学者
2026-11-05 16:31:15
JS使用Math.round实现保留两位小数的原理与代码
2026-11-05 15:35:55
JavaScript 原生 Date 对象怎么实现日期加减
2026-11-05 14:30:00
