本文主要介绍js实现扫雷小程序的示例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧,希望能帮助到大家。
初学javascript,写了一个扫雷程序练练手!
扫雷规则及功能
扫雷想必大家都不陌生,就是windows上点击排雷的小游戏,它的主要规则有
1.左键点击显示当前格子是否为雷,如果为雷的话,GameOver啦,如果不是雷的话,这个格子会显示周围八个格子内的雷数量。
2.鼠标右键标记,标记可能的雷,标记了之后取消需要再次右键点击该格子,左键无效果。
3.鼠标中键(滚轮)按下后,快捷扫雷(如果周围雷数和未被标记且未被翻开的格子相等,会将这些格子一并翻开)
主要功能基本完全复刻了windows7扫雷的功能
扫雷github地址:扫雷github地址
扫雷算法
1.首先我定义了一个构造函数,里面是一系列的属性:
var mineCraft = function(num1,num2,mine_num,obj,type){ this.num1 = num1; //整个扫雷的行数 this.num2 = num2; //整个扫雷的列数 this.mine_num = mine_num; //雷的个数 this.tiles = []; //数组里面存放的是每个小格子 this.obj = obj; //扫雷放置的对象 this.flag = true; this.arr = []; this.arr_2 = []; this.time_dsq = null; this.time_dc =''; this.time_arr = [[],[],[]]; //时间统计信息 this.details = [[],[],[]]; // 游戏统计详情 this.type = type; //游戏类型:初级/中级/高级/自定义 this.buildTiles(); //创建游戏函数 };
2.在页面上创建扫雷的界面 函数buildTiles
buildTiles:function(){ this.obj.style.width = 51*this.num1+'px'; //在传进来的对象上画整体格子,每个小格子51px大小,总大小就为个数*单个大小 this.obj.style.height = 51*this.num2+'px'; var indexOfp = 0; for(var i = 0;i<this.num2;i++){ for(var j = 0;j<this.num1;j++){ var tile = document.createElement('p'); tile.className = 'tile'; //定义小格子class tile.index = indexOfp; //为每个小格子添加索引 this.tiles[indexOfp] = tile; //将小格子存入数组中 indexOfp++; this.obj.appendChild(tile); //将小格子插入到整个扫雷界面中 } } this.obj.oncontextmenu = function(){ //取消浏览器的默认右键菜单事件 return false; } this.event(); //点击事件 },
3.绑事件函数:
event : function(){ var _this = this; this.obj.onmouseover = function(e){ //鼠标悬停事件--- if(e.target.className == 'tile'){ e.target.className = 'tile current'; } } this.obj.onmouseout = function(e){ //鼠标移出事件-- if(e.target.className == 'tile current'){ e.target.className = 'tile'; } } this.obj.onmousedown = function(e){ //鼠标按下事件 var index = e.target.index; if(e.button == 1){ //e.button属性 左键0/中键1/右键2 event.preventDefault(); //取消默认 } _this.changeStyle(e.button,e.target,index); } this.obj.onmouseup = function(e){ //鼠标弹起事件 if(e.button == 1){ _this.changeStyle(3,e.target); } } },
4.点击调用的函数:
changeStyle:function(num1,obj,num_index){ if(num1 == 0){ //是左键的话 if(this.flag){ //this.flag 是之前定义的用于判断是否为第一次点击 this.store(num_index); //store函数,存放被点击的格子周围的8个格子 this.setMineCraft(this.mine_num,this.arr,num_index); //如果是第一次点击 即调用布雷函数 更改flag状态 this.flag = false; this.detail_statistics(0,false); //开始信息统计函数 } if(obj.className != 'tile'&&obj.className !='tile current'){//如果不是第一次点击,被点击的格子不是未点击状态,无效 return false; } if(obj.getAttribute('val') == 0){ //如果不是雷。改为翻开状态 obj.className = "showed"; obj.innerHTML = obj.getAttribute('value') == 0?'':obj.getAttribute('value'); //显示周围雷数 this.showAll(obj.index); //递归函数判断周围格子的情况,就是扫雷游戏上一点开会出现一片的那种 } if(this.over(obj)){ //判断游戏是否结束 this.last(); } } if(num1 == 2){ //右键标记事件 if(obj.className == 'biaoji'){ obj.className = 'tile'; }else if(obj.className !='biaoji'&&obj.className != 'showed'){ obj.className = 'biaoji'; } } if(num1 == 1){ // 中键事件 if(obj.className =="showed"){ this.show_zj1(obj.index); } } if(num1 == 3){ //鼠标弹起事件 if (obj.className == "showed") { var flag1 = this.show_zj2(obj.index,0); }else{ this.show_zj2(obj.index,1) return false; } if(flag1&&this.over()){ //弹起判断是否结束 this.last(); } } },
5.布雷:我之前的布雷是在页面加载在buildTiles()的时候布雷的,但是这样会导致有可能你电机的第一个格子就是雷(游戏性不强),后来修改到第一次点击完成之后布雷(确保第一下点的不是雷),避开直接炸死的现象.所以把调用放在后面的event后触发的changeStyle函数中
setMineCraft:function(num,arr_first,num_first){ //雷的个数、最开始被点击的格子周围的八个、被点击的那个格子 var arr_index = []; for(var i = 0;i<arr_first.length;i++){ arr_index.push(arr_first[i].index); } var length = this.tiles.length; for (var i = 0; i < length; i++) { this.tiles[i].setAttribute("val", 0); } for (var i = 0; i < num; i++) { var index_Mine = Math.floor(Math.random() * this.tiles.length); if(index_Mine == num_first||arr_index.lastIndexOf(index_Mine)>-1){//如果是属于第一次点击的周围的直接跳过在该位置布雷 num++; continue; } if (this.tiles[index_Mine].getAttribute("val") == 0) { this.tiles[index_Mine].setAttribute("val", 1); }else { num++; } } this.showValue(); this.event() },
6.存储周围格子的函数:
store : function(num) { //传入格子的index. var tiles_2d = []; var indexs = 0; for(var i = 0;i<this.num2;i++){ tiles_2d.push([]); for(var j = 0;j<this.num1;j++){ tiles_2d[i].push(this.tiles[indexs]); indexs++; } } var j = num % this.num1; var i = (num - j) / this.num1; this.arr = []; //左上 if (i - 1 >= 0 && j - 1 >= 0) { this.arr.push(tiles_2d[i - 1][j - 1]); } //正上 if (i - 1 >= 0) { this.arr.push(tiles_2d[i - 1][j]); } //右上 if (i - 1 >= 0 && j + 1 <= this.num1-1) { this.arr.push(tiles_2d[i - 1][j + 1]); } //左边 if (j - 1 >= 0) { this.arr.push(tiles_2d[i][j - 1]); } //右边 if (j + 1 <= this.num1-1) { this.arr.push(tiles_2d[i][j + 1]); } //左下 if (i + 1 <= this.num2-1 && j - 1 >= 0) { this.arr.push(tiles_2d[i + 1][j - 1]); } //正下 if (i + 1 <= this.num2-1) { this.arr.push(tiles_2d[i + 1][j]); } //右下 if (i + 1 <= this.num2-1 && j + 1 <= this.num1-1) { this.arr.push(tiles_2d[i + 1][j + 1]); } },
7.showAll函数:作用是如果该格子周围没有雷,自动翻开周围8个格子,然后再判断周围八个格子的周围8隔格子是否有雷,利用了递归的方法
showAll:function(num){ if (this.tiles[num].className == "showed" && this.tiles[num].getAttribute("value") == 0){ this.store(this.tiles[num].index); var arr2 = new Array(); arr2 = this.arr; for (var i = 0; i < arr2.length; i++) { if (arr2[i].className != "showed"&&arr2[i].className !='biaoji') { if (arr2[i].getAttribute("value") == 0) { arr2[i].className = "showed"; this.showAll(arr2[i].index); } else { arr2[i].className = "showed"; arr2[i].innerHTML = arr2[i].getAttribute("value"); } } } } },
8.show_zj函数:主要是中键按钮的作用中键点击后的函数,这里的show_zj1是鼠标键按下后的显示效果,
show_zj2函数就是
show_zj1:function(num){ this.store(this.tiles[num].index); for (var i = 0; i < this.arr.length; i++) { if (this.arr[i].className == "tile") { this.arr_2.push(this.arr[i]); this.arr[i].className = "showed"; // this.arr[i].className = "test"; } } }, show_zj2:function(num,zt){ var count = 0; this.store(this.tiles[num].index); for(var i = 0,len = this.arr_2.length;i<len;i++){ this.arr_2[i].className = 'tile'; //按下效果恢复原状 } this.arr_2.length = 0; for(var i = 0;i<this.arr.length;i++){ this.arr[i].className == 'biaoji'&&count++; } if(zt == 1){ return false; } var numofmines = this.tiles[num].getAttribute("value"); if(numofmines == count){ //如果周围雷数和周围被标记数相等就翻开周围的格子 var arr = new Array(this.arr.length); for(var i = 0;i<this.arr.length;i++){ arr[i] = this.arr[i]; } for (var i = 0,length = arr.length; i < length; i++) { if (arr[i].className == "tile" && arr[i].getAttribute("val") != 1) {//如果周围格子无雷则继续。 arr[i].className = "showed"; arr[i].innerHTML = arr[i].getAttribute("value") == 0?"":arr[i].getAttribute("value"); this.showAll(arr[i].index); } else if (arr[i].className == "tile" && arr[i].getAttribute("val") == 1) { //如果周围格子有雷,游戏结束 this.over(arr[i]); this.last(); return false; } } } return true; },
9.结束判断:
over:function(obj){ var flag = false; var showed = document.getElementsByClassName('showed'); var num = this.tiles.length - this.mine_num; if(showed.length == num){ //如果被排出来的格子数等于总格子数-雷数,这游戏成功结束 this.detail_statistics(1,true); //游戏统计 ,true代表胜,false,代表失败 alert('恭喜你获得成功'); flag = true; }else if(obj&&obj.getAttribute('val') == 1){ //如果被点击的是雷,则炸死 this.detail_statistics(1,false); alert('被炸死!'); flag = true; } return flag; },
10.结束后的显示函数:
last:function(){ var len = this.tiles.length; for(var i = 0;i<len;i++){ this.tiles[i].className = this.tiles[i].getAttribute('val') == 1?'boom':'showed'; if(this.tiles[i].className != 'boom'){ // this.tiles[i].innerHTML = this.tiles[i].getAttribute('value') == 0?'':this.tiles[i].getAttribute('value'); } } this.obj.onclick = null; this.obj.oncontextmenu = null; },
11 统计信息:还是比较全的和windows7扫雷版的判断项目是一样的,使用的是每次结束游戏后将数据存入localStorage中,
//已玩游戏,已胜游戏,胜率,最多连胜,最多连败,当前连局; detail_statistics:function(num,zt){ var time_pay = 1; var _this = this; if(num == 0){ this.time_dsq = setInterval(function(){ $('#time_need').text(time_pay); _this.time_dc =time_pay; time_pay++; },1000); } else if(num == 1){ clearInterval(this.time_dsq); if(this.type == 4){return false;} if(localStorage.details == undefined){ localStorage.details = JSON.stringify([[0,0,0,0,0,0],[0,0,0,0,0,0],[0,0,0,0,0,0]]); //这里存放的就是上面注释中的六项数据 } if(JSON.parse(localStorage.details) instanceof Array){ this.details = JSON.parse(localStorage.details); } this.details[this.type][0] += 1; if(zt == false){ if(this.details[this.type][5]>=0){ this.details[this.type][5] = -1; }else{ this.details[this.type][5] -= 1; } if(this.details[this.type][5]<this.details[this.type][4]){ this.details[this.type][4] = this.details[this.type][5]; } this.details[this.type][2] = this.toPercent(this.details[this.type][2]/this.details[this.type][0]); localStorage.details = JSON.stringify(this.details); return false; } if(this.details[this.type][5]>=0){ this.details[this.type][5] += 1; }else{ this.details[this.type][5] = 1; } if(this.details[this.type][5]>this.details[this.type][3]){ this.details[this.type][3] = this.details[this.type][5]; } this.details[this.type][3] += 1; this.details[this.type][2] = this.toPercent(this.details[this.type][4]/this.details[this.type][0]); localStorage.details = JSON.stringify(this.details); var time1 = new Date(); var time_str = time1.getFullYear()+'/'+time1.getMonth()+'/'+time1.getDate()+' '+time1.getHours()+':'+time1.getMinutes(); if(localStorage.time == undefined){ localStorage.time = JSON.stringify([[],[],[]]); } if(JSON.parse(localStorage.time) instanceof Array){ this.time_arr = JSON.parse(localStorage.time); } this.time_arr[this.type].push([this.time_dc,time_str]); this.time_arr[this.type].sort(function(a,b){ return a[0]-b[0]; }); if(this.time_arr[this.type].length>5){ this.time_arr[this.type].pop(); } localStorage.time = JSON.stringify(this.time_arr); } },
扫雷的主要部分就是这些了,还有一些小功能包括没写来,要看完整的可以看gitHub
相关推荐:
以上是js实现扫雷的代码的详细内容。更多信息请关注PHP中文网其他相关文章!

Python和JavaScript的主要区别在于类型系统和应用场景。1.Python使用动态类型,适合科学计算和数据分析。2.JavaScript采用弱类型,广泛用于前端和全栈开发。两者在异步编程和性能优化上各有优势,选择时应根据项目需求决定。

选择Python还是JavaScript取决于项目类型:1)数据科学和自动化任务选择Python;2)前端和全栈开发选择JavaScript。Python因其在数据处理和自动化方面的强大库而备受青睐,而JavaScript则因其在网页交互和全栈开发中的优势而不可或缺。

Python和JavaScript各有优势,选择取决于项目需求和个人偏好。1.Python易学,语法简洁,适用于数据科学和后端开发,但执行速度较慢。2.JavaScript在前端开发中无处不在,异步编程能力强,Node.js使其适用于全栈开发,但语法可能复杂且易出错。

javascriptisnotbuiltoncorc; saninterpretedlanguagethatrunsonenginesoftenwritteninc.1)javascriptwasdesignedAsalightweight,解释edganguageforwebbrowsers.2)Enginesevolvedfromsimpleterterterpretpreterterterpretertestojitcompilerers,典型地提示。

JavaScript可用于前端和后端开发。前端通过DOM操作增强用户体验,后端通过Node.js处理服务器任务。1.前端示例:改变网页文本内容。2.后端示例:创建Node.js服务器。

选择Python还是JavaScript应基于职业发展、学习曲线和生态系统:1)职业发展:Python适合数据科学和后端开发,JavaScript适合前端和全栈开发。2)学习曲线:Python语法简洁,适合初学者;JavaScript语法灵活。3)生态系统:Python有丰富的科学计算库,JavaScript有强大的前端框架。

JavaScript框架的强大之处在于简化开发、提升用户体验和应用性能。选择框架时应考虑:1.项目规模和复杂度,2.团队经验,3.生态系统和社区支持。

引言我知道你可能会觉得奇怪,JavaScript、C 和浏览器之间到底有什么关系?它们之间看似毫无关联,但实际上,它们在现代网络开发中扮演着非常重要的角色。今天我们就来深入探讨一下这三者之间的紧密联系。通过这篇文章,你将了解到JavaScript如何在浏览器中运行,C 在浏览器引擎中的作用,以及它们如何共同推动网页的渲染和交互。JavaScript与浏览器的关系我们都知道,JavaScript是前端开发的核心语言,它直接在浏览器中运行,让网页变得生动有趣。你是否曾经想过,为什么JavaScr


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

EditPlus 中文破解版
体积小,语法高亮,不支持代码提示功能

PhpStorm Mac 版本
最新(2018.2.1 )专业的PHP集成开发工具

SublimeText3 Linux新版
SublimeText3 Linux最新版

WebStorm Mac版
好用的JavaScript开发工具

ZendStudio 13.5.1 Mac
功能强大的PHP集成开发环境