用jquery制作简单的扫雷小游戏

这是我自己在学习jquery时突发奇想做的一个扫雷小游戏,主要用到的知识是html5,css3,javascript和jquery,用到的jquery版本是jquery-1.6.4.min,代码文件和库文件大家可以点这个链接进行下载 :用jquery做的扫雷小游戏代码和资源。以下就是我在做这个小游戏时的主要思路和代码。

准备工作

首先我们需要明确游戏的规则并以此来决定功能,并且要知道自己希望游戏的界面是什么样的。我的这个扫雷小游戏是通过我的一个课堂实验改编的,原本它只是一堆可以变颜色的格子而以。

下面是我的思路
  1. 首先要在网页上放置81个格子,所有格子统一样式,但每个格子的id都由行号和列号组成,便于查找(我这里格子是用p标签制作的)。
  2. 在81个格子中放置10个地雷,地雷的坐标自然是记录在数组中,而不是体现在格子中。
  3. 每个格子中放一个span标签元素,用于记录数字,默认为0,数字的作用代表周围地雷数,玩过扫雷的应该都知道。
  4. 给每一个span标签添加数字,方法是根据地雷的位置来判断,使得每个地雷周围的span标签元素的值加1。
  5. 添加格子的鼠标单击事件,当格子被点击时,进行判定,若该格子为地雷,则游戏结束,若不是地雷,则翻开格子(这里情况比较复杂,下面会详解,因为这涉及到地雷的自动翻开格子,就是你点的格子没有任何数字时,游戏会帮你自动翻开周围的格子一直到被数字包围)。

具体功能实现

先来定义好一些需要的样式(style),这里我们主要的是格子(p标签)的样式,格子被点开后的样式以及地雷被点开后的样式。这里我把正常被点开的格子的样式放在highlight类中,设置背景色为金色,而地雷被点开的颜色为红色,放在lowlight类中。p标签只有设置一点外边距和边框宽度就好了,然后设置浮动为左浮动。因为我们需要把81个格子变成9*9排列,每一排格子都要放在一个div中,所以还有设置一个div样式。

<style type="text/css">
	body {
    
     width:760px; }
	div {
    
     margin:5px 10px; clear:both; }
	p {
    
     float:left; margin:3px; width:30px; height:30px; border:2px solid black; text-align:center; display:table;}
	.highlight {
    
     background-color:gold; }
	.lowlight{
    
    background-color:red;}
</style>

然后引入一下jquery的库文件。记住要把jquery文件和网页文件放在同一个文件夹内。

<script src="jquery-1.6.4.min.js" type="text/javascript"></script>

定义好样式后,就可以在页面上放置格子了,这里我用了两个for循环,第一个用来产生div(代表一行),第二个用来在div中产生p(格子)。

//产生一个9*9的格子地图
		for(var i=0;i<9;i++){
    
    
			$("body").append("<div id='"+i+"i'></div>");
			for(var j=0;j<9;j++){
    
    
				$("#"+i+"i").append("<p id='"+i+"i"+j+"j'><span style='display:table-cell;vertical-align:middle;visibility:hidden;'>0</span></p>");
			}
		}

哈哈,是不是感觉span标签的定义很长,这里先解释一下为什么要给span标签这么多style的属性,其中display:table-cell表示span会作为表格单元格显示,而span的父元素p标签的样式中,定义了display:table(见第一段代码),这两个display的属性和vertical-align能够使得span标签垂直居中显示,说白了这个属性是为了好看用的。visibility:hidden,这个属性是为了隐藏span标签,为什么要隐藏?因为在我们点格子之前可不希望看到格子里的数字,数字代表着周围地雷数。

这样我们就把格子定义好了,然后就是产生10 个地雷了,这里我定义了两个一维数组,分别用于存储地雷的行号和列号(从0~8)。其中Math.floor()函数用于产生整数,Math.random()用于产生随机数。这两个函数同时使用用于产生随机整数。

