前端技术搭建扫雷小游戏(内含源码)

2025-12-13 0 798

写在前面

上周我们实通过前端基础实现了贪吃蛇游戏,今天还是继续按照我们原定的节奏来带领大家完成一个游戏,功能也比较简单简单,也是想借助这样一个简单的功能,然后来帮助大家了解我们JavaScript在前端中的作用, 在前面的文章当中我们也提及到我们在本系列的专栏是循序渐进从简单到复杂的过程,后续会带领大家用前端实现翻卡片、扫雷等有趣的小游戏,纯前端语言实现,都会陆续带给大家。欢迎大家订阅我们这份前端小游戏的专栏。订阅链接:https://blog.csdn.net/jhxl_/category_12261013.html


功能介绍

扫雷是一款经典的单人益智游戏,目标是在雷区中揭开所有非雷方块而避免触雷。以下是游戏的玩法说明和规则:游戏开始时,你将面对一个方块组成的地图,其中包含隐藏的雷方块和非雷方块。你需要逐个点击方块来揭开它们。如果揭开的方块是雷方块,你失败并游戏结束。揭开的方块可能是数字方块,它会显示周围八个方块中雷的数量。根据这些数字,你可以推断其他方块的状态。如果揭开的方块是空白方块,它将自动展开,揭开相邻的空白方块,直到边界或有数字的方块。通过观察数字方块周围的雷的数量,你可以推断出潜在的雷区,并使用右键进行标记,帮助记忆和避免揭开雷方块。如果你成功揭开所有非雷方块,而没有触雷,你将获得胜利。

前端技术搭建扫雷小游戏(内含源码)

在扫雷游戏中,推理、记忆和谨慎是取得胜利的关键。通过观察和推断雷的位置,并运用合适的标记策略,你可以在雷区中探索出更多安全的方块,并最终解开所有的谜题。记住要保持冷静,小心行事,以在这个挑战性的益智游戏中获得成功!


页面搭建

创建文件

首先呢我们创建我们的HTML文件,这里我就直接命名为扫雷.html了,大家可以随意命名, 文件创建生成后我们通过编辑器打开,这里我用的是VScode, 然后初始化我们的代码结构,那在这里告诉大家一个快捷键,就是我们敲上我们英文的一个!我们敲击回车直接就会给我们生成基础版本的前端代码结构。

前端技术搭建扫雷小游戏(内含源码)

文档声明和编码设置: 在HTML文档的头部,使用<!DOCTYPE>声明HTML文档类型,确保浏览器以正确的方式渲染网页内容。同时,设置UTF-8编码,以确保浏览器能够正确地解析和显示中文字符。下面我就开始搭建我们的DOM结构了!

DOM结构搭建

这段HTML代码是一个简单的扫雷游戏界面的布局。让我为你解释一下每个部分的作用:<div class=\”bigBox\”>:这是一个包含整个游戏内容的大容器,它用来将游戏界面的各个元素进行组合和布局。<div id=\”controls\”>:这个<div>元素包含了游戏的控制面板,用于设置游戏的难度级别和重新开始游戏。<form>:这是一个表单元素,用于包裹控制面板中的各个控件。<label for=\”level\”>难度级别:</label>:这是一个用于显示文本的<label>元素,它与下面的下拉菜单(<select>)建立了关联,通过for属性指定了关联的控件的id。<select id=\”level\”>:这是一个下拉菜单(选择框)控件,用于选择游戏的难度级别。它有三个选项:简单、中等和困难。<button id=\”reset\”>重新开始</button>:这是一个按钮控件,用于重新开始游戏。<table id=\”board\”></table>:这是一个空的表格元素,用于承载扫雷游戏的方格(格子)。在游戏开始后,这个表格会被动态生成,并显示雷区的方格布局。

总体而言,这段HTML代码定义了一个扫雷游戏的基本界面结构,包括了难度选择、重新开始按钮和雷区的表格容器。通过这些元素,玩家可以进行难度选择,并在雷区中进行游戏操作。

<body>

