编程实现扫雷(一)

扫雷游戏的规则很简单:

游戏面板上有一些格子,每个格子中有一个数字(空白表示数字为 0)或是地雷,格子中的数字表示格子周围格子中地雷的数量。玩家要做的就是把数字格子找出来,时间花的越少越好。

除边界上的格子外,每个格子周围有 8 个格子:上、下、左、右、4 个斜角。所以数字范围是 0~8。

所以我们的算法如下:

根据用户选择的难易程度(有初、中、高三个级别,级别越高地雷和格子数量越多),随机产生一定个数的地雷并随机放在格子中。然后遍历格子,计算每个格子中的数字,标记在格子上。玩家左键点击格子时显示格子内容(如果遇到地雷则挑战失败,游戏结束),右键点击格子时标记格子为地雷,真到正确标记所有地雷并打开所有非地雷格子,挑战成功,游戏结束。

小技巧:由于格子中数字范围是 0~8,所以为了便于计算,我们可以把地雷所在的格子中的数字记为 9。

我们分4个步骤

  1. 显示游戏信息
  2. 画格子
  3. 初始化游戏
  4. 给格子添加点击事件
  5. 添加相关功能控件

首先我们需要有一个面板来显示游戏信息,包括剩余地雷个数、所用时间、难度级别等。因为格子数量不是固定的,所以我们先不画格子,放在 JS 代码中绘制。

创建 index.html 文件

添加如下代码并保存:




 
 JavaScript版扫雷
 


 
 
剩余雷数:0 个 持续时间: 0
难度选择:



提示:
  • 1、点击“开始游戏”游戏开始计时
  • 2、游戏过程中点击“开始游戏”将开始新游戏

然后需要调整面板上游戏信息的位置,添加一些样式,在 index.css 中添加如下代码并保存:

.main {
 margin:10px auto;
 padding:20px;
 background:#EEE;
 width:600px;
 zoom:1;
}
.main table {
 background:#CCC;
 float:left;
}
.main table td {
 border:2px outset #EEE;
 font-size:20px;
 width:32px;
 height:32px;
 text-align:center;
 cursor:pointer;
}
.main table td:hover {
 background-color:#AAA;
}
.main #operation {
 width:180px;
 float:right;
 text-align:center;
}
.landMine {
 background-image:url(mine.png);
 background-position:center;
 background-repeat:no-repeat;
}
.main table td.normal {
 border:2px solid #EEE;
 background-color:#AAA;
}
.main table td.normal:hover {
 background-color:#AAA;
}
.flag {
 background-image:url(flag.png);
 background-position:center;
 background-repeat:no-repeat;
}
.main:after {
 clear: both;
 display: block;
 content: "";
 line-height: 0;
 height: 0;
 visibility:hidden;
}
.main .tip {
 font-size:14px;
 margin:5px;
}
.main .tip ul {
}
.main .tip ul li {
 margin:5px 0;
 line-height:20px;
}
.main .light{
 font-size:30px;
}
.main .red {
 color:red;
}
.main .f60 {
 color:#F60;
}
.main input[type=button] {
 padding:2px 10px;
 margin:5px;
 font-size:20px;
 cursor:pointer;
}
.main .txtleft {
 text-align:left;
}
.main input[type='radio'],
.main fieldset label {
 cursor:pointer;
}
.main fieldset {
 margin:10px 0;
 line-height:25px;
}

画格子需要传入一些参数,如放格子的表格的 id,格子的数量(用行数和列数表示)。另外,游戏的其他数据也要进行初始化。

在 jms.js 中添加如下代码并保存:

//在jms.js中
(function () {
 var JMS = function (id,rowCount,colCount, minLandMineCount, maxLandMineCount) {
 if (!(this instanceof JMS))
 return new JMS(id, rowCount, colCount, minLandMineCount, maxLandMineCount);
 this.doc = document;
 this.table = this.doc.getElementById(id);//画格子的表格
 this.cells = this.table.getElementsByTagName("td");//小格子
 this.rowCount = rowCount || 10;//格子行数
 this.colCount = colCount || 10;//格子列数
 this.landMineCount = 0;//地雷个数
 this.markLandMineCount = 0;//标记的地雷个数
 this.minLandMineCount = minLandMineCount || 10;//地雷最少个数
 this.maxLandMineCount = maxLandMineCount || 20;//地雷最多个数
 this.arrs = [];//格子对应的数组
 this.beginTime = null;//游戏开始时间
 this.endTime = null;//游戏结束时间
 this.currentSetpCount = 0;//当前走的步数
 this.endCallBack = null;//游戏结束时的回调函数
 this.landMineCallBack = null;//标记为地雷时更新剩余地雷个数的回调函数
 this.doc.oncontextmenu = function () {//禁用右键菜单
 return false;
 };
 this.drawMap();
 };
 JMS.prototype = {
 //画格子
 drawMap: function () {
 var tds = [];
 if (window.ActiveXObject && parseInt(navigator.userAgent.match(/msie ([d.]+)/i)[1]) < 8) {
 var css = '#JMS_main table td{background-color:#888;}',
 head = this.doc.getElementsByTagName("head")[0],
 style = this.doc.createElement("style");
 style.type = "text/css";
 if (style.styleSheet) {
 style.styleSheet.cssText = css;
 } else {
 style.appendChild(this.doc.createTextNode(css));
 }
 head.appendChild(style);
 }
 for (var i = 0; i < this.rowCount; i++) {
 tds.push("");
 for (var j = 0; j < this.colCount; j++) {
 tds.push("");
 }
 tds.push("");
 }
 this.setTableInnerHTML(this.table, tds.join(""));
 },
 //添加HTML到Table
 setTableInnerHTML: function (table, html) {
 if (navigator && navigator.userAgent.match(/msie/i)) {
 var temp = table.ownerDocument.createElement('p');
 temp.innerHTML = '' + html + '
'; if (table.tBodies.length == 0) { var tbody = document.createElement("tbody"); table.appendChild(tbody); } table.replaceChild(temp.firstChild.firstChild, table.tBodies[0]); } else { table.innerHTML = html; } } }; window.JMS = JMS; })();

上面的代码中,部分代码是为了兼容 IE 浏览器,可忽略。

在 index.js 的调用代码中,我们需要绑定难度选择按钮的事件,然后调用上面定义的 JMS,开始绘制格子。

在 index.js 中添加如下代码并保存:

//在index.js中
var jms = null,
 timeHandle = null;
window.onload = function () {
 var radios = document.getElementsByName("level");
 for (var i = 0, j = radios.length; i < j; i++) {
 radios[i].onclick = function () {
 if (jms != null)
 if (jms.landMineCount > 0)
 if (!confirm("确定结束当前游戏?"))
 return false;
 var value = this.value;
 init(value, value, value * value / 5 - value, value * value / 5);
 document.getElementById("JMS_main").style.width = value * 40 + 180 + 60 + "px";
 }
 }
 init(10, 10);
};
function init(rowCount, colCount, minLandMineCount, maxLandMineCount) {
 var doc = document,
 landMineCountElement = doc.getElementById("landMineCount"),
 timeShow = doc.getElementById("costTime"),
 beginButton = doc.getElementById("begin");
 if (jms != null) {
 clearInterval(timeHandle);
 timeShow.innerHTML = 0;
 landMineCountElement.innerHTML = 0;
 }
 jms = JMS("landmine", rowCount, colCount, minLandMineCount, maxLandMineCount);
}

现在,我们开始对游戏初始化,主要分三步:

  1. 把所有格子(代码中用一个数组表示)初始化为 0
  2. 随机生成地雷个数,把地雷随机放到数组中,数组项值设置为 9
  3. 计算其他格子中的数字,值放入数组中

在 jms.js 中 JMS.prototype 内加入如下代码:

//在jms.js中JMS.prototype内加入
//初始化,一是设置数组默认值为0,二是确定地雷个数
init: function () {
 for (var i = 0; i < this.rowCount; i++) {
 this.arrs[i] = [];
 for (var j = 0; j < this.colCount; j++) {
 this.arrs[i][j] = 0;
 }
 }
 this.landMineCount = this.selectFrom(this.minLandMineCount, this.maxLandMineCount);
 this.markLandMineCount = 0;
 this.beginTime = null;
 this.endTime = null;
 this.currentSetpCount = 0;
},
//把是地雷的数组项的值设置为9
landMine: function () {
 var allCount = this.rowCount * this.colCount - 1,
 tempArr = {};
 for (var i = 0; i < this.landMineCount; i++) {
 var randomNum = this.selectFrom(0, allCount),
 rowCol = this.getRowCol(randomNum);
 if (randomNum in tempArr) {
 i--;
 continue;
 }
 this.arrs[rowCol.row][rowCol.col] = 9;
 tempArr[randomNum] = randomNum;
 }
},
//计算其他格子中的数字
calculateNoLandMineCount: function () {
 for (var i = 0; i < this.rowCount; i++) {
 for (var j = 0; j < this.colCount; j++) {
 if (this.arrs[i][j] == 9)
 continue;
 if (i > 0 && j > 0) {
 if (this.arrs[i - 1][j - 1] == 9)
 this.arrs[i][j]++;
 }
 if (i > 0) {
 if (this.arrs[i - 1][j] == 9)
 this.arrs[i][j]++;
 }
 if (i > 0 && j < this.colCount - 1) {
 if (this.arrs[i - 1][j + 1] == 9)
 this.arrs[i][j]++;
 }
 if (j > 0) {
 if (this.arrs[i][j - 1] == 9)
 this.arrs[i][j]++;
 }
 if (j < this.colCount - 1) {
 if (this.arrs[i][j + 1] == 9)
 this.arrs[i][j]++;
 }
 if (i < this.rowCount - 1 && j > 0) {
 if (this.arrs[i + 1][j - 1] == 9)
 this.arrs[i][j]++;
 }
 if (i < this.rowCount - 1) {
 if (this.arrs[i + 1][j] == 9)
 this.arrs[i][j]++;
 }
 if (i < this.rowCount - 1 && j < this.colCount - 1) {
 if (this.arrs[i + 1][j + 1] == 9)
 this.arrs[i][j]++;
 }
 }
 }
},
//获取一个随机数
selectFrom: function (iFirstValue, iLastValue) {
 var iChoices = iLastValue - iFirstValue + 1;
 return Math.floor(Math.random() * iChoices + iFirstValue);
},
//通过数值找到行数和列数
getRowCol: function (val) {
 return {
 row: parseInt(val / this.colCount),
 col: val % this.colCount
 };
},

接下来的两部分我放在下一篇文章里。

展开阅读全文

页面更新:2024-05-11

标签:地雷   初始化   格子   函数   标记   表格   剩余   个数   级别   数量   代码   数字   时间   体育   游戏   信息

1 2 3 4 5

上滑加载更多 ↓
推荐阅读:
友情链接:
更多:

本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828  

© CopyRight 2020-2024 All Rights Reserved. Powered By 71396.com 闽ICP备11008920号-4
闽公网安备35020302034903号

Top