var aa=[0];	//地雷横坐标
		var bb=[0];	//地雷纵坐标
		var flag=true;	//判断是否产生了重复坐标
		//产生不重复的10个整数并存入aa,bb数组中,作为地雷坐标
		for(var i=0;i<10;i++){
    
    
			aa[i]=Math.floor(Math.random()*9);
			bb[i]=Math.floor(Math.random()*9);
			for(var j=0;j<i;j++){
    
    
				if(aa[i]==aa[j]&&bb[i]==bb[j]){
    
    
					i--;
					flag=false;
					break;
				}
			}
			if(flag==false){
    
    
				flag=true;
			}else{
    
    
				console.log(aa[i],bb[i]);
			}
		}

这里console.log()函数的作用仅用于调试,在测试时可以打开网页,按F12在Console中查看产生的地雷坐标

地雷产生后,就需要根据地雷坐标,给周围的span元素赋值了,由于一开始所有span元素的值都为0,所以我们要做的就是给地雷周围的每一个span元素的值+1。当然,我们需要先获取span元素的值,然后+1,再赋值给它。这里代码不复杂,只是看着长而已。

//给每个地雷周围的格子加数字,数字代表周围地雷数
		var z=[""];			//记录地雷周围p的id;
		for(var i=0;i<10;i++){
    
    
			x=aa[i];
			x1=x-1;
			x2=x+1;
			y=bb[i];
			y1=y-1;
			y2=y+1;
			//获取每个p的id;
			z[0]="#"+x1+"i"+y1+"j";
			z[1]="#"+x1+"i"+y+"j";
			z[2]="#"+x1+"i"+y2+"j"
			z[3]="#"+x+"i"+y1+"j";
			z[4]="#"+x+"i"+y2+"j";
			z[5]="#"+x2+"i"+y1+"j";
			z[6]="#"+x2+"i"+y+"j";
			z[7]="#"+x2+"i"+y2+"j";
			$(z[0]).children().html(Number($(z[0]).children().html())+1);
			$(z[1]).children().html(Number($(z[1]).children().html())+1);
			$(z[2]).children().html(Number($(z[2]).children().html())+1);
			$(z[3]).children().html(Number($(z[3]).children().html())+1);
			$(z[4]).children().html(Number($(z[4]).children().html())+1);
			$(z[5]).children().html(Number($(z[5]).children().html())+1);
			$(z[6]).children().html(Number($(z[6]).children().html())+1);
			$(z[7]).children().html(Number($(z[7]).children().html())+1);
		}

最后一步是重中之重,就是给p标签添加点击事件了。下面我先展示一下p标签点击事件的流程图。
在这里插入图片描述
这里下半部分的逻辑有点复杂,我可能没有清晰的表达出来,总而言之就是一个递归调用的过程,当检测函数checkBlank()发现被点击格子周围的某个格子的值为0时,会对这个格子调用checkBlank()函数,重新进行检测。打个比方,你点了一个值为0的格子(这是主角),checkBlank()会先检查该格子左上角的格子,如果左上角的格子的值也为0,且没被翻开,也不是地雷,那么左上角的格子就成了一个新的主角,checkBlank()函数会先对新的主角进行检测了。以此来模拟扫雷时,点击了一个周围没雷的格子,然后系统会自动帮你翻开所有的空白格子。下面是该功能的代码。

