本文实例为大家分享了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)
}
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。
原文链接:https://blog.csdn.net/a754334599/article/details/112969475
查看更多关于原生js实现自定义难度的扫雷游戏的详细内容...