您的位置:首页 > Web前端 > JavaScript

原生js实现自定义难度的扫雷游戏

2021-02-01 04:07 1286 查看

本文实例为大家分享了js实现扫雷游戏的具体代码,供大家参考,具体内容如下

游戏功能:

1、有四个难度
2、可以自定难度

1、html相关代码

<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>扫雷</title>
<script src="js/mine.js"></script>
<link rel="stylesheet" href="./css/mine.css" >
</head>
<!--
需求分析:
1.游戏的区域:
9*9的区域
2.方格可以打开与标记
左键打开,显示数字,为周围格子的地雷数,右键标记
3.地雷
地雷随机分布
4.踩到地雷时,游戏结束
所有的地雷显示出来
5.连锁开大空方格
6.剩余地雷数与计时器
7.游戏胜利条件
所有的方格除了地雷都被打开了,则游戏胜利
一个方格所包含的信息:
坐标 x y
是否是一个地雷
周围的地雷数 = 9
二维数组中存储的是周围的地雷数
-->

<body>
<div class="level">
<button type="button" name="button" class="choice-level">自定义</button>
<button type="button" name="button" class="choice-level">初级</button>
<button type="button" name="button" class="choice-level">中级</button>
<button type="button" name="button" class="choice-level">高级</button>
<button type="button" name="button" class="choice-level">魔鬼级</button>
<button type="button" name="button" class="restart">重新开始</button>
</div>
<div class="gameBox"></div>
<div class="info">
<p>剩余雷数:
<span class="residue"></span>
</p>
<p>
TIME:
<span class="tick"></span>S
</p>

</div>
</body>

</html>

2、css样式

*{
margin: 0;
padding: 0;
}
.gameBox{
margin-top: 30px;
}
body{
font-size: 0;
}
ul{
list-style: none;
text-align: center;
overflow: hidden;
}
.col{
display: inline-block;
width: 22px;
height: 22px;
line-height: 22px;
background-color: rgba(32, 226, 255, 0.4);
border: 1px solid rgb(129, 129, 129);
font-size: 16px;
margin: 1.5px;
vertical-align: top;
position: relative;
}
.col:hover{
background-color: #0af;
}
.col span{
cursor: default;
}
.hide{
display: none;
}
.boom{
background: url("../img/boom.svg") no-repeat 2.5px 2px;
background-size: 18px 18px;
}
.num-1{
color: rgb(8, 153, 235);
}
.num-2{
color: rgb(255, 45, 178);
}
.num-3{
color:#16a085;
}
.num-4{
color: #8e44ad;
}
.num-5{
color: rgb(255, 167, 45);
}
.num-6{
color: rgb(8, 126, 176);
}
.num-7{
color: #e67e22;
}
.num-8{
color: #c0392b;
}
.img-flag{
width: 18px;
height: 18px;
position: absolute;
top: 3px;
left: 3px;
}
.level{
margin-top: 30px;
font-size: 20px;
text-align: center;
}
.level button{
padding: 5px 8px;
background-color: rgb(67, 183, 189);
border: none;
outline: none;
border-radius: 3px;
cursor: pointer;
color: #fff;
}
.level button:hover{
background-color: rgb(23, 132, 138);
}
.info{
margin-top: 30px;
font-size: 16px;
text-align: center;
}
.info p{
display: inline-block;
width: 130px;
margin: 0 auto;
}
.info p span{
color: rgb(67, 183, 189);
}

3、js代码