var zz=[""];		//记录地雷所在p的id
		for(var i=0;i<10;i++){
    
    
			zz[i]=aa[i]+"i"+bb[i]+"j";
		}
		//p标签点击事件
		jQuery("p").click(function(){
    
    		
			var k=$(this).parent().index();		//p所在行
			var n=$(this).attr("id");			//p的id
			var	t=$(this).parent().children("#"+n+"").index();	//p所在列
			var gameOver=false;			//游戏结束的标志
			for(var i=0;i<10;i++){
    
    
				if(k==aa[i]&&t==bb[i]){
    
    
					gameOver=true;
				}
			}
			if(gameOver==true){
    
    	
				for(var i=0;i<10;i++){
    
    
					$("#"+aa[i]+"i"+bb[i]+"j").addClass("lowlight");
				}
				setTimeout(alertGame,100);
				function alertGame(){
    
    
					alert("你输了");
					setTimeout(window.location.reload());		//刷新页面
				}
			}else{
    
    
				$(this).children().css("visibility","visible");		//显示格子周围地雷数
				$(this).addClass("highlight");		//设置格子背景色为高亮
				if(Number($(this).children(0).html())==0){
    
    
					var currentBlank=$(this);
					checkBlank(currentBlank);
				}
			}
			
			//检测空白格子是否需要被翻开
			function checkBlank(aBlank){
    
    
				var a=aBlank.index();
				var b=a-1;
				var c=a+1;
				var d=aBlank.parent().prev().children(":eq("+b+")").children();
				judge(d);
				d=aBlank.parent().prev().children(":eq("+a+")").children();
				judge(d);
				d=aBlank.parent().prev().children(":eq("+c+")").children();
				judge(d);
				d=aBlank.parent().next().children(":eq("+b+")").children();
				judge(d);
				d=aBlank.parent().next().children(":eq("+a+")").children();
				judge(d);
				d=aBlank.parent().next().children(":eq("+c+")").children();
				judge(d);
				d=aBlank.prev().children();
				judge(d);
				d=aBlank.next().children();
				judge(d);
				//主要的判断函数,若满足两个条件则可以被翻开,1.格子内span元素的visibility属性为hidden. 2.格子不是地雷
				function judge(e){
    
    
					if(Number(e.html())!=0&&e.css("visibility")=="hidden"&&checkBoom(e.parent())==false){
    
    
						e.css("visibility","visible");
						e.parent().addClass("highlight");
					}else if(Number(e.html())==0&&e.css("visibility")=="hidden"&&checkBoom(e.parent())==false){
    
    
						e.css("visibility","visible");
						e.parent().addClass("highlight");
						checkBlank(e.parent());
					}	
				}
				function checkBoom(f){
    
    
					var g=f.attr("id");
					var gg=false;
					for(var i=0;i<10;i++){
    
    
						if(g==zz[i]){
    
    
							gg=true;
							break;
						}
					}
					return gg;
				}
			}
		});

写到这里,我们的扫雷游戏就完成了,不过这个小游戏还是有很多地方可以完善的,我没有继续做下去,大家可以自己去尝试的做一下。比如游戏胜利条件的判断,标注地雷的功能。大家如果需要资源的可以点下面这个链接进行下载。
用jquery做的扫雷小游戏代码和资源
以下是完整代码

<!DOCTYPE html >
<html>
<head>
<meta charset="utf-8"/>
<title>扫雷</title>
<style type="text/css">
	body {
    
     width:760px; }
	div {
    
     margin:5px 10px; clear:both; }
	p {
    
     float:left; margin:3px; width:30px; height:30px; border:2px solid black; text-align:center; display:table;}
	.highlight {
    
     background-color:gold; }
	.lowlight{
    
    background-color:red;}
