1500字范文,内容丰富有趣,写作好帮手!
1500字范文 > 网页扫雷html css js 小游戏:扫雷 前端 H5 + CSS + JS

网页扫雷html css js 小游戏:扫雷 前端 H5 + CSS + JS

时间:2019-11-01 08:48:29

相关推荐

网页扫雷html css js 小游戏:扫雷 前端 H5 + CSS + JS

简介

很久以前刚接触前端的时候做的扫雷小游戏。虽然花了不少时间,但是整个做下来,还是很有收获的。

现在来看代码还是比较一般的,但也是一番心血。

特地分享出来,希望对需要的人有所帮助。适合初学者练习。

运行效果

运行效果

上方的表格左边格子表示剩余雷数,中间选择难度,右边计时。按下空格可以开始新游戏。

游戏中

游戏胜利

游戏失败

主体思路

随机生成雷的分布,用二维数组储存。同时遍历数组,生成数字,表示周围的雷的数目,同样储存在这个二维数组中。

生成div来表示格子,并且绑定一个坐标属性。与二维数组一一对应。

点击格子,根据坐标判断是否点到雷。是雷就游戏结束,不是雷就显示数字。

难点

1.点击到空白处的时候,会自动打开一大片格子。这个效果当时也是研究了很久。

最后的实现方法是:设置一个searched数组,储存已经点击或者查找过的坐标。然后点到空白处的时候,向上、下、左、右、右上、左上、右下、左下八个方向进行深度优先搜索,并将搜索过的格子的坐标储存到searched数组。搜索终止的条件是:遇到searched数组中的坐标,或者遇到数字,或者遇到边界。

(.10.3 更新:今天回顾这个代码,发现如果使用广度优先效果会更好,只用向上下左右四个方向搜索。)

2.玩过扫雷的都知道扫雷有一个操作是:在一个数字块上同时按下鼠标的左键和右键,如果操作目标周围插旗的格子数目等于数字的值,那么就能快速打开周围所有未标记的格子。

然而同时按下鼠标的操作js是没有的。

我的解决是方法是,计算鼠标点击的时间,如果2次点击时间间隔很小,那么就认定是同时按下左右键。调试之后,发现时间间隔设置为100毫秒的效果比较好。

代码

扫雷

.grid{

width: 18px;

height: 18px;

background-color: #0066cc;

float: left;

border: 1px black solid;

}

.mine{

width: 18px;

height: 18px;

float: left;

background-image:url(mine.png);

background-size: 18px 18px;

border: 1px black solid;

}

.flag{

width: 18px;

height: 18px;

float: left;

background-image:url(flag.png);

background-size: 18px 18px;

border: 1px black solid;

}

.number{

width: 18px;

height: 18px;

float:left;

text-align: center;

line-height: 20px;

border: 1px black solid;

background-color: palegoldenrod;

font-weight: bold;

}

#box{

height: 200px;

width: 200px;

border: black 5px solid;

position: absolute;

left:calc(50% - 100px);

top: 100px;

}

#info{

position: absolute;

left:calc(50% - 185px);

top: 30px;

text-align: center;

}

#tip{

position: absolute;

bottom: 160px;

right: calc(50% - 70px);

}

按下空格开始新游戏

var mineMap = new Array();

var searched = new Array();

var clickX;

var clickY;

var boxHeight;

var boxWidth;

var mineNumber;

var intervalid;

var diffi = 0;

var around = [[-1,-1],[-1,0],[-1,1],[0,-1],[0,1],[1,-1],[1,0],[1,1]];

var eleBox = document.getElementById('box');

var eleRestMine = document.getElementById('restMine');

//设置难度数值

diffiSet(diffi);

//设置Box

setBox();

//生成格子

createGrid();

//点击下拉框,选择不同难度

function btnChange(values){

diffiSet(parseInt(values));

clearGrid();

setBox();

createGrid();

}

//点击空格,开始新游戏

window.onkeydown = function (event){

if(event.keyCode == 32){

clearGrid();

createGrid();

}

}

//生成格子,并添加鼠标事件