<div class=\”bigBox\”>
<div id=\”controls\”>
<form>
<label for=\”level\”>难度级别:</label>
<select id=\”level\”>
<option value=\”easy\”>简单</option>
<option value=\”medium\”>中等</option>
<option value=\”hard\”>困难</option>
</select>
<button id=\”reset\”>重新开始</button>
</form>
</div>

<table id=\”board\”></table>
</div>

</body>

前端技术搭建扫雷小游戏(内含源码)


样式设置

我们看到了上面的的DOM已经搭建好了,但是页面什么都看不出来,下面我们简单的来配置一下样式吧,其实我们本专栏也是想带领大家掌握一些逻辑所以样式方面我们就一切从简;

  1. .bigBox:这个类选择器用于样式化游戏的大容器。设置了背景颜色、宽度、居中对齐、内边距等样式,使游戏界面具有一定的外观和布局。

  2. #reset:这是一个ID选择器,用于样式化重新开始按钮。设置了按钮的宽度、字体大小等样式。

  3. table:这个选择器用于样式化表格元素。设置了表格的边框合并、居中对齐、外边距等样式,使雷区的方格在表格中呈现出合适的布局。

  4. td:这个选择器用于样式化表格中的单元格(方格)。设置了单元格的宽度、高度、文本对齐、垂直对齐、边框等样式,使方格具有一致的外观。

  5. button:这个选择器用于样式化按钮元素。设置了按钮的宽度、高度、内边距、外边距、字体大小、字体加粗、文本颜色、背景颜色等样式,使按钮呈现出一致的外观和按钮效果。

  6. #controls:这个ID选择器用于样式化控制面板的样式。设置了控制面板的顶部外边距,使其与上方的元素保持一定的间距。

总体而言,这段CSS代码通过设置不同的选择器和样式属性,为扫雷游戏的界面元素和控制面板元素提供了外观和布局的样式。这样可以使游戏界面看起来更加美观、整洁,并提供良好的用户体验。

/* 游戏布局样式 */
.bigBox {
background-color: rgb(163, 159, 159);
width: 40%;
margin: 5% auto;
text-align: center;
padding: 20px;
}

#reset {
width: 100px;
font-size: 15px;
}

table {
border-collapse: collapse;
margin: 30px auto;
}

td {
width: 30px;
height: 30px;
text-align: center;
vertical-align: middle;
border: 1px solid #ccc;
}

button {
width: 100%;
height: 100%;
padding: 0;
margin: 0;
font-size: 16px;
font-weight: bold;
color: #fff;
background-color: #333;
border: none;
}

/* 控制面板样式 */
#controls {
margin-top: 20px;
}

前端技术搭建扫雷小游戏(内含源码)


逻辑部分

上面我们搭建了基本的样式,下面呢我们就通过js代码,实现我们游戏的功能吧,下面是对代码的简化解释:

  1. const config = { … }:这是一个对象,用于存储游戏的参数配置。根据难度级别(简单、中等、困难),配置了每个级别的行数、列数和地雷数量。

  2. 变量声明和初始化:声明了一系列变量用于存储游戏所需的各种信息,如游戏界面元素、游戏状态、地雷数量等。

  3. 事件监听器:通过监听重新开始按钮(reset)和难度级别选择器(level)的点击事件或改变事件,调用相应的初始化函数(init())来重新开始游戏或改变游戏难度。

  4. init()函数:该函数用于初始化游戏。根据选择的难度级别,设置相应的行数、列数和地雷数量。然后,根据行数和列数动态生成游戏的表格布局,并为每个单元格(方格)添加按钮元素。最后,初始化地雷的位置,并更新地雷数量的显示。

  5. clickCell()函数:该函数用于处理玩家点击单元格(方格)的操作。根据点击的单元格的位置,判断是否有地雷,如果有地雷则显示所有地雷并结束游戏;如果没有地雷,则根据周围的地雷数量显示相应的数字或递归地显示周围的方格。

  6. revealNeighbors()函数:该函数用于递归地展开周围的方格,直到周围有地雷或有数字。

  7. countMinesAround()函数:该函数用于计算给定方格周围的地雷数量。

  8. revealMines()函数:该函数用于显示所有的地雷,将地雷方格的背景颜色设置为红色。

  9. updateMinesCount()函数:该函数用于更新剩余地雷数量的显示。

  10. showGameOver()函数:该函数用于展示游戏结束的提示信息,根据参数win的值判断是胜利还是失败。

  11. checkWin()函数:该函数用于检查玩家是否已经胜利,遍历所有方格,如果有任何未揭示的非地雷方格,则返回false,否则返回true。

  12. init()函数调用:在脚本末尾,调用init()函数来初始化游戏。

