样式:目前将button效果替换成DIV+CSS实现,原本是利用伪类active实现点击效果,做出来后发现如果要实现,扩散效果就要每个元素都触发active,实在麻烦也不利于扩展,直接改成CSS3的动画效果,切换class的时候让div模拟被点击效果。
扩散效果实现:因为JS是单线程的,一开始的思路是在切换样式的时候进行休眠,实现点击扩散的效果,后发现样式切换不是异步执行的,会在方法完成后一口气执行,然后查了jq的运行机制和队列和异步,发现setTimeOut是一个异步操作,我将样式切换延迟执行,因为是递归每组延迟后会产生了扩散效果。
完成效果
采用DIV只适应布局。
<!DOCTYPE html>
<html>
<head>
<title>扫雷</title>
<meta charset="utf-8" />
<link rel="stylesheet" type="text/css" href="myGame.css">
</head>
<body>
<div class="main">
<div class="GameBox">
<div class="header">
<label>扫雷游戏--By七月流星</label>
</div>
<div class="content" οnkeyup="">
</div>
<div class="footer">
<!-- 计时 -->
<div class="timing">
<div class="timeImage"></div>
<div class="text_lable" id="time">0</div>
</div>
<!-- 计数-->
<div class="count">
<div class="mineImage"></div>
<div class="text_lable" id="countMine">0</div>
</div>
</div>
</div>
<div class="GameDescription">
<h2>控制面板</h2>
<ul class="setting">
<li>
<label>难度:</label>
<input type="radio" name="level" value="1" checked="checked"/>初级
<input type="radio" name="level" value="2"/>中级
<input type="radio" name="level" value="3"/>高级
<input type="radio" name="level" value="4" />自定义
</li>
<li class="customize">
<label>行:</label>
<input type="number" id="row"/>
</li>
<li class="customize">
<label>列:</label>
<input type="number" id="col"/>
</li>
<li class="customize">
<label>雷数:</label>
<input type="number" id="count"/>
</li>
<li>点击开始游戏,即可开始扫雷</li>
<li>左键翻开格子,右键插上红旗</li>
<!--<li>左右键同时点击数字,可翻开数字周围格子</li>-->
<li></li>
</ul>
<button style="height: 25px" id="start"> 开始游戏</button>
</div>
</div>
</body>
</html>
<script src="jquery-3.1.0.min.js">
</script>
<script type="text/javascript" src="mineGame.js"></script>
页面
* {
margin: 0;
padding: 0;
font-family: 微软雅黑;;
}
.main{
margin-top: 20px;
text-align: center;
display:-webkit-box;
-webkit-box-pack: center;
}
/*游戏说明*/
.GameDescription{
width: auto;
height: 50%;
background: #CCC;
border-radius: 5px;
box-shadow: 10px 10px 10px black;
padding: 20px;
margin: 30px;
}
/*li去掉点*/
li{
list-style: none;
margin-top: 5px;
}
.setting li label{
width: 50px;
text-align: left;
float: left;
}
.customize{
display: none;
}
/*以下是游戏框*/
.GameBox{
border: #000 3px outset;
left: 55%;
}
.GameBox .header,.GameBox .footer{
width:auto;
height: 30px;
border: 2px solid black;
margin: 10px 30px ;
text-align: center;
}
.GameBox .header label{
font-size: 22px;
font-weight: bold;
font-family: 仿宋;
}
.GameBox .footer .timing{
width: 100px;
height: 30px;
float: left;
margin-left: 20%;
}
.GameBox .footer .timing .timeImage{
float: left;
width: 26px;
height: 25px;
background: url("image/time.jpg") no-repeat scroll -2px -2px ;
border: 2px inset black;
-webkit-border-radius: 13px;
-moz-border-radius: 13px;
border-radius: 13px;
}
.GameBox .footer .timing .text_lable{
width: 40px;
height: 20px;
border: 2px #1B345D inset;
background: #848484;
float: left;
text-align: center;
font-weight: bold;
color: white;
border-radius: 6px;
margin-top: 3px;
margin-left: 8px;
}
.GameBox .footer .count{
width: 100px;
height: 30px;
float: right;
margin-right: 20%;
}
.GameBox .footer .count .mineImage{
float: right;
width: 26px;
height: 25px;
background: url("image/lei.jpg") no-repeat scroll -2px -2px ;
border: 2px inset black;
-webkit-border-radius: 13px;
-moz-border-radius: 13px;
border-radius: 13px;
}
.GameBox .footer .count .text_lable{
width: 40px;
height: 20px;
border: 2px #1B345D inset;
background: #848484;
float: right;
text-align: center;
font-weight: bold;
color: white;
border-radius: 6px;
margin-top: 3px;
margin-right: 8px;
}
div.content{
width:auto;
height: auto;
top: 50px;
border: #999 4px inset;
margin: 10px 30px ;
text-align: center;
padding-top: 1px;
}
div.hidden{
display: inline-block;
width: 40px; height: 40px;
line-height: 40px;
text-align: center;
vertical-align: middle;
border: 2px solid white;
border-right: 2px solid #848484;
border-bottom:2px solid #848484;
cursor: Pointer;
overflow: hidden;
background: #CECFCE;
}
div.hidden:hover{
background: #848484;
/*border-right: 1px solid #848484;*/
border-bottom:1px solid #848484;
}
/*红旗*/
div.flag{
display: inline-block;
width: 40px; height: 40px;
line-height: 40px;
text-align: center;
vertical-align: middle;
border: 2px solid white;
border-right: 2px solid #848484;
border-bottom:2px solid #848484;
cursor: Pointer;
overflow: hidden;
background: url("image/flag.png") no-repeat #CECFCE;
background-size: 40px;
}
/*炸弹爆炸*/
div.mineBoom{
display: inline-block;
width: 40px; height: 40px;
line-height: 40px;
text-align: center;
vertical-align: middle;
overflow: hidden;
cursor: default;
color:#00CD00;
border:2px solid #B4B4B4;
-webkit-animation:onClick 1s ;
-o-animation:onClick 1s ;
animation:onClick 1s ;
background: url("image/mineBoom.png") no-repeat white;
background-size: 40px;
}
div.mine{
display: inline-block;
width: 40px; height: 40px;
line-height: 40px;
text-align: center;
vertical-align: middle;
overflow: hidden;
cursor: default;
color:#00CD00;
border:2px solid #B4B4B4;
-webkit-animation:onClick 1s ;
-o-animation:onClick 1s ;
animation:onClick 1s ;
background: url("image/mine.png") no-repeat white;
background-size: 40px;
}
/*点击效果*/
div.hidden:active{
display: inline-block;
width: 40px; height: 40px;
line-height: 40px;
text-align: center;
vertical-align: middle;
overflow: hidden;
cursor: default;
background: #CECFCE;
color:#00CD00;
border:2px solid #B4B4B4;
-webkit-animation:onClick 1s ;
-o-animation:onClick 1s ;
animation:onClick 1s ;
font-size: 18px;
font-weight: bold;
}
div.show{
display: inline-block;
width: 40px; height: 40px;
line-height: 40px;
text-align: center;
vertical-align: middle;
overflow: hidden;
cursor: default;
background: #CECFCE;
color:#00CD00;
border:2px solid #B4B4B4;
-webkit-animation:onClick 1s ;
-o-animation:onClick 1s ;
animation:onClick 1s ;
font-size: 18px;
font-weight: bold;
}
@keyframes onClick {
0%{
display: inline-block;
width: 40px;
height: 40px;
line-height: 40px;
text-align: center;
vertical-align: middle;
cursor: default;
overflow: hidden;
border: 2px solid #848484;
background: #CECFCE;
color:#CECFCE;
}
70% {
display: inline-block;
width: 40px;
height: 40px;
border: 2px solid white;
border-right: 2px solid #848484;
border-bottom:2px solid #848484;
cursor: Pointer;
overflow: hidden;
background: #CECFCE;
color:#CECFCE;
}
}
css
/**
* 扫雷游戏js 七月Ne流星
* 9*9(初级),16*16(中级),16*30(高级)
*
*/
$(document).ready(function(){
mineGame.Layout();//初始化画布
});
var mineGame={
TIME:null,//计时对象
TIME_COUNT:0,//计时
MINE_COUNT:10,//雷数暂定10
Game_row:'9',//游戏行暂定9
Game_col:'9',//游戏列暂定9
MineList:new Array(this.Game_row),//游戏Model 初始化游戏行
init:function(){//游戏初始化
$(".content").html("");
this.Layout();
this.putBoom();
this.countBoom();
$("#countMine").html(this.MINE_COUNT);
//开始计时
mineGame.TIME_COUNT=0;
this.timeCount();
},
Layout:function(){ //布局
//并对数组进行初始化
for(let i=0;i<this.Game_row;i++){//行
this.MineList[i]=new Array(this.Game_col);//初始化游戏列
for(let j=0;j<this.Game_col;j++){//列
//对数组进行初始化
this.MineList[i][j]=0;
$(".content").append("<div class='hidden' id='"+i+"-"+j+"' ></div>");
//初始化DIV事件
this.intiEvent(i,j);
}
$(".content").append("<br/>");
}
},
//布雷
putBoom:function(){
let i=0,x,y;
for(;i<this.MINE_COUNT;){
//随机数
x=Math.floor(Math.random()*this.Game_row);
y=Math.floor(Math.random()*this.Game_col);
if(this.MineList[x][y]!=-1){//
this.MineList[x][y]=-1;
i++;
}
}
},
countBoom:function(){//算出炸弹旁边的数字
for(let row=0;row<this.Game_row;row++){//行
for(let col=0;col<this.Game_col;col++){
if(this.MineList[row][col] ==-1){//如果这格刚刚好是炸弹
//对它周围的数组+1
for(let x=row-1;x<row+2;x++){
for(let y=col-1;y<col+2;y++){
if(x >=0 && y >=0 && x<this.Game_row && y<this.Game_col){//判断出画布大小
if (this.MineList[x][y]!=-1) this.MineList[x][y]++;
}
}
}
}
}
}
},
openBtn:function(x,y,){//打开按钮
let id="#"+x+"-"+y;
let num=this.MineList[x][y];//当前数目
if (num==-1) {
mineGame.stopCount();//停止计时
$(id).attr('class','mineBoom');
this.gameOverEvent(x,y);
alert("Game Over!");
}else if(num>0){
this.removeBtn(id,num);
}else if(num==0){
this.removeBtn(id,num);
this.infected(x,y);//遍历
}
},
/**
*
* @param x
* @param y
* @param type 感染类型
* 0正常扩散
* 1为游戏结束 findMineAll
*/
infected:function(x,y){
for(let xtemp=x-1;xtemp<x+2;xtemp++){//判断行
for(let ytemp=y-1;ytemp<y+2;ytemp++){//判断列
if(xtemp >=0 && ytemp >=0 && xtemp<this.Game_row && ytemp<this.Game_col){//判断出画布大小
let id="#"+xtemp+"-"+ytemp;
if(this.MineList[xtemp][ytemp]!=-1){//如果不是炸弹
let num=this.MineList[xtemp][ytemp];//当前数目
if(xtemp==x && ytemp==y){
}else if(this.MineList[xtemp][ytemp] >0 && $(id).hasClass("hidden") ){
this.removeBtn(id,num);
}else if(this.MineList[xtemp][ytemp] == 0 && $(id).hasClass("hidden") ){// $(id).length > 0判断元素是否存在
this.removeBtn(id,num);
let _this=this;
setTimeout(function () { _this.openBtn(xtemp,ytemp); }, 120);//加入任务队列实现扩散效果。
}
}
}
}
}
},
gameOverEvent:function(){
let count=0;
for(let i=0;i<this.Game_row;i++){
for (let j=0;j<this.Game_col;j++){
let id="#"+i+"-"+j;
if(this.MineList[i][j]==-1 && !$(id).hasClass("mineBoom") ){//如果不是炸弹
setTimeout(function () {
$(id).attr('class','mine');
}, 120*count);//加入任务队列实现扩散效果。
count++;
}
}
}
},
removeBtn:function(id,num){//移除格子
$(id).attr('class','show'); f(num!=0)$(id).html(num);
},
//初始化事件
intiEvent:function (x,y) {
let id="#"+x+"-"+y;
/**
* 左键单机
* 右键
* 左右按键
*/
$(id).mousedown(function(e) {
//右键为3
if (3 == e.which) {
mineGame.isFlag(id);
} else if (1 == e.which) {
//左键为1
//是hidden状态的才能触发效果
if($(id).hasClass("hidden")) mineGame.openBtn(x,y);
} else if(e.which == 2){
//鼠标滚轮按下事件为2
}
});
$(id).dblclick(function(){
alert("双击了");
});
},//判断是否是flag
isFlag(id){
//如果是隐藏的那就加上旗帜,否则相反
if( $(id).hasClass("hidden")){
$(id).attr('class','flag');
mineGame.MINE_COUNT--;
}else if($(id).hasClass("flag") ){
$(id).attr('class','hidden');
mineGame.MINE_COUNT++;
}
$("#countMine").html(this.MINE_COUNT);
},
/**
*
* @param x
* @param y
* @param type 感染类型
* 0正常扩散
* 1为游戏结束 findMineAll
*/
scan:function(x,y){
for(let xtemp=x-1;xtemp<x+2;xtemp++){//判断行
for(let ytemp=y-1;ytemp<y+2;ytemp++){//判断列
if(xtemp >=0 && ytemp >=0 && xtemp<this.Game_row && ytemp<this.Game_col){
let id="#"+xtemp+"-"+ytemp;
if(this.MineList[xtemp][ytemp]!=-1){//如果不是炸弹
let num=this.MineList[xtemp][ytemp];//当前数目
if(xtemp==x && ytemp==y){
}else if(this.MineList[xtemp][ytemp] >0 && $(id).hasClass("hidden") ){
this.removeBtn(id,num);
}else if(this.MineList[xtemp][ytemp] == 0 && $(id).hasClass("hidden") ){// $(id).length > 0判断元素是否存在
this.removeBtn(id,num);
let _this=this;
setTimeout(function () { _this.openBtn(xtemp,ytemp); }, 120);//加入任务队列实现扩散效果。
}
}
}
}
}
},
//计时器
timeCount:function () {
mineGame.TIME_COUNT++;
$("#time").text( mineGame.TIME_COUNT);
mineGame.TIME=setTimeout("mineGame.timeCount()",1000);
},
//停止计时
stopCount:function () {
clearTimeout( mineGame.TIME);
}
};
$("#start").click(()=>{
let val=$("input[name=level]:checked").val();
switch (val){
case "1":
mineGame.Game_row=9;
mineGame.Game_col=9;
mineGame.MINE_COUNT=10;
break;
case "2":
mineGame.Game_row=16;
mineGame.Game_col=16;
mineGame.MINE_COUNT=40;
break;
case "3":
mineGame.Game_row=16;
mineGame.Game_col=30;
mineGame.MINE_COUNT=99;
break;
case "4":
mineGame.Game_row=$("#row").val();
mineGame.Game_col=$("#col").val();
mineGame.MINE_COUNT=$("#count").val();
break;
}
mineGame.init();
});
/**
* 显示自定义
*/
$("[name='level']").click(()=>{
let isShow=$(".customize").is(":hidden");//是否隐藏
let val=$("input[name=level]:checked").val();
if(val=='4'){
$(".customize").fadeIn(1000);
}else{
$(".customize").fadeOut(1000);
}
});
//阻止浏览器默认右键点击事件
document.oncontextmenu = function() {
return false;
}