function createGrid(){

// 生成格子

for (var i = 0 ; i < boxHeight ; i++){

for(var j = 0; j < boxWidth ; j++){

eleImg = document.createElement('div');

eleImg.className = 'grid';

//添加坐标

eleImg.attributes.coor = [i,j];

document.getElementById('box').appendChild(eleImg);

}

}

//剩余雷数

eleRestMine.innerText = mineNumber;

//添加鼠标事件

var eleGrid = document.getElementsByTagName('div');

var time1;

var time2;

for(var i = 1 ; i < eleGrid.length; i++){

// 阻止右键菜单

eleGrid[i].oncontextmenu = function(e){

e.preventDefault();

}

// 获取左右键点击number类的时间,实现左右键同时点击的功能

eleGrid[i].onmouseup = function(e){

if(e.button == 0 && this.className == 'number'){

time1 = new Date().getTime();

}

if(e.button == 2 && this.className == 'number'){

time2 = new Date().getTime();

}

// 左键点击

if(e.button == 0 && this.className == 'grid'){

clickX = this.attributes.coor[0];

clickY = this.attributes.coor[1];

// 如果searched为空,则生成扫雷图

if(searched.length == 0){

mineMap = showNumber(createMine(clickX,clickY,boxWidth,boxHeight,mineNumber));

console.log(mineMap);

// 启动计时器

var count = 0;

intervalid = setInterval(function(){

var second = ++count % 60;

var minute = parseInt(count / 60);

document.getElementById('time').innerText = minute + ':' + second;

},1000);

}

// 点到雷,游戏失败

if(mineMap[clickX][clickY] == '*'){

gameFail(eleGrid);

// 红雷

this.style.backgroundImage = 'url(o.png)';

}

// 普通点击

else{

this.className = 'number';

if (mineMap[clickX][clickY] != 0){

this.innerText = mineMap[clickX][clickY];

}

clickMap(mineMap,clickX,clickY);

showBlank(eleGrid);

}

console.log(searched);

// 判断胜利

if(searched.length == boxHeight * boxWidth - mineNumber){

eleRestMine.innerText = 0;

clearInterval(intervalid);

// 自动插上所有旗子

for(var j = 1; j < eleGrid.length; j++){

if(eleGrid[j].className == 'grid'){

eleGrid[j].className = 'flag';

}

}

console.log('你赢了');

}

}

// 点击滚轮 或者同时按下左右键

if((e.button == 1 || Math.abs(time1 - time2) < 100) && this.className == 'number'){

var flagNum = 0;

var tempArr = new Array();

clickX = this.attributes.coor[0];

clickY = this.attributes.coor[1];

for(var j = 0;j < 8; j++){

tempX = clickX + around[j][0];

tempY = clickY + around[j][1];

// 判断是否越界

if(tempX >= 0 && tempX <= boxHeight && tempY >= 0 && tempY <= boxWidth ){

// 查找周围格子

for(var k = 1; k < eleGrid.length; k++){

if(eleGrid[k].attributes.coor.toString() == [tempX,tempY].toString()){

// 统计旗子数目

if(eleGrid[k].className == 'flag'){

flagNum++;

}

// 统计grid坐标

else if(eleGrid[k].className == 'grid'){

tempArr.push([tempX,tempY]);

}

break;

}

}

}

}

// 如果旗数与数字相等,触发快捷操作

if(flagNum == mineMap[clickX][clickY]){

for(var k = 0;k < tempArr.length;k++){

// 引爆地雷,游戏失败

if(mineMap[tempArr[k][0]][tempArr[k][1]] == '*'){

gameFail(eleGrid);

}

clickMap(mineMap,tempArr[k][0],tempArr[k][1])

}

showBlank(eleGrid);

}

}

}

// 设置右键点击插旗

setRight(eleGrid[i]);

}

}

function setRight(ele){

ele.onmousedown = function(e){

if(e.button == 2){

if( this.className == 'grid'){

this.className = 'flag';

eleRestMine.innerText--;

}

else if(this.className == 'flag'){

this.className = 'grid';

eleRestMine.innerText++;

}

}

}

}

//设置难度数值