通过这段JavaScript代码,扫雷游戏实现了玩家点击方格、展开周围方格、计算地雷数量等功能,并提供了重新开始游戏和切换难度级别的功能。

<script>
// 游戏参数配置
const config = {
easy: {
rows: 8,
cols: 8,
mines: 10,
},
medium: {
rows: 10,
cols: 10,
mines: 20,
},
hard: {
rows: 12,
cols: 12,
mines: 30,
},
};
// 初始化游戏
let board = document.getElementById(\”board\”);
let level = document.getElementById(\”level\”);
let reset = document.getElementById(\”reset\”);
let cells = [];
let gameover = false;
let minesLeft = 0;
let minesCount = 0;
let rows, cols, mines;

reset.addEventListener(\”click\”, init);

level.addEventListener(\”change\”, function () {
init();
});

function init () {
// 初始化游戏参数
let levelConfig = config[level.value];
rows = levelConfig.rows;
cols = levelConfig.cols;
mines = levelConfig.mines;
minesLeft = mines;
minesCount = 0;
gameover = false;
// 初始化游戏布局
board.innerHTML = \”\”;
cells = [];
for (let i = 0; i < rows; i++) {
let row = [];
let tr = document.createElement(\”tr\”);
for (let j = 0; j < cols; j++) {
let td = document.createElement(\”td\”);
let button = document.createElement(\”button\”);
button.addEventListener(\”click\”, function () {
if (!gameover) {
clickCell(i, j);
}
});
td.appendChild(button);
tr.appendChild(td);
row.push({ button: button, hasMine: false, revealed: false });
}
cells.push(row);
board.appendChild(tr);
}
// 初始化地雷
for (let i = 0; i < mines; i++) {
let row, col;
do {
row = Math.floor(Math.random() * rows);
col = Math.floor(Math.random() * cols);
} while (cells[row][col].hasMine);
cells[row][col].hasMine = true;
}
// 更新地雷数目显示
updateMinesCount();
}

function clickCell (row, col) {
let cell = cells[row][col];
if (cell.revealed) {
return;
}
if (cell.hasMine) {
revealMines();
showGameOver(false);
return;
}
cell.revealed = true;
cell.button.style.backgroundColor = \”#ddd\”;
let minesAround = countMinesAround(row, col);
if (minesAround > 0) {
cell.button.textContent = minesAround;
} else {
revealNeighbors(row, col);
}
if (checkWin()) {
showGameOver(true);
}
}

function revealNeighbors (row, col) {
for (let i = row – 1; i <= row + 1; i++) {
for (let j = col – 1; j <= col + 1; j++) {
if (i >= 0 &amp;& i < rows && j >= 0 && j < cols && !(i == row && j == col)) {
clickCell(i, j);
}
}
}
}

function countMinesAround (row, col) {
let count = 0;
for (let i = row – 1; i <= row + 1; i++) {
for (let j = col – 1; j <= col + 1; j++) {
if (i >= 0 && i < rows && j >= 0 && j < cols && cells[i][j].hasMine) {
count++;
}
}
}
return count;
}

function revealMines () {
for (let i = 0; i < rows; i++) {
for (let j = 0; j < cols; j++) {
if (cells[i][j].hasMine) {
cells[i][j].button.style.backgroundColor = \”#f00\”;
}
}
}
}

