扫雷html5简单初级,纯原生JS用面向对象class方法实现简易扫雷小游戏

Demo介绍

纯原生js 实现 且用ES6语法class写的扫雷小游戏:布局为10*10的网格,随机生成10-20个雷。

左键点击扫雷。右键标记该地方有雷。该demo下载下来复制到html文件中直接可以使用。不需要下载任何插件和引入任何框架。

小游戏源代码

Document

* {

padding: 0;

margin: 0;

}

.container {

width: 500px;

height: 500px;

background: rgb(150, 130, 130);

position: relative;

border: 5px solid #000;

margin: 0 auto;

}

class mineSweeping {

constructor() {

let container = this.$$(".container")

this.container = container;

this.mineWidth = 50;

this.mineHeight = 50;

this.mineNum =

(this.container.clientWidth * this.container.clientHeight) /

(this.mineWidth * this.mineHeight);

this.brr = [-11, -10, -9, -1, 1, 9, 10, 11];//

this.mineColNum = this.container.clientWidth / this.mineWidth;

this.createDiv()

this.createMine()

this.setNum()

}

// 创建div;

createDiv() {

for (let i = 0; i < this.mineNum; i++) {

let div = document.createElement("div");

// 添加样式

Object.assign(div.style, {

width: this.mineWidth - 2 + "px",

height: this.mineHeight - 2 + "px",

backgroundColor: "#ccc",

border: "1px solid #fff",

position: "absolute",

left: (i % this.mineColNum) * this.mineWidth + "px",

top: parseInt(i / this.mineColNum) * this.mineHeight + "px",

textAlign: "center",

lineHeight: "50px",

userSelect: "none"

});

// 添加自定义属性

div.mine = false // 是否为雷

div.show = false // 是否被点开

// 添加索引

div.index = i

// 添加坐标

div.pos = {

x: parseInt(i / this.mineColNum) + 1,

y: i % this.mineColNum + 1,

}

// 绑定事件

div.onclick = this.clickFn.bind(this)//左键事件

div.oncontextmenu = this.contextmenuFn//右键事件

this.container.appendChild(div);//追加小盒子

}

}

// 随机生成几个地雷

createMine() {

this.divs = this.container.children

let arr = []

for (let i = 0; i < this.getRandom(10, 20); i++) {

let x = this.getRandom(1, 11)

let y = this.getRandom(1, 11)

//随机获得10-20个得并随机放置,将左边存进数组

arr.push({

x, y

})

}

for (let j = 0; j < arr.length; j++) {

Array.from(this.divs).forEach(v => {

// console.log(v.pos);

if (arr[j].x === v.pos.x && arr[j].y === v.pos.y) {

v.mine = true

}

})

}

}

// 计算数字

setNum() {

for (let i = 0; i < this.divs.length; i++) {

if (this.divs[i].mine) {

continue;

}

let num = 0;

for (var j = 0; j < this.brr.length; j++) {

// 考虑最上面一行 - 不能-11 不能-10 不能-9

if (i < this.mineColNum && (this.brr[j] === -11 || this.brr[j] === -10 || this.brr[j] === -9)) {

continue;

}

// // 最左边一行过滤掉

if (i % this.mineColNum === 0 && (this.brr[j] === -11 || this.brr[j] === -1 || this.brr[j] === 9)) {

continue;

}

// 最下面一行

if (parseInt(i / this.mineColNum) === this.mineColNum - 1 && (this.brr[j] === 9 || this.brr[j] === 10 || this.brr[j] === 11)) {

continue;

}

// 最右边一行

if (i % this.mineColNum === this.mineColNum - 1 && (this.brr[j] === -9 || this.brr[j] === 1 || this.brr[j] === 11)) {

continue;

}

// console.log(this.divs[i + this.brr[j]].mine);

if (this.divs[i + this.brr[j]].mine) {

num++

// console.log(num);

}

}

// 把数字存起来

this.divs[i].num = num

}

}

//左键点击事件

clickFn(e) {

e = e || window.event;

let target = e.target || e.srcElement;

let divs = target.parentNode.children

if (target.mine) {//这里注意 要加target

for (let i = 0; i < divs.length; i++) {

divs[i].innerText = '';

divs[i].innerText = divs[i].num ? divs[i].num : ''

divs[i].style.backgroundColor = '#0f0'

}

for (let i = 0; i < divs.length; i++) {

if (divs[i].mine) {

divs[i].style.backgroundColor = 'red';

divs[i].innerText = '雷';

}

}

} else {

this.openAround(target.index)

}

}

//右键点击事件标记雷

contextmenuFn() {

this.style.backgroundColor = 'blue'

return false // 阻止默认事件

}

// 自动递归打开周围空格子

openAround(index) {

this.container.children[index].innerText = this.container.children[index].num

this.container.children[index].style.backgroundColor = '#0f0'

this.container.children[index].show = true

if (this.container.children[index].num === 0) {

this.container.children[index].style.backgroundColor = 'pink';

for (let j = 0; j < this.brr.length; j++) {

if (index < this.mineColNum && (this.brr[j] === -11 || this.brr[j] === -10 || this.brr[j] === -9)) {

continue;

}

// // 最左边一行过滤掉

if (index % this.mineColNum === 0 && (this.brr[j] === -11 || this.brr[j] === -1 || this.brr[j] === 9)) {

continue;

}

// 最下面一行

if (parseInt(index / this.mineColNum) === this.mineColNum - 1 && (this.brr[j] === 9 || this.brr[j] === 10 || this.brr[j] === 11)) {

continue;

}

// 最右边一行

if (index % this.mineColNum === this.mineColNum - 1 && (this.brr[j] === -9 || this.brr[j] === 1 || this.brr[j] === 11)) {

continue;

}

if (this.container.children[index + this.brr[j]].show) {

continue

}

this.openAround(index + this.brr[j])

}

}

}

// 获取随机数

getRandom(min, max) {

return Math.floor(Math.random() * (max - min) + min);

}

//获取节点

$$(tag, all = false) {

return all ? document.querySelectorAll(tag) : document.querySelector(tag);

}

};

