很久木来博客园了,今天献上周末撸的扫雷游戏咯~~

下面先上效果图

上图为最终效果,界面没美化,有点丑将就将就,,,,哈哈

不多说,上代码看注释已经注释好多,扫雷主要难度在于计算但前点击周围你的安全区域,我的想法是:递归循环计算当前点击的上、下、左、右4个格子,如果遇到空白则继续,如果遇到周围有雷则停止。

由中心点往外扩散,在扩散中肯定回遇到已经处理过的格子,则跳过continue。。。。

html代码

<!doctype html>
<html>
<head>
	<meta charset="UTF-8">
	<title>扫雷游戏</title>
	<style>

		*{padding:0;margin:0;}

		.main{
			margin: 10px 0 0 10px;
		}

		.head{

		}

		.body{
			margin: 10px;
		}

		.minefield,
		.minefield tr,
		.minefield td{border:1px solid #000;}

		.minefield td{
			color:#00f;
			width: 20px;
			height: 20px;
			text-align: center;
			cursor: pointer;
		}

		/*.minefield td:hover{background-color:#ccc;}*/

		/*初始化颜色*/
		.init-color{background-color: #ddd;}
		/*打开颜色*/
		.oper-color{background-color: #fff;}
		/*标志颜色*/
		.flag-color{background-color: #00FF00;}
		/*雷颜色*/
		.mine-color{background-color: #f00;}

		fieldset{
			padding: 5px;
			width: 800px;
			font-size: 14px;
		}
		legend{
			font-size: 12px;
			color: #00f;;
		}

		.info{
			font-size: 12px;
			color: #00f;
		}
	</style>
</head>
<body>
	<div class="main">
		<div class="head">
			<fieldset>
				<legend>难度</legend>
				<fieldset>
					<legend><input type="radio" name="define" checked="checked" value="1"/>系统定义</legend>
					<label title="9x9,10"><input type="radio" name="diff" checked="checked" value="1"/>初级</label>
					<label title="16x16,40"><input type="radio" name="diff" value="2"/>中级</label>
					<label title="16x30,99"><input type="radio" name="diff" value="3"/>高级</label>
				</fieldset>
				<fieldset>
					<legend><input type="radio" name="define" value="0"/>自定义</legend>
					<label>行数(9~24):<input type="text" id="rowNum" value="9"/></label>
					<label>列数(9~30):<input type="text" id="colNum" value="9"/></label>
					<label>雷数(10~668):<input type="text" id="mineNum" value="10"/></label>
				</fieldset>
				<button type="button" id="start">走你</button>

				<div class="body" id="minefield"></div>
				<div class="info">
					<label>用时:<span id="useTime">0</span>秒</label>    <span id="gameEnd"></span>
				</div>
			</fieldset>
		</div>

	</div>

	<script src="jquery-1.9.1.min.js"></script>     <script src="minefield.jquery.js"></script>
	<script>
        $(function(){
		  $(‘#start‘).bind(‘click‘, function(){
			var data = {},
			  define = $(‘input[name="define"]:checked‘).val(),
			  diff = $(‘input[name="diff"]:checked‘).val(),
			  rowNum = $.trim($(‘#rowNum‘).val()),
			  colNum = $.trim($(‘#colNum‘).val()),
			  mineNum = $.trim($(‘#mineNum‘).val());

		    // 选择系统定义
		    if(define == ‘1‘){
			  switch(diff){
				case ‘1‘:
					data = {
						rowNum: 9,
						colNum: 9,
						mineNum: 10
					}
				     break;
			       	case ‘2‘:
					data = {
				  	  rowNum: 16,
					  colNum: 16,
					  mineNum: 40
					}
					break;
			      case ‘3‘:
					data = {
					  rowNum: 16,
					  colNum: 30,
					  mineNum: 99
					}
					break;
			   }
			}else{
			  // 选择自定义
			  if(9 > rowNum || rowNum > 24){
				alert(‘o no~~最多只能是24行,9~24!!‘);
				return ;
			  }
			  if(9 > colNum || colNum > 30){
				alert(‘擦最多只能是30列,9~30!!‘);
				return ;
			  }                // 这里根据列、行计算最多雷数怎么计算?希望高手指点一二~~
			  if(9 > mineNum || mineNum > 668 || mineNum > (rowNum*colNum-1) ){
				alert(‘干,这是要死的节奏啊,弄这么多雷!!‘);
				return ;
			  }
	      	  if(rowNum && !isNaN(rowNum)){
				data.rowNum = parseInt(rowNum);
			  }
			  if(colNum && !isNaN(colNum)){
				data.colNum = parseInt(colNum);
		       }
			  if(mineNum && !isNaN(mineNum)){
				data.mineNum = parseInt(mineNum);
			  }
			}
			              // 清除下面计时器              clearTimeout(timeFlag);
			$(‘#gameEnd‘).empty();              // 游戏启动时调用
			data.gameStart = function(){
				useTime(1);
				$(‘#gameEnd‘).html(‘进行中....加油~使劲~‘);
			}

			data.gameEnd = function(flag){
				clearTimeout(timeFlag);
				var time = $(‘#useTime‘).text();
				var str = ‘‘;
				if(flag){                       // 游戏通过后可以根据条件给玩家定义一些级别
					if(time <= 20){
					  str = ‘你雷逼‘;
					}
					if(20 < time < 50){
					  str = ‘你牛逼!‘;
					}
					if(50<=time<100){
					  str = ‘恭喜你过关!‘;
					}
					if(time >= 100){
					  str = ‘终于过了,不容易啊~~~‘;
					}
					$(‘#gameEnd‘).html(‘<span style="color:#0f0;">‘+str+‘</span>‘);
				}else{
					$(‘#gameEnd‘).html(‘<span style="color:#f00;">真是彩笔~~</span>‘);
				}
			}              // 启动游戏
			$(‘#minefield‘).minefield(data);
		});

		// 初始化
		$(‘#start‘).click();

		});
		         // 计时器
		var timeFlag;
		function useTime(time){
			$(‘#useTime‘).text(time);

			timeFlag = setTimeout(function(){
				useTime(time+1);
			},1000);
		}

	</script>
</body>
</html>

minefield.jquery.js 脚本代码

         /**
		*	minefield.jquery.js
		*	扫雷插件
		*	CBQ [email protected]
		*/
		(function(window, $){

			//扩展array indexOf方法
			if(!Array.prototype.indexOf){
				Array.prototype.indexOf = function(v){
					var i , len;
					for(i=0,len=this.length;i<len;i++){
						if(this[i] == v){
							return i;
						}
					}

					return -1;
				}
			}

			function Minefield( options, dom ){
				this._default = {
					init: true,   // 是否初始化
					rowNum: 9,   // 多少行
					colNum: 9,   // 多少列
					mineNum: 10,   // 累的个数
					gameStart: function(){},
					gameEnd: function(){}
				};
				this.settings = $.extend(true, this._default, options); // 用户配置
				this.$dom = $(dom);  // 当前插入扫雷dom对象
				this.$table = $(‘<table class="minefield" border="1" cellpadding="1" cellspacing="1"><tbody></tbody></table>‘); // 扫雷对象
				this.mineData = []; // 雷分布数组(包括所有对象)
				this.minePosition = []; // 存储雷区位置(只有雷区)
				this.mineNumData = []; // 每个格子的雷数
				this.gameStart = false;
				this.gameOver = false;

				this.tempSafeArea = [];

				this._init(); // 初始化
			}

			// 扩展prototype对象
			$.extend(Minefield.prototype,{
				// 初始化函数
				_init: function(){
					var me = this;
					// 创建地雷分布区域
					me._createMineData();
					// 创建用户交互界面
					me._createGame();
					// 创建事件监听
					me._addEvent();
				},
				// 创建雷的分布区域
				_createMineData: function(){
					var me=this,
						i=0, j=0,
						rowNum = me.settings.rowNum,
						colNum = me.settings.colNum,
						max = rowNum * colNum,
						mineNum = me.settings.mineNum,
						mineData = me.mineData,
						minePosition = me.minePosition,
						mine;
					for(i=0; i<max; i++){
						mineData.push(0);
					}

					// 生成雷
					for(j=0;j<mineNum;){
						mine = Math.floor(Math.random()*(max-1));
						//如果生成的雷已经存在,则重新生成
						if(minePosition.indexOf(mine) == -1){
							minePosition.push(mine);
							mineData[mine] = 1;
							j++;
						}
					}

				},
				// 创建用户交互界面
				_createGame: function(){
					var me=this,
						i=0, j=0,index = 0,
						rowNum = me.settings.rowNum,
						colNum = me.settings.colNum,
						mineData = me.mineData,
						mineNumData = me.mineNumData,
						trs=[], tds=[],
						isMine = 0
						;

					for(i=0; i<rowNum; i++){
						tds.splice(0, colNum);
						for(j=0; j<colNum; j++){
							isMine = mineData[index];
							// 获取每个格子的旁边的地雷数量,如果格子本身就是地雷则为 -1
							if(isMine == 1){
								mineNumData[index] = -1;
							}else{
								mineNumData[index] = me.getMineNumber(j, i);
							}

							// tds.push(‘<td class="init-color"> ‘+index+‘,‘+isMine+‘,‘+mineNumData[index]+‘</td>‘);
							// tds.push(‘<td class="init-color"> ‘+isMine+‘,‘+mineNumData[index]+‘</td>‘);
							tds.push(‘<td class="init-color"> </td>‘);
							index++;
						}

						trs.push(‘<tr>‘ + tds.join(‘‘) + ‘</tr>‘);
					}

					me.$table.find(‘tbody‘).append(trs.join(‘‘));
					me.$dom.empty().append(me.$table);
				},
				// 绑定事件
				_addEvent: function(){
					var me = this;                       // 只为table添加事件,这样可以减少多余不必要的事件,如果给每个格子添加点击事件那要污染多少
					me.$table
						.bind(‘click‘, function(e){
							var target = e.target, $currTr,
								currIndex,mineNum,
								name = target.nodeName.toLowerCase(),
								allSafeArea;

							var $currTd;
							if(name == ‘td‘){                                      // 如果游戏已经结束则无需继续往下走
								if(!me.gameStart){
									me.gameStart = true;
									me.settings.gameStart ? me.settings.gameStart():‘‘;
								}
								$currTd = $(target);  // 当前点击格子
								$currTr = $currTd.parent(); // 当前点击行                                      // 如果格子已经被点击过,则无需再做操作
								if($currTd.hasClass(‘open-color‘) || $currTd.hasClass(‘flag-color‘) || me.gameOver){
									return ;
								}
								// 计算当前点击位置  currIndex = (当前行 * 列数) + 当前位置 ,因为使用table布局所以点击没行格子都会从0开始
								currIndex = ($currTr.index() * me.settings.colNum) + $currTd.index();
								mineNum = me.mineNumData[currIndex];
								switch(mineNum){
									case 0 :  // 安全区
										// 清空安全区,重新计算
										me.tempSafeArea.splice(0,me.tempSafeArea.length);                                               // 计算当前点击格子旁边的安全格子
										me._getLRUDSafeArea($currTd.index(), $currTr.index());                                               // 修改安全格子背景颜色
										me._setSafeBgColor( me.tempSafeArea );

										if(me._isWin()){
											// 获胜事件
											me.settings.gameEnd ? me.settings.gameEnd(true):‘‘;
										}
										break;
									case -1 : // 雷区
										$currTd.addClass(‘mine-color‘);
										me.gameOver = true;
										me._showMine();
										// 失败事件
										me.settings.gameEnd ? me.settings.gameEnd(false):‘‘;
										break;
									default: // 其他
										$currTd.removeClass(‘init-color‘).addClass(‘open-color‘).text(mineNum);
										if(me._isWin()){
											// 获胜事件
											me.settings.gameEnd ? me.settings.gameEnd(true):‘‘;
										}
									break;
								}

							}
						})
						.bind(‘contextmenu‘, function(e){ // 右击事件,用于标识自己认为的雷区,或解除
							e.stopPropagation();
							var target = e.target,
								name = target.nodeName.toLowerCase();

							var $currTd;

							if(name == ‘td‘ && !me.gameOver){
								$currTd = $(target);

								if( $currTd.hasClass(‘init-color‘) ){
									$currTd.removeClass(‘init-color‘).addClass(‘flag-color‘);
									return false;
								}
								if( $currTd.hasClass(‘flag-color‘) ){
									$currTd.removeClass(‘flag-color‘).addClass(‘init-color‘);
									return false;
								}
							}

							return false;
						})
						;
				},
				// 获取每个单元的上、下、左、右、左上、右上、左下、右下八个位置的雷分布
				getMineNumber: function( x, y ){
					var me = this,
						mineData = me.mineData,
						rowNum = me.settings.rowNum,
						colNum = me.settings.colNum,
						index = y * colNum + x,
						upNum = parseInt(index)-parseInt(colNum),
						downNum = parseInt(index)+parseInt(colNum),
						mineNum = 0;

					// 获取左值,如果是第一个值则不计算
					if(x > 0 && mineData[index - 1] == 1){
						mineNum += 1;
					}
					// 获取右值,如果是每行的最后一个值则不计算
					if(x<(colNum-1) && mineData[index + 1] == 1){
						mineNum += 1;
					}
					// 获取上方值,如果是第一行则不计算
					if(y>0 && mineData[upNum] == 1){
						mineNum += 1;
					}
					// 获取下方值,如果是第一行则不计算
					if(y<(rowNum-1) && mineData[downNum] == 1){
						mineNum += 1;
					}
					// 获取左上角一个值,如果是第一个值则不计算
					if(x>0 && y>0 && mineData[upNum-1] == 1){
						mineNum += 1;
					}
					// 获取右上角一个值,如果是第一个值则不计算
					if(x<(colNum-1) && y>0 && mineData[upNum+1] == 1){
						mineNum += 1;
					}
					// 获取左下角一个值,如果是第一个值则不计算
					if(x>0 && y<(rowNum-1) && mineData[downNum-1] == 1){
						mineNum += 1;
					}
					// 获取右下角一个值,如果是第一个值则不计算
					if(x<(colNum-1) && y<(rowNum-1) && mineData[downNum+1] == 1){
						mineNum += 1;
					}

					return mineNum;
				},                   // 获取当前格子的上(Up)、下(Down)、左(Left)、右(Right)安全区
				_getLRUDSafeArea: function(x, y){
					var me = this,
						mineNumData = me.mineNumData,
						rowNum = parseInt(me.settings.rowNum),
						colNum = parseInt(me.settings.colNum),
						index = y * colNum + x,
						mineNum;
					// 如果已经登记过的安全区,则不再查看
					if(me.tempSafeArea.indexOf(index) != -1){
						return ;
					}

					mineNum = mineNumData[index];
					// 记录安全区
					me.tempSafeArea.push(index);
					// 如果但前安全区周边没有任何危险,则查看上下左右区域是否安全
					if(mineNum == 0 ){
						// 左边
						if(x>0){
							me._getLRUDSafeArea(x-1, y);
						}
						// 右边
						if(x<(colNum-1)){
							me._getLRUDSafeArea(x+1, y);
						}
						// 上边
						if(y>0){
							me._getLRUDSafeArea(x, y-1);
						}
						// 下边
						if(y<(rowNum-1)){
							me._getLRUDSafeArea(x, y+1);
						}
					}

				},
				_setSafeBgColor: function( allSafeArea ){
					var me = this,
						mineNumData = me.mineNumData,
						i, len,
						$tds = me.$table.find(‘td‘),
						$td;

					for(i=0,len=allSafeArea.length; i<len; i++){
						$td = $($tds.get(allSafeArea[i]));
						if($td.hasClass(‘init-color‘)){
							$td.removeClass(‘init-color‘).addClass(‘open-color‘).html(mineNumData[allSafeArea[i]] || ‘ ‘);
						}
					}
				},                   // 每次点击判断是否赢了
				_isWin: function(){
					var me = this;
					if(me.$table.find(‘.init-color,.flag-color‘).size() == me.settings.mineNum){
						return true;
					}
					return false;
				},                   // 显示所有雷区
				_showMine: function(){
					var me = this,
						i, len,
						minePosition = me.minePosition,
						$tds = me.$table.find(‘td‘);

					for(i=0,len=minePosition.length; i<len; i++){
						$($tds[minePosition[i]]).addClass(‘mine-color‘);
					}
				}
			});

			// jquery插件
			$.fn.minefield = function( options ){
				return this.each(function(index, dom){
					new Minefield( options, dom );
				});
			};

		})(window, jQuery);

  

时间: 2024-10-22 19:58:29

很久木来博客园了,今天献上周末撸的扫雷游戏咯~~的相关文章

很开心我们在博客园园龄有七年了啦

:)不知不觉博主已经在园子里度过了七个春夏秋冬,从微软的WPF/SL/Win10/C#到html5跨平台WEBAPP .再到今天的Unity3D.Unreal.HoloLens (虚拟现实/增强现实)内容定制业务 . 做软件定制业务很辛苦,也很充实,服务好每个客户真的不是一件容易的事,程序员有的时候就是比较急躁,协调好客户.业务.技术开发.测试的关系,是我们多年来的收获~ 我们在这里忠心希望博客园越办越好,尤其在微软“黑科技” HoloLens 硬件和生态.技术的引领下发挥更大的作用! 下面整理

关于博客园创始人的心路历程,启发很大!

文章转自:https://www.cnblogs.com/yesihoang/p/4566471.html 本期人物简介:dudu 1997年毕业于南京电力高等专科学校,对计算机技术有一种执着的兴趣与热情,喜欢挑战性,喜欢为了自己的目标去努力,.NET技术的坚定支持者,博客园的创建者和维护者. 我见过很多技术类个人网站,以前的Visual Basic技术网站.Visual C++技术网站.现在的.net和Java网站,他们有一个共同特点就是在开始的时候红红火火,1-2年后就逐渐消亡,很难作大,很

博客园添加网站统计访问量-操作简单很实用哦!

浏览博客园,看到这个小文章,跟着操作了一下,可以定制网站的访问人数.访问量,需要的亲果断试试看吧! 效果图: 博文: 无意中看到有这个访问量的统计,觉得挺好玩的,我们现在就来添加一个吧: 1. 先到http://www.amazingcounters.com/sign-up.php   这个地址去申请一个帐户,申请时填写好自己的资料,比如 你的统计风格样式.要统计的地址.要统计的类型,是浏览量(PV) 还是 访客数(UV),或者你也可以2个都统计:这些统计数据都是可以任意修改的哟,不过我们最好还

我的版权何在?博客园就不维护博友文章的版权?

说到版权心里就很不爽,大家很多时候自己的利益都有被侵犯的时候,很多人感觉不再乎,以前自己也是. 自己以前在51cto技术博客也写博客,不能说每天都写吧,但是每周都会出新笔记,当时自己也有很多粉丝,当时朋友就给我说,记得写笔记啊,我们都等着看呢,晚上10点前发出来,我必看.当时自己把自己知道的,结合所学到的一块做成world文档,加图片,标注,一心一意的写,偶尔也会录个小视频.想着自己会有越来越多的粉丝,后来博客就被封了,就中午下去吃顿饭的功夫,后来申诉去了,说我博客内容雷同,想想可能版权的问题,

初到博客园

因为一份新的工作,开始接触到软件开发的知识,虽说只需要掌握一些基础的linux,mongodb的知识,可是对于我来说,也是个不小的挑战. 已经接触linux的基础命令,知晓一些基础的命令行,参考鸟哥,从一开始的小白,安装软件,到现在基本的一些常识都在慢慢的积累,希望自己不要跑偏,朝着目前的工作需求慢慢前行. 也许正是因为工作需求,我自己才能从头开始学起一门新的知识,毕业才两年,似乎很多时候,已经很难静下心去学习新的东西,此次正好换城市,换工作,换行业,而且,领导给我时间让我自己学习,这是多么仁慈

【原】博客园第三方客户端-i博客园App开源

[原]博客园第三方客户端-i博客园App开源 本文转载请注明出处 —— polobymulberry-博客园 1.前言 目前i博客园App已经更新到2.0.0版本了,使用了最新的博客园Web API.相比于第一个版本,添加了很多新的功能,也修改了很多功能.整体来说改动比较大,代码也比较混乱.所以趁着清明假期,把代码好好整理了一番.目前基本的架构已成型(当然,后期还需要不断优化),但App基本功能方面还有很多需要添加的,后面会集中把App功能完善. 上面简单介绍了下目前App的情况,回到开源的话题

【工具】今天有人问我可以直接离线一个完整的网站吗?有没有什么工具之类的?我推荐一款:Httrack (网站复制机)案例:离线你的博客园

搞安全的朋友这款工具可能用的比较多,毕竟信息收集阶段还是很必须的,这篇文章主要讲一下离线你的博客园案例 官网:http://www.httrack.com/ 里面有windows,linux,Android等等几个版本 先简单介绍一下,具体的你可以自己摸索一下 一.windows下 安装很简单就不说了,讲下简单使用(里面有简体中文) 新建一个工程名,最好是英文的,选择一下存放路径(分类可以不选) 设置要离线的网站地址(可以设置一些参数)随意演示一下,你们保持默认即可 准备阶段结束 开始离线了~等

使用Windows Live Writer 2012和Office Word 2013 发布文章到博客园全面总结

[超详细教程]使用Windows Live Writer 2012和Office Word 2013 发布文章到博客园全面总结 去年就知道有这个功能,不过没去深究总结过,最近有写网络博客的欲望了,于是又重新拾起这玩意儿. 具体到底是用Windows Live Writer 2012还是用Word 2013,个人觉得看个人,因为这2个软件各有优点,各有缺点. 1.首先用LiveWriter发博客显然更专业,发布后的效果也与本地最接近,但是在编辑功能上肯定大不如Word,另外一个最大缺点是它本地保存

使用Windows Live Writer 2012和Office Word 2013 发布文章到博客园

引用六仙庵的博客:[超详细教程]使用Windows Live Writer 2012和Office Word 2013 发布文章到博客园全面总结 - 六仙庵 - 博客园http://www.cnblogs.com/liuxianan/archive/2013/04/13/3018732.html 不过在安装Windows Live Writer 2012的时候出了点小问题. 微软官方的解释 .NET Framework 3.5 安装错误:0x800F0906.0x800F081F.0x800F0