function updateMinesCount () {
console.log(\’这是哈哈\’, minesLeft)
// minesCountElem.textContent = minesLeft;
}

function showGameOver (win) {
gameover = true;
let message = win ? \”You Win!\” : \”You Lose!\”;
alert(message);
}

function checkWin () {
for (let i = 0; i < rows; i++) {
for (let j = 0; j < cols; j++) {
let cell = cells[i][j];
if (!cell.hasMine && !cell.revealed) {
return false;
}
}
}
return true;
}

init();

</script>

完整代码


<!DOCTYPE html>
<html lang=\”en\”>

<head>
<meta charset=\”UTF-8\”>
<meta http-equiv=\”X-UA-Compatible\” content=\”IE=edge\”>
<meta name=\”viewport\” content=\”width=device-width, initial-scale=1.0\”>
<title>Document</title>
<style>
/* 游戏布局样式 */
.bigBox {
background-color: rgb(163, 159, 159);
width: 40%;
margin: 5% auto;
text-align: center;
padding: 20px;
}

#reset {
width: 100px;
font-size: 15px;
}

table {
border-collapse: collapse;
margin: 30px auto;
}

td {
width: 30px;
height: 30px;
text-align: center;
vertical-align: middle;
border: 1px solid #ccc;
}

button {
width: 100%;
height: 100%;
padding: 0;
margin: 0;
font-size: 16px;
font-weight: bold;
color: #fff;
background-color: #333;
border: none;
}

/* 控制面板样式 */
#controls {
margin-top: 20px;
}
</style>
</head>

<body>

<div class=\”bigBox\”>
<div id=\”controls\”>
<form>
<label for=\”level\”>难度级别:</label>
<select id=\”level\”>
<option value=\”easy\”>简单</option>
<option value=\”medium\”>中等</option>
<option value=\”hard\”>困难</option>
</select>
<button id=\”reset\”>重新开始</button>
</form>
</div>

<table id=\”board\”></table>
</div>

</body>

<script>
// 游戏参数配置
const config = {
easy: {
rows: 8,
cols: 8,
mines: 10,
},
medium: {
rows: 10,
cols: 10,
mines: 20,
},
hard: {
rows: 12,
cols: 12,
mines: 30,
},
};
// 初始化游戏
let board = document.getElementById(\”board\”);
let level = document.getElementById(\”level\”);
let reset = document.getElementById(\”reset\”);
let cells = [];
let gameover = false;
let minesLeft = 0;
let minesCount = 0;
let rows, cols, mines;

reset.addEventListener(\”click\”, init);

level.addEventListener(\”change\”, function () {
init();
});

function init () {
// 初始化游戏参数
let levelConfig = config[level.value];
rows = levelConfig.rows;
cols = levelConfig.cols;
mines = levelConfig.mines;
minesLeft = mines;
minesCount = 0;
gameover = false;
// 初始化游戏布局
board.innerHTML = \”\”;
cells = [];
for (let i = 0; i < rows; i++) {
let row = [];
let tr = document.createElement(\”tr\”);
for (let j = 0; j < cols; j++) {
let td = document.createElement(\”td\”);
let button = document.createElement(\”button\”);
button.addEventListener(\”click\”, function () {
if (!gameover) {
clickCell(i, j);
}
});
td.appendChild(button);
tr.appendChild(td);
row.push({ button: button, hasMine: false, revealed: false });
}
cells.push(row);
board.appendChild(tr);
}
// 初始化地雷
for (let i = 0; i < mines; i++) {
let row, col;
do {
row = Math.floor(Math.random() * rows);
col = Math.floor(Math.random() * cols);
} while (cells[row][col].hasMine);
cells[row][col].hasMine = true;
}
// 更新地雷数目显示
updateMinesCount();
}

function clickCell (row, col) {
let cell = cells[row][col];
if (cell.revealed) {
return;
}
if (cell.hasMine) {
revealMines();
showGameOver(false);
return;
}
cell.revealed = true;
cell.button.style.backgroundColor = \”#ddd\”;
let minesAround = countMinesAround(row, col);
if (minesAround > 0) {
cell.button.textContent = minesAround;
} else {
revealNeighbors(row, col);
}
if (checkWin()) {
showGameOver(true);
}
}