window.onload = function() {
var row = 4;
var col = 4;
var num = 1;
// 判断踩雷之后不能胜利
var gg = false;
// 生成地图
function mineMap(r, c, num) {
// 定义行
var map = [];
//给行数,生成二维数组
for (var i = 0; i < r; i++) {
map[i] = new Array()
}
// 赋值
for (var i = 0; i < map.length; i++) {
for (var j = 0; j < c; j++) {
// //周围的地雷数
map[i][j] = 0;
}
}
var plus = function(array, x, y) {
if (x >= 0 && x < r && y >= 0 && y < c) {
if (array[x][y] !== 9) {
array[x][y]++
}
}
}
for (var i = 0; i < num; i++) {
var x = Math.floor(Math.random() * r)
var y = Math.floor(Math.random() * c)
if (map[x][y] != 9) {
map[x][y] = 9
//上下6个 +1
for (var j = -1; j < 2; j++) {
//上三个
plus(map, x - 1, y + j)
//下三个
plus(map, x + 1, y + j)
}
//左右2个 +1
plus(map, x, y - 1)
plus(map, x, y + 1)
} else {
//重新随机
num++
}
}
return map;
}
//先通过x轴数量写入ul,再讲过y轴的属性写入li
function writeHtml(map) {
// 获取盒子
var gameBox = document.querySelector(".gameBox");
// 声明空字符串,存放生成的ul、li
var gridHTML = "";
for (var i = 0; i < map.length; i++) {
gridHTML += '<ul class = "row" data-x="' + i + '">';
//生成li
for (var j = 0; j < map[0].length; j++) {
var m = map[i][j]
if (m == 0) {
m = "";
}
gridHTML += "<li class='col' data-y=" + j + ">" +
"<span class='hide num-" + m + "'>" + m + "</span>" +
"<img src='img/flag.svg' class='img-flag hide'>" +
"</li>"
}
gridHTML += '</ul>'
gameBox.innerHTML = gridHTML;
}
}

//给方格绑定事件, 点开数字 地雷 右键标记
function show() {
// 获取行ul
var rows = document.querySelectorAll(".row");
// 遍历所有ul
for (var i = 0; i < rows.length; i++) {
var element = rows[i];
// 添加点击事件
element.onclick = function(event) {
// 当前点击元素
var el = event.target;
// 判断是否为li
if (el.nodeName != "LI") {
return;
}
//todo 判断是否被打开以及标记了
if (el.style.background == "white" || !el.children[1].classList.contains("hide")) {
return;
}
// 获取span标签内容
var mineNum = el.children[0].innerHTML;
if (mineNum !== "9" && el.style.background !== "white") {
// 空白连锁打开
if (mineNum == "") {
var x = parseInt(el.parentNode.dataset.x);
var y = parseInt(el.dataset.y);
showNoMine(x, y);
}
// li背景变白色;span显示
el.style.background = "white";
el.children[0].style.display = "inline";
// 判断打开数量
clearMineNum++;
// 胜利函数
judgeVictory()

} else if (mineNum == "9") {
// 清除胜利计时器
clearInterval(stopTime);
// li添加类名
el.classList.add("boom");
alert("你真菜!")
gg = true;
// 显示所有地雷,获取所有li
var all = document.querySelectorAll(".col");
// 放置所有的地雷
var ff = [];
var allnum = 0;
// 遍历所有li
for (var i = 0; i < all.length; i++) {
if (all[i].children[0].innerHTML == "9") {
// 雷赋值给数组
ff[allnum] = all[i];
allnum++;
}
}
// 设置一个计时器一个一个打开雷
allnum = 0;
var stop = setInterval(function() {
ff[allnum].classList.add("boom")
allnum++;
// 判断结束条件
if (allnum == ff.length) {
// 清除计时器
clearInterval(stop);
}
}, 30)

}
}
// 右键标记地雷
element.oncontextmenu = function(event) {
// 阻止右键菜单
event.preventDefault();
// 获取当前点击节点
var el = event.target;
// 判断是否是
if (el.parentNode.nodeName == "LI") {
el = el.parentNode;
}
if (el.nodeName != "LI") {
return;
}
// 获取img
var classList = el.children[1].classList;
// 剩余雷数
var residue = document.querySelector(".residue");
var mineNum = parseInt(residue.innerHTML);
// 如果没有旗子,没有被点开,可以插旗子
if (classList.contains("hide") && el.style.background != "white") {
// 移除隐藏
classList.remove("hide");
// 获取雷数
mineNum--;
} else if (el.style.background != "white") {
classList.add("hide");
// 判断雷数
if (mineNum < num) {
mineNum++;
}
}
// 剩余雷数
residue.innerHTML = mineNum;
}
}
}

function judgeVictory() {
//游戏胜利
if (clearMineNum === (row * col - num)) {
//做一个小动画
var all = document.querySelectorAll(".col");
var allNum = 0;
var stop = setInterval(function() {
var r = Math.floor(Math.random() * 256)
var g = Math.floor(Math.random() * 256)
var b = Math.floor(Math.random() * 256)
all[allNum].style.background = "rgba(" + r + "," + g + "," + b + ",0.6)";
//将旗子和span都隐藏
all[allNum].children[0].style.display = "none"
all[allNum].children[1].style.display = "none"
allNum++
if (allNum === all.length) {
clearInterval(stop)
if (!gg) {
alert("大吉大利,今晚吃鸡")
init(row, col, num)
}
}
}, 20)
}
}
//自动打开空格
function showNoMine(x, y) {
for (var i = -1; i <= 1; i++) {
if (x + i >= 0 && x + i < row) {
// 获取当前行
var rowElement = document.querySelectorAll(".row")[x + i];
for (var j = -1; j <= 1; j++) {
if (y + j >= 0 && y + j < col) {
//获取当前单元格
var el = rowElement.children[y + j]
//自动打开必须是未打开的方格
if (el.style.background != "white") {
el.style.background = "white"
el.children[0].style.display = "inline"
//打开方格数量+1
clearMineNum++
//判断游戏是否胜利
judgeVictory(clearMineNum)

if (el.children[0].innerText === "") {
showNoMine(x + i, y + j)
}
}
}
}
}
// if (x + i >= 0 && x + i < row) {
// // 获取当前行
// var rowElement = document.querySelectorAll(".row")[x + i];
// for (var j = -1; j <= 1; j++ && y + j < col) {
//  // 获取当前单元格
//  var el = rowElement.children[y + j];
//  if (el.style.background !== "white") {
//  el.style.background = "white";
//  el.children[0].style.display = "inline";
//  // 打开放格数量加1
//  clearMineNum++;
//  // 判断游戏是否胜利
//  judgeVictory(clearMineNum);
//  // 判断打开周围的放格周围是否为空
//  if (el.children[0].innerHTML === "") {
//   showNoMine(x + i, y + j)
//  }
//  }
// }
// }
}

}
//初始化方法
var stopTime;

function init(row, col, num) {
//数据初始化
clearMineNum = 0
gg = false;
//清除原来的地图,生成新的地图
var box = document.querySelector(".gameBox")
box.innerHTML = "";
var map = mineMap(row, col, num);
// 新建地图
writeHtml(map);
show()
//将雷数写入html中
var residue = document.querySelector(".residue")
residue.innerHTML = num
// 获取计时
var tick = document.querySelector(".tick");
var i = 0;
// 初始化
tick.innerHTML = i;
// 清除计时
clearInterval(stopTime);
// 时间计时器
stopTime = setInterval(function() {
tick.innerHTML = ++i
}, 1000)
}
// 重置
var restart = document.querySelector(".restart");
restart.onclick = function(event) {
//阻止冒泡
event.stopPropagation()
init(row, col, num)
}
// 自定义
var level = document.querySelector(".level")
level.onclick = function(event) {
var el = event.target;
switch (el.innerHTML) {
case "初级":
row = 9;
col = 9;
num = 10;
init(row, col, num)
break;
case "中级":
row = 16;
col = 16;
num = 40;
init(row, col, num)
break;
case "高级":
row = 16;
col = 30;
num = 479;
init(row, col, num)
break;
case "魔鬼级":
row = 40;
col = 50;
num = 300;
init(row, col, num)
break;
case "自定义":
row = prompt("请输入列数!");
col = prompt("请输入行数!");
num = prompt("请输入你想要的雷数,(请慎重选择)");
init(row, col, num);
break;
default:
row = 9;
col = 9;
num = 10;
init(row, col, num)
break;
}
}
init(row, col, num)
}

以上就是本文的全部内容,希望对大家的学习有所帮助

您可能感兴趣的文章:
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  js 扫雷