</style>
<script src="../jquery-1.6.4.min.js" type="text/javascript"></script>
<script>
	jQuery(document).ready(function(){
    
    
		//产生一个9*9的格子地图
		for(var i=0;i<9;i++){
    
    
			$("body").append("<div id='"+i+"i'></div>");
			for(var j=0;j<9;j++){
    
    
				$("#"+i+"i").append("<p id='"+i+"i"+j+"j'><span style='display:table-cell;vertical-align:middle;visibility:hidden;'>0</span></p>");
			}
		}
		var aa=[0];	//地雷横坐标
		var bb=[0];	//地雷纵坐标
		var flag=true;	//判断是否产生了重复坐标
		//产生不重复的10个整数并存入aa,bb数组中,作为地雷坐标
		for(var i=0;i<10;i++){
    
    
			aa[i]=Math.floor(Math.random()*9);
			bb[i]=Math.floor(Math.random()*9);
			for(var j=0;j<i;j++){
    
    
				if(aa[i]==aa[j]&&bb[i]==bb[j]){
    
    
					i--;
					flag=false;
					break;
				}
			}
			if(flag==false){
    
    
				flag=true;
			}else{
    
    
				console.log(aa[i],bb[i]);
			}
		}
		//给每个地雷周围的格子加数字,数字代表周围地雷数
		var z=[""];			//记录地雷周围p的id;
		for(var i=0;i<10;i++){
    
    
			x=aa[i];
			x1=x-1;
			x2=x+1;
			y=bb[i];
			y1=y-1;
			y2=y+1;
			//获取每个p的id;
			z[0]="#"+x1+"i"+y1+"j";
			z[1]="#"+x1+"i"+y+"j";
			z[2]="#"+x1+"i"+y2+"j"
			z[3]="#"+x+"i"+y1+"j";
			z[4]="#"+x+"i"+y2+"j";
			z[5]="#"+x2+"i"+y1+"j";
			z[6]="#"+x2+"i"+y+"j";
			z[7]="#"+x2+"i"+y2+"j";
			$(z[0]).children().html(Number($(z[0]).children().html())+1);
			$(z[1]).children().html(Number($(z[1]).children().html())+1);
			$(z[2]).children().html(Number($(z[2]).children().html())+1);
			$(z[3]).children().html(Number($(z[3]).children().html())+1);
			$(z[4]).children().html(Number($(z[4]).children().html())+1);
			$(z[5]).children().html(Number($(z[5]).children().html())+1);
			$(z[6]).children().html(Number($(z[6]).children().html())+1);
			$(z[7]).children().html(Number($(z[7]).children().html())+1);
		}
		var zz=[""];		//记录地雷所在p的id
		for(var i=0;i<10;i++){
    
    
			zz[i]=aa[i]+"i"+bb[i]+"j";
		}
		//p标签点击事件
		jQuery("p").click(function(){
    
    		
			var k=$(this).parent().index();		//p所在行
			var n=$(this).attr("id");			//p的id
			var	t=$(this).parent().children("#"+n+"").index();	//p所在列
			var gameOver=false;			//游戏结束的标志
			for(var i=0;i<10;i++){
    
    
				if(k==aa[i]&&t==bb[i]){
    
    
					gameOver=true;
				}
			}
			if(gameOver==true){
    
    	
				for(var i=0;i<10;i++){
    
    
					$("#"+aa[i]+"i"+bb[i]+"j").addClass("lowlight");
				}
				setTimeout(alertGame,100);
				function alertGame(){
    
    
					alert("你输了");
					setTimeout(window.location.reload());		//刷新页面
				}
			}else{
    
    
				$(this).children().css("visibility","visible");		//显示格子周围地雷数
				$(this).addClass("highlight");		//设置格子背景色为高亮
				if(Number($(this).children(0).html())==0){
    
    
					var currentBlank=$(this);
					checkBlank(currentBlank);
				}
			}
			
			//检测空白格子是否需要被翻开
			function checkBlank(aBlank){
    
    
				var a=aBlank.index();
				var b=a-1;
				var c=a+1;
				var d=aBlank.parent().prev().children(":eq("+b+")").children();
				judge(d);
				d=aBlank.parent().prev().children(":eq("+a+")").children();
				judge(d);
				d=aBlank.parent().prev().children(":eq("+c+")").children();
				judge(d);
				d=aBlank.parent().next().children(":eq("+b+")").children();
				judge(d);
				d=aBlank.parent().next().children(":eq("+a+")").children();
				judge(d);
				d=aBlank.parent().next().children(":eq("+c+")").children();
				judge(d);
				d=aBlank.prev().children();
				judge(d);
				d=aBlank.next().children();
				judge(d);
				//主要的判断函数,若满足两个条件则可以被翻开,1.格子内span元素的visibility属性为hidden. 2.格子不是地雷
				function judge(e){
    
    
					if(Number(e.html())!=0&&e.css("visibility")=="hidden"&&checkBoom(e.parent())==false){
    
    
						e.css("visibility","visible");
						e.parent().addClass("highlight");
					}else if(Number(e.html())==0&&e.css("visibility")=="hidden"&&checkBoom(e.parent())==false){
    
    
						e.css("visibility","visible");
						e.parent().addClass("highlight");
						checkBlank(e.parent());
					}	
				}
				function checkBoom(f){
    
    
					var g=f.attr("id");
					var gg=false;
					for(var i=0;i<10;i++){
    
    
						if(g==zz[i]){
    
    
							gg=true;
							break;
						}
					}
					return gg;
				}
			}
		});	
	});
</script>
</head>
<body>
	
</body>
</html>

猜你喜欢

转载自blog.csdn.net/zhulong16/article/details/102321210