function diffiSet(diffi){

switch (diffi){

case 0:

boxWidth = 9;

boxHeight = 9;

mineNumber = 10;

break;

case 1:

boxWidth = 16;

boxHeight = 16;

mineNumber = 40;

break;

case 2:

boxWidth = 30;

boxHeight = 16;

mineNumber = 99;

break;

default:

break;

}

}

//设置box

function setBox(){

eleBox.style.height = 20 * boxHeight + 'px';

eleBox.style.width = 20 * boxWidth + 'px';

eleBox.style.left = 'calc(50% - ' + (20 * boxWidth / 2) + 'px)';

}

//生成雷的分布

function createMine(x,y,width,height,mineNum){

var mineArr = new Array()

for(var i=0 ; i < height ; i++){

mineArr[i]=new Array(i);

for(var j=0 ; j < width ; j++){

mineArr[i][j] = 0;

}

}

var count = 0;

while(count != mineNum){

randX = parseInt(Math.random()*height);

randY = parseInt(Math.random()*width);

if(randX != x && randY != y && mineArr[randX][randY] != '*'){

mineArr[randX][randY] = '*';

count++;

}

}

return mineArr;

}

//生成数字

function showNumber(mineArr){

for (var i = 0; i < mineArr.length ; i++){

for (var j = 0 ; j < mineArr[i].length ; j++){

if(mineArr[i][j] == 0){

var mineCount = 0;

for (var k = 0; k < 8; k++){

var aroundI = i + around[k][0];

var aroundJ = j + around[k][1];

if(aroundI >= 0 && aroundI < mineArr.length && aroundJ >= 0 && aroundJ < mineArr[0].length && mineArr[aroundI][aroundJ] == '*'){

mineCount++;

}

}

mineArr[i][j] = mineCount;

}

}

}

return mineArr;

}

//显示数字和空白区

function showBlank(eleGrid){

for (var i = 0; i < searched.length; i++){

for(var j = 1;j < eleGrid.length; j++){

if(searched[i].toString() == eleGrid[j].attributes.coor.toString()){

if(eleGrid[j].className == 'flag'){

searched.splice(i,1);

i--;

}

else{

eleGrid[j].className = 'number';

var temp = mineMap[eleGrid[j].attributes.coor[0]][eleGrid[j].attributes.coor[1]];

if(temp != 0){

eleGrid[j].innerText = temp ;

}

}

}

}

}

}

//点击

function clickMap(mineArr,x,y){

if(x < 0 || x >= boxHeight || y < 0 || y >= boxWidth ){

return;

}

for (var i = 0; i < searched.length; i++){

if(x+','+y == searched[i].toString()){

return;

}

}

if(mineArr[x][y] == '*'){

return ;

}

searched.push([x,y]);

if(mineArr[x][y] == 0){

for(var i = 0; i < 8; i++){

clickMap(mineArr,x + around[i][0],y + around[i][1]);

}

}

return ;

}

function gameFail(eleGrid){

clearInterval(intervalid);

// 所有雷都显示出来

for(var j = 0; j < boxHeight; j++){

for(var k = 0;k < boxWidth ;k++){

if( mineMap[j][k] == '*'){

for(var m = 1;m < eleGrid.length; m++){

if(j+','+k == eleGrid[m].attributes.coor.toString()){

eleGrid[m].className = 'mine';

}

// 将鼠标事件取消

eleGrid[m].onmouseup = "return false";

eleGrid[m].onmousedown = 'return false';

}

}

// 如果不是雷,但是插了旗子,则显示X

else{

for(var m = 1;m < eleGrid.length; m++){

if(j+','+k == eleGrid[m].attributes.coor.toString()){

if(eleGrid[m].className == 'flag'){

eleGrid[m].style.backgroundImage = 'url(X.png)';

}

break;

}

}

}

}

}

}

//清空searched数组、所有格子并重置计时器

function clearGrid(){

//重置时间

clearInterval(intervalid);

document.getElementById('time').innerText = '0:0';

// 清空搜索数组

searched.splice(0,searched.length);

//清空原有的格子

eleBox = document.getElementById('box');

eleBox.innerHTML = '';

}

需要用到的图片

mine.png

flag.png

o.png

X.png

图片均来自网络,如果侵权,请联系本人进行删除

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。