function revealNeighbors (row, col) {
for (let i = row – 1; i <= row + 1; i++) {
for (let j = col – 1; j <= col + 1; j++) {
if (i >= 0 && i < rows && j >= 0 && j < cols && !(i == row && j == col)) {
clickCell(i, j);
}
}
}
}

function countMinesAround (row, col) {
let count = 0;
for (let i = row – 1; i <= row + 1; i++) {
for (let j = col – 1; j <= col + 1; j++) {
if (i >= 0 && i < rows && j >= 0 && j < cols && cells[i][j].hasMine) {
count++;
}
}
}
return count;
}

function revealMines () {
for (let i = 0; i < rows; i++) {
for (let j = 0; j < cols; j++) {
if (cells[i][j].hasMine) {
cells[i][j].button.style.backgroundColor = \”#f00\”;
}
}
}
}

function updateMinesCount () {
console.log(\’这是哈哈\’, minesLeft)
// minesCountElem.textContent = minesLeft;
}

function showGameOver (win) {
gameover = true;
let message = win ? \”You Win!\” : \”You Lose!\”;
alert(message);
}

function checkWin () {
for (let i = 0; i < rows; i++) {
for (let j = 0; j < cols; j++) {
let cell = cells[i][j];
if (!cell.hasMine && !cell.revealed) {
return false;
}
}
}
return true;
}

init();

</script>

</html>

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

申明:本文由第三方发布,内容仅代表作者观点,与本网站无关。对本文以及其中全部或者部分内容的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。本网发布或转载文章出于传递更多信息之目的,并不意味着赞同其观点或证实其描述,也不代表本网对其真实性负责。

左子网 编程相关 前端技术搭建扫雷小游戏(内含源码) https://www.zuozi.net/36301.html

常见问题
  • 1、自动:拍下后,点击(下载)链接即可下载;2、手动:拍下后,联系卖家发放即可或者联系官方找开发者发货。
查看详情
  • 1、源码默认交易周期:手动发货商品为1-3天,并且用户付款金额将会进入平台担保直到交易完成或者3-7天即可发放,如遇纠纷无限期延长收款金额直至纠纷解决或者退款!;
查看详情
  • 1、描述:源码描述(含标题)与实际源码不一致的(例:货不对板); 2、演示:有演示站时,与实际源码小于95%一致的(但描述中有”不保证完全一样、有变化的可能性”类似显著声明的除外); 3、发货:不发货可无理由退款; 4、安装:免费提供安装服务的源码但卖家不履行的; 5、收费:价格虚标,额外收取其他费用的(但描述中有显著声明或双方交易前有商定的除外); 6、其他:如质量方面的硬性常规问题BUG等。 注:经核实符合上述任一,均支持退款,但卖家予以积极解决问题则除外。
查看详情
  • 1、左子会对双方交易的过程及交易商品的快照进行永久存档,以确保交易的真实、有效、安全! 2、左子无法对如“永久包更新”、“永久技术支持”等类似交易之后的商家承诺做担保,请买家自行鉴别; 3、在源码同时有网站演示与图片演示,且站演与图演不一致时,默认按图演作为纠纷评判依据(特别声明或有商定除外); 4、在没有”无任何正当退款依据”的前提下,商品写有”一旦售出,概不支持退款”等类似的声明,视为无效声明; 5、在未拍下前,双方在QQ上所商定的交易内容,亦可成为纠纷评判依据(商定与描述冲突时,商定为准); 6、因聊天记录可作为纠纷评判依据,故双方联系时,只与对方在左子上所留的QQ、手机号沟通,以防对方不承认自我承诺。 7、虽然交易产生纠纷的几率很小,但一定要保留如聊天记录、手机短信等这样的重要信息,以防产生纠纷时便于左子介入快速处理。
查看详情

相关文章

猜你喜欢
发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务