new mineSweeping;

3.Demo代码分析

1.定义位置。动态创建div小格子。将格子动态设置样式。给盒子设置自定义属性mine属性判断是否是地雷属性。show则判断是否被打开

2. 给盒子坐标编号。同时根据坐标值随机生成10-20个地雷在随机位置。

3. 添加点击事件。左键点击扫雷。右键点击标记。同时追加盒子在画布container上

4. 给每个盒子计算数字。并且设置边缘检测。每个盒子8个位置 上 上右,上左,下,下右,下左的位置设置成一个brr[I]数组。周围有地雷。则数值加加。

5. 点击左键事件:点击盒子,点击后显示数字且变色。吧show属性改为true。如果是雷有mine属性其为true.直接打开所有盒子并游戏结束。否则调用展开方法openaround()

6. 展开方法其实是一个递归函数。通过检查是否是空是则继续检查四周几个位置是否为空。直到碰到周边有雷的位置。递归终止。这里要注意。展开的递归函数是要排除自己的,如果比如你向右递归。但改盒子的左边又是上一个递归的本身。那就会出现死循环。报错。

4.运行截图

025d708261b0493e9ef4fedce7cd51ae.jpg

79c28c96388048c884f2f2abdc5265a6.jpg

d3f0d4890b3b46c88d6eab5fd8ce6ca7.jpg

5.还需要改进或者可与完善的点

没有游戏结束中止和计分设置。可以在循环判断是否触雷那里改写成promise。then,catch方法则判定游戏获胜或结束。

可与将展开函数进行改造。改成一种DFC(图中的深度优先算法)

边界检测调用了几次,可以将其封装起来

周围值数组值可以未来根据盒子实际大小动态生成。

6.总结

写这种demo虽然工作中完全用不了,但对于js原生写法的和逻辑的锻炼以及js初学者有所帮助。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值