Day44 扫雷
1. HTML
有选择难度的下拉列表
开始按钮
重新加载按钮
画板(显示的小方格)
标题提示文字
<body>
<select name="" id="set_num">
<option value="0">初级</option>
<option value="1">中级</option>
<option value="2">高级</option>
</select>
<button id="start">开始游戏</button>
<span id="refresh">重新加载游戏</span>
<div id="content">
<!-- 先写好小格子,通过css设置完样式化,即可删除,因为每个小格子都是js动态生成的 -->
<!-- 写出这几个div 只是为了方便我们进行css样式设置,确定设置无误后,可删除 -->
<div class="tile">默认</div>
<div class="showed">已点击</div>
<div class="boom">雷</div>
<div class="tile current">鼠标移入</div>
<div class="tile tag">小红旗</div>
</div>
<h1 id='title'>选择难度并点击确定,开始游戏<br> 右键可以标记小红旗哦~</h1>
</body>
#set_num 是选择难度
#start 是开始游戏
#refresh 是重新加载
#content 画板
.tile默认样式
.showed 已点击样式
.boom 雷的样式
.tile current 鼠标移入样式
.tile tag 右键小红旗样式
#title 友情提示
2. CSS
布局
*{
margin: 0;
padding: 0;
}
body{
text-align: center;
font-size: 15px;
font-family: '楷体';
}
#content{
/* border: 1px solid; */
/* width: 200px; */
margin: 0 auto;
}
/* 重新加载 */
#refresh{
/* 设置行内块,否则不能设置宽高 */
display: inline-block;
width: 100px;
height: 30px;
/* 行高和高度一致,则内容垂直居中 */
line-height: 30px;
border: 1px solid gray;
/* 圆角边 */
border-radius: 5px;
/* 小手状 */
cursor: pointer;
color: white;
background-color: rgb(143,122,102);
}
/* 每一个div小格子 */
/* 默认 */
#content div{
width: 49px;
height: 49px;
border: 1px solid black;
text-align: center;
font-size: 20px;
line-height: 49px;
cursor: pointer;
float: left;
}
.tile{
background: url(../img/ba.png);
}
/* 已点击 */
.showed{
background: rgb(195,206,228);
}
/* 雷 */
.boom{
background: url(../img/Minesmall.png);
}
/* 移入 */
.current{
background: url(../img/baq.png);
}
/* 小红旗 */
.tag{
/* 第一个是前景,第二个是背景 */
background: url(../img/hq.png),url(../img/ba.png);
}
3. JS
// 使用闭包,解决$命名冲突问题
(function ($) {
/**
* 对外提供的接口
*
* 必须传递 行 row,列 column,雷的个数 mine_num,显示画板的位置 obj 盒子的ID值
*/
$.fn.mineClearance = function (options) {
// console.log(options);
// var obj1 = {name:'张三',age:16};
// var obj2 = {name:'李四',addr:'石家庄'}
// 合并两个对象,如果有相同的属性,则使用后者替换前者
// 所以前者适合做默认值,后者适合做参数传递
// var obj3 = $.extend(obj1,obj2);
// console.log(obj3);
var settings = $.extend({
// 默认列
column: 10,
// 默认行
row: 10,
// 默认雷个数
mine_num: 20,
// 默认画板ID
obj: "#content",
// 每一个div盒子,默认是空数组
tiles: [],
// 周边8个元素
arr: [],
// 判断游戏是否是第一点击,如果是第一次就初始化雷,true表示第一次点击
flag: true
}, options || {});
// 生成画板
buildTiles();
/**
* 生成画板
*/
function buildTiles() {
// 判断行和列是否合法
if (settings.column <= 0 || settings.row <= 0) {
alert('行和列必须大于 0 哦~');
return;
}
// 判断雷
if (settings.mine_num <= 0) {
alert("没雷你玩啥?");
return;
}
if (settings.mine_num >= (settings.column * settings.row)) {
alert("全是雷");
return;
}
// 到这里说明数据没啥问题
// 获取画板的DOM对象
var obj = $(settings.obj)[0];
// 设置画板的宽高
// 每个盒子宽高是49,边框都是1,所以实际宽高为 51
// 画板的宽度 = 列数 * 51
// obj.style.width = 51 * settings.column + "px";
// obj.style.height = 51 * settings.row + "px";
obj.width(51 * settings.column);
obj.height(51 * settings.row);
// 对div添加索引,0,1,2,3,.....
// 方便我们操作,我们能够根据点击的是谁,获取它和周边8个元素
// 比如 3行4列, 我们点的是第6个,索引就是 5
// 5 % 列数 = 1
// (5-1) / 列数 = 1
var indexOfdiv = 0;
// 根据行和列 生成div 并设置索引
for (var i = 0; i < settings.row; i++) {
for (var j = 0; j < settings.column; j++) {
// 创建div标签
var tile = document.createElement("div");
// var tile = $('<div class="tile"></div>')
// 设置class属性值为 tile
tile.className = 'tile';
// 添加索引
// tile.setAttribute('index',indexOfdiv);
tile.index = indexOfdiv;
// 把div保存到 settings.tiles数组中,方便我们后续操作
settings.tiles[indexOfdiv] = tile;
indexOfdiv++;
// 把div添加到 画板中
obj.appendChild(tile);
}
}
// 绑定事件
event();
}
/**
* 对div绑定事件
*/
function event() {
// 获取画板对象
var obj = $(settings.obj)[0];
// 对画板绑定事件,通过事件源,找到真正触发的这个小div即可
// 移入
obj.onmouseover = function (e) {
// 如果class属性值不是tile ,
// 说明要么你移动到已经点击过的div
// 要么你移动到边框上,就是画板了
// 我们只对未点击过的div做移入事件
if (e.target.className == 'tile') {
e.target.className = 'tile current';
}
}
// 移出
obj.onmouseout = function (e) {
// 如果class属性值不是tile ,
// 说明要么你移动到已经点击过的div
// 要么你移动到边框上,就是画板了
// 我们只对未点击过的div做移入事件
if (e.target.className == 'tile current') {
e.target.className = 'tile';
}
}
// 右键事件,添加小红旗
obj.oncontextmenu = function (e) {
// 当右键的时候,如果不是雷,不是已点击的,就可以添加红旗
// 因为如果是boom雷的时候,说明游戏已经结束
if (e.target.className != 'boom' && e.target.className != 'showed') {
// e.target.className = 'tile';
// console.log(e.target.className);
// if(e.target.className.split(' ').length == 3){
// e.target.className = 'tile current'
// }else{
// e.target.className = 'tile current tag'
// }
$(e.target).toggleClass('tag');
}
return false;
}
// 点击事件
obj.onclick = function (e) {
// console.log(22);
if (e.target.nodeName == 'DIV') {
// 获取事件源索引
var index = e.target.index;
// console.log(index);
// 判断点击的是否含有小红旗
// class属性是否包含 tag
// console.log(e.target.classList.contains('tag'));
if (e.target.classList.contains('tag')) {
alert("请先右键取消小红旗");
return;
}
}
// 到这里 说明点击的不是小红旗
// 初始化所有div , 生成雷,判断周边几个雷
changeStyle(e.target, index);
}
}
/**
* 生成雷,统计周围雷的个数等
*
* 第一个参数 : 点击的元素
* 第二个参数 : 该元素的index索引
*/
function changeStyle(obj, num_index) {
// 判断是否是第一次点击
if (settings.flag) {
// 是的话,生成雷等信息
// 获取周围八个元素
// store(num_index);
// 生成雷,val 表示,1是雷,0不是雷
setMineCraft();
settings.flag = false;
}
/**
* 初始化操作已完成
*/
// 雷和周边雷个数 已完成,需判断点击之后,是否是雷,是否游戏结束(胜利和失败),不是雷就需要进行扩散显示
// 不是就判断点击的是否是雷
// 判断游戏是否结束 - 胜利, 失败
if (!obj.getAttribute('val')) {
// 设置为已点击状态
obj.className = 'showed';
// 显示周围几个雷
let value = obj.getAttribute('value');
obj.innerHTML = value == 0 ? '' : value;
// 扩散显示
showAll(obj.index);
}
// 判断游戏是否结束,如果结束,显示所有div信息
// 比如 是雷的 就替换成雷的图片,周围有几个雷 就显示几
if (over(obj)) {
// 进来说明游戏结束
// 显示所有div信息
show();
}
}
/**
* 游戏结束 重置div,所有信息都显示
*/
function show() {
// 思路 : 遍历所有div 判断val是1是0 是 设置class为 boom 是0 设置class为 showed
for (var i = 0; i < settings.tiles.length; i++) {
settings.tiles[i].className = settings.tiles[i].getAttribute('val') == 1 ? 'boom' : 'showed';
// 如果不是雷 就要显示周边几个雷
if (settings.tiles[i].className != 'boom') {
var value = settings.tiles[i].getAttribute('value');
settings.tiles[i].innerHTML = value == 0 ? '' : value;
}
}
// 取消事件
$(settings.obj)[0].onclick = null;
}
/**
* 游戏结束判断
*
* @param {点击的元素} obj
*/
function over(obj) {
// true说明结束,false说明没有结束
var flag = false;
// 如何算游戏胜利 : 已点击的 + 雷的个数 = 总div个数
// 获取已点击的元素
var showed = document.getElementsByClassName('showed');
// div总个数 减去 雷的个数,得到剩余div个数
var num = settings.tiles.length - settings.mine_num;
if (num == showed.length) {
alert("恭喜你获得成功~");
flag = true;
// 如何算失败 : 点到雷就失败 val == 1
} else if (obj.getAttribute('val') == 1) {
alert('被炸死,游戏结束!');
flag = true;
}
// 没结束 就返回false,继续游戏
return flag;
}
/**
* 判断周围是否是雷,如果不是雷,就全部显示
*
* 如果周围有雷,就不再进行遍历
*
* @param {点击元素的索引} num
*/
function showAll(num) {
// 判断 周围是否有雷
// 如果有 终止
// 如果没有,遍历周边元素的周边元素,依次判断
if (settings.tiles[num].className == 'showed' && settings.tiles[num].getAttribute('value') == 0) {
// 获取周边8个(settings.arr)
store(num);
// 如果递归,会更改arr的值,所以保存为局部变量
var arr2 = settings.arr;
// 非showed
for (var i = 0; i < arr2.length; i++) {
// 如果添加小红旗标识 就跳过该次循环
if (arr2[i].classList.contains('tag')) {
continue;
}
if (arr2[i].className != 'showed') {
// value == 0
// 判断周边8个是否有雷,没有就显示并递归
if (arr2[i].getAttribute('value') == 0) {
// true 递归
arr2[i].className = 'showed';
showAll(arr2[i].index);
} else {
// false 设置为showed并显示value
arr2[i].className = 'showed';
arr2[i].innerHTML = arr2[i].getAttribute('value');
}
}
}
}
}
/**
* 生成雷,val 表示,1是雷,0不是雷
*/
function setMineCraft() {
// 雷的个数
var num = settings.mine_num;
// 遍历所有div 设置不是雷
// for (var i = 0; i < settings.tiles.length; i++) {
// settings.tiles[i].setAttribute('val', 0);
// }
// 随机生成雷
for (var i = 0; i < num; i++) {
// 随机的雷的索引
var index_Mine = Math.floor(Math.random() * settings.tiles.length);
// 判断生成的索引 是否生产过雷
// console.log(settings.tiles[index_Mine].getAttribute("val"));
if (!settings.tiles[index_Mine].getAttribute("val")) {
// 没有 就设置为 雷
settings.tiles[index_Mine].setAttribute('val', 1);
} else {
// 如果生产过 就不搭理,但是 i要-1 否则 最终雷的个数就会少
i--;
}
}
// 设置value值,点击之后 显示周围有几个雷
showValue();
}
/**
* 设置value值,点击之后 显示周围有几个雷
*
* 比如周围8个有一个类 就显示1
*/
function showValue() {
// 1 对所有不是雷的元素 设置内容
// 2 获取每个非雷元素的周边8个盒子
// console.log(settings.tiles.length);
for (var i = 0; i < settings.tiles.length; i++) {
// 判断是否是雷,是就跳过
if (settings.tiles[i].getAttribute('val') == 1) {
continue;
}
// 如果不是雷,就获取周边8个元素,传递当前元素的索引 index
store(settings.tiles[i].index);
// console.log(settings.arr);
// 3 遍历8个盒子,对雷的个数进行计数 arr
var count = 0;
for (var j = 0; j < settings.arr.length; j++) {
if (settings.arr[j].getAttribute('val') == 1) {
count++;
}
}
// 4 把计数结果 设置到 当前div的内容当中
// if (count != 0) {
// settings.tiles[i].innerHTML = count;
settings.tiles[i].setAttribute('value', count);
// }
}
}
/**
* 获取周围八个元素
* @param {点击的元素的索引} num
*/
function store(num) {
/**
* settings.tiles 转换为二维数组,方便查找周边八个元素
*/
// var tiles_2d = [];
// 当做 settings.tiles的下标
// var indexs = 0;
// 遍历settings.tiles 封装到二维数组中
// for (var i = 0; i < settings.row; i++) {
// // 二维数组中 添加一个空的一维数组
// tiles_2d.push([]);
// for (var j = 0; j < settings.column; j++) {
// tiles_2d[i].push(settings.tiles[indexs]);
// indexs++;
// }
// }
// 根据点击的元素的索引 获取在二维数组中的下标
// var j = num % settings.column;
// var i = (num - j) / settings.column;
// 对settings.arr 初始化
settings.arr = [];
var index = num;
var c = settings.column;
var r = settings.row;
// 左上
if (index % c > 0 && index - c >= 0) {
settings.arr.push(settings.tiles[index - c - 1]);
}
// 正上
if (index - c >= 0) {
settings.arr.push(settings.tiles[index - c]);
}
// 右上
if (index - c >= 0 && index % c < c - 1) {
settings.arr.push(settings.tiles[index - c + 1]);
}
// 左边
if (index % c > 0) {
settings.arr.push(settings.tiles[index - 1]);
}
// 右边
if (index % c < c - 1) {
settings.arr.push(settings.tiles[index + 1]);
}
// 左下
if (index % c > 0 && index + c < c * r) {
settings.arr.push(settings.tiles[index + c - 1]);
}
// 正下
if (index + c < c * r) {
settings.arr.push(settings.tiles[index + c]);
}
// 右下
if (index % c < c - 1 && index + c < c * r) {
settings.arr.push(settings.tiles[index + c + 1]);
}
// console.log(settings.arr);
}
}
})(jQuery);
修改后代码(jQuery)
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!-- 引入资源 -->
<script src="../resources/js/jquery-1.11.1.min.js"></script>
<script src="../resources/js/sl.js"></script>
<script src="../resources/js/test.js"></script>
<link rel="stylesheet" href="../resources/css/sl.css">
<script>
$(function () {
// 画板对象
var content = $("#content");
// 雷的格式,初级 10,中级 40 , 高级 200
var arr = [10, 40, 200];
// 行和列,默认是方形
var arr_type = [10, 16, 24];
//对自定义输入框进行隐藏
$('.input').hide();
/*
*自定义选择难度
*/
var ar, w_h;
$('#set_num').change(function () {
//通过下拉列表获取难度value值
var val = $("#set_num").val();
//根据获取val 值分别设置行列 和 雷数
//不是自定义
if (val != 3) {
$('.input').hide();//隐藏自定义输入框
ar = arr[val];
w_h = arr_type[val];
} else if (val == 3) {
$('.input').show();//是自定义就显示输入框
}
});
/**
* 开始游戏
*/
$("#start").click(function () {
// 判断游戏是否开始
// 画板中,有盒子的时候说明开始了
// console.log(content.children().length);
if (content.children().length != 0) {
var c = confirm("游戏已经开始,确定需要重新开始吗?");
if (c) {
// 清空内容
content.html("");
// 重新开始游戏
start();
}
} else {
// 开始游戏
start();
}
});
/**
* 开始游戏
*/
function start() {
// 1 隐藏title
$("#title").hide();
// 2 获取选择的难度
var val = $("#set_num").val();
// 3 根据难度获取对应的雷个数和行列
if (val != 3) {
// TODO 调用插件,传入数据
$.fn.mineClearance({
row: w_h,
column: w_h,
mine_num: ar,
obj: '#content'
});
}else if(val == 3){
$.fn.mineClearance({
row: $('.row').val(),
column: $('.col').val(),
mine_num: $('.mine').val(),
obj: '#content'
});
}
}
/**
* 重新加载页面
*/
$("#refresh").click(function () {
// 重新加载页面
window.location.reload();
});
/**
* 字体闪烁
*/
function changeColor() {
var r = Math.floor(Math.random() * 256);
var g = Math.floor(Math.random() * 256);
var b = Math.floor(Math.random() * 256);
var color = 'rgb(' + r + ',' + g + ',' + b + ')';
$("#title").css("color", color);
$(".showed").css("color", color);
}
// 定时器
setInterval(changeColor, 200);
});
</script>
</head>
<body>
<select name="" id="set_num">
<option value="0">初级</option>
<option value="1">中级</option>
<option value="2">高级</option>
<option value="3">自定义</option>
</select>
<div class="input">
行数:<input type="text" class='row'>
列数:<input type="text" class="col">
雷数:<input type="text" class="mine">
</div>
<button id="start">开始游戏</button>
<span id="refresh">重新加载游戏</span>
<div id="content"></div>
<audio id="move" src="../resources/mp3/move.mp3" controls="controls" hidden></audio>
<audio id="gameover" src="../resources/mp3/gameOver.mp3" controls="controls" hidden></audio>
<audio id="boom" src="../resources/mp3/boom.mp3" controls="controls" hidden></audio>
<audio id="click" src="../resources/mp3/click.mp3" controls="controls" hidden></audio>
<audio id="victory" src="../resources/mp3/victory.mp3" controls="controls" hidden></audio>
<h1 id='title'>选择难度并点击确定,开始游戏<br> 右键可以标记小红旗哦~</h1>
</body>
</html>
CSS
*{
margin: 0;
padding: 0;
}
body{
text-align: center;
font-size: 15px;
font-family: '楷体';
}
#content{
/* border: 1px solid; */
/* width: 200px; */
margin: 0 auto;
}
/* 重新加载 */
#refresh{
/* 设置行内块,否则不能设置宽高 */
display: inline-block;
width: 100px;
height: 30px;
/* 行高和高度一致,则内容垂直居中 */
line-height: 30px;
border: 1px solid gray;
/* 圆角边 */
border-radius: 5px;
/* 小手状 */
cursor: pointer;
color: white;
background-color: rgb(143,122,102);
}
/* 每一个div小格子 */
/* 默认 */
#content div{
width: 48px;
height: 49px;
border: 1px solid black;
text-align: center;
font-size: 20px;
line-height: 49px;
cursor: pointer;
float: left;
}
.tile{
background: url(../img/ba.png);
}
/* 已点击 */
.showed{
background: rgb(195,206,228);
/* background-color: red; */
}
/* 雷 */
.boom{
background: rgb(195,206,228) url(../img/Minesmall.png);
}
/* 移入 */
.current{
background: url(../img/baq.png);
}
/* 小红旗 */
.tag{
/* 第一个是前景,第二个是背景 */
background: url(../img/hq.png),url(../img/ba.png);
}
JS
// 使用闭包,解决$命名冲突问题
(function ($) {
/**
*
*/
function change() {
}
/**
* 对外提供的接口
*
* 必须传递 行 row,列 column,雷的个数 mine_num,显示画板的位置 obj 盒子的ID值
*/
$.fn.mineClearance = function (options) {
// console.log(options);
// var obj1 = {name:'张三',age:16};
// var obj2 = {name:'李四',addr:'石家庄'}
// 合并两个对象,如果有相同的属性,则使用后者替换前者
// 所以前者适合做默认值,后者适合做参数传递
// var obj3 = $.extend(obj1,obj2);
// console.log(obj3);
var settings = $.extend({
// 默认列
column: 10,
// 默认行
row: 10,
// 默认雷个数
mine_num: 20,
// 默认画板ID
obj: "#content",
// 每一个div盒子,默认是空数组
tiles: [],
// 周边8个元素
arr: [],
// 判断游戏是否是第一点击,如果是第一次就初始化雷,true表示第一次点击
flag: true
}, options || {});
// 生成画板
buildTiles();
/**
* 生成画板
*/
function buildTiles() {
// 判断行和列是否合法
if (settings.column <= 0 || settings.row <= 0) {
alert('行和列必须大于 0 哦~');
return;
}
// 判断雷
if (settings.mine_num <= 0) {
alert("没雷你玩啥?");
return;
}
if (settings.mine_num >= (settings.column * settings.row)) {
alert("全是雷");
return;
}
// 到这里说明数据没啥问题
// 获取画板的DOM对象
var obj = $(settings.obj);
// 设置画板的宽高
// 每个盒子宽高是49,边框都是1,所以实际宽高为 51
// 画板的宽度 = 列数 * 51
// obj.style.width = 51 * settings.column + "px";
// obj.style.height = 51 * settings.row + "px";
obj.width(51 * settings.column);
obj.height(51 * settings.row);
// 对div添加索引,0,1,2,3,.....
// 方便我们操作,我们能够根据点击的是谁,获取它和周边8个元素
// 比如 3行4列, 我们点的是第6个,索引就是 5
// 5 % 列数 = 1
// (5-1) / 列数 = 1
var indexOfdiv = 0;
// 根据行和列 生成div 并设置索引
for (var i = 0; i < settings.row; i++) {
for (var j = 0; j < settings.column; j++) {
// 创建div标签
// var tile = document.createElement("div");
var tile = $('<div class="tile"></div>');
// 设置class属性值为 tile
// tile.className = 'tile';
// 添加索引
// tile.setAttribute('index',indexOfdiv);
tile.attr('index', indexOfdiv);
// 把div保存到 settings.tiles数组中,方便我们后续操作
settings.tiles[indexOfdiv] = $(tile);
indexOfdiv++;
// 把div添加到 画板中
// obj.appendChild(tile);
obj.append(tile);
}
}
//清空事件,避免叠加事件
obj.unbind();
// 绑定事件
event();
}
/**
* 对div绑定事件
*/
function event() {
// 获取画板对象
var obj = $(settings.obj);
// 对画板绑定事件,通过事件源,找到真正触发的这个小div即可
// 移入
obj.mouseover(function (e) {
// 如果class属性值不是tile ,
// 说明要么你移动到已经点击过的div
// 要么你移动到边框上,就是画板了
// 我们只对未点击过的div做移入事件
if ($(e.target).attr('class') == 'tile') {
$(e.target).attr('class','tile current') ;
//添加音乐
$('#move')[0].play();
}
});
// 移出
obj.mouseout(function (e) {
// 如果class属性值不是tile ,
// 说明要么你移动到已经点击过的div
// 要么你移动到边框上,就是画板了
// 我们只对未点击过的div做移入事件
if ($(e.target).attr('class') == 'tile current') {
$(e.target).attr('class','tile') ;
//取消音乐
$('#move')[0].pause();
}
});
// 右键事件,添加小红旗
obj.contextmenu(function (e) {
// 当右键的时候,如果不是雷,不是已点击的,就可以添加红旗
// 因为如果是boom雷的时候,说明游戏已经结束
if ($(e.target).attr('class') != 'boom' && $(e.target).attr('class') != 'showed') {
// e.target.className = 'tile';
// console.log(e.target.className);
// if(e.target.className.split(' ').length == 3){
// e.target.className = 'tile current'
// }else{
// e.target.className = 'tile current tag'
// }
$(e.target).toggleClass('tag');
}
return false;
});
// 点击事件
obj.click(function (e) {
// alert(22);
if ($(e.target).hasClass('tile')) {
// 获取事件源索引
// var index = e.target.index;
var index = $(e.target).index();
// console.log(index);
// 判断点击的是否含有小红旗
// class属性是否包含 tag
// console.log(e.target.classList.contains('tag'));
if ($(e.target).hasClass('tag')) {
alert("请先右键取消小红旗");
return;
}
}
$('#click')[0].play();
// 到这里 说明点击的不是小红旗
// 初始化所有div , 生成雷,判断周边几个雷
changeStyle($(e.target), index);
});
}
/**
* 生成雷,统计周围雷的个数等
*
* 第一个参数 : 点击的元素
* 第二个参数 : 该元素的index索引
*/
function changeStyle(obj, num_index) {
// 判断是否是第一次点击
if (settings.flag) {
// 是的话,生成雷等信息
// 获取周围八个元素
// store(num_index);
// 生成雷,val 表示,1是雷,0不是雷
setMineCraft();
settings.flag = false;
}
/**
* 初始化操作已完成
*/
// 雷和周边雷个数 已完成,需判断点击之后,是否是雷,是否游戏结束(胜利和失败),不是雷就需要进行扩散显示
// 不是就判断点击的是否是雷
// 判断游戏是否结束 - 胜利, 失败
if (!obj.attr('val')) {
// 设置为已点击状态
// obj.className = 'showed';
obj.attr('class', 'showed');
// 显示周围几个雷
// let value = obj.getAttribute('value');
let value = obj.attr('value');
obj.html(value) == 0 ? '' : value;
// 扩散显示
showAll(obj.index());
}
// 判断游戏是否结束,如果结束,显示所有div信息
// 比如 是雷的 就替换成雷的图片,周围有几个雷 就显示几
if (over(obj)) {
// 进来说明游戏结束
// 显示所有div信息
show();
}
}
/**
* 游戏结束 重置div,所有信息都显示
*/
function show() {
// 思路 : 遍历所有div 判断val是1是0 是 设置class为 boom 是0 设置class为 showed
for (var i = 0; i < settings.tiles.length; i++) {
// settings.tiles[i].className = settings.tiles[i].getAttribute('val') == 1 ? 'boom' : 'showed';
// console.log($(settings.tiles[i].addClass('val')));
// $(settings.tiles[i]).addClass($(settings.tiles[i]).attr('val') ==1 ? 'boom' : 'showed') ;
$(settings.tiles[i]).attr('class', $(settings.tiles[i]).attr('val') == 1 ? 'boom' : 'showed')
// 如果不是雷 就要显示周边几个雷
if ($(settings.tiles[i]).attr('class') != 'boom') {
var value = $(settings.tiles[i]).attr('value');
$(settings.tiles[i]).html(value) == 0 ? '' : value;
}
}
// 取消事件
$(settings.obj).unbind('click');
}
/**
* 游戏结束判断
*
* @param {点击的元素} obj
*/
function over(obj) {
// true说明结束,false说明没有结束
var flag = false;
// 如何算游戏胜利 : 已点击的 + 雷的个数 = 总div个数
// 获取已点击的元素
var showed = $('.showed');
// div总个数 减去 雷的个数,得到剩余div个数
var num = settings.tiles.length - settings.mine_num;
if (num == showed.length) {
$('#victory')[0].play();
alert("恭喜你获得成功~");
flag = true;
// 如何算失败 : 点到雷就失败 val == 1
} else if (obj.attr('val') == 1) {
$('#boom')[0].play();
alert('被炸死,游戏结束!');
$('#gameover')[0].play();
flag = true;
}
// 没结束 就返回false,继续游戏
return flag;
}
/**
* 判断周围是否是雷,如果不是雷,就全部显示
*
* 如果周围有雷,就不再进行遍历
*
* @param {点击元素的索引} num
*/
function showAll(num) {
// 判断 周围是否有雷
// 如果有 终止
// 如果没有,遍历周边元素的周边元素,依次判断
// console.log($(settings.tiles[num]).attr('class') == 'showed'==$(settings.tiles[num]).attr('value'));
if ($(settings.tiles[num]).attr('class') == 'showed' && $(settings.tiles[num]).attr('value') == 0) {
// 获取周边8个(settings.arr)
store(num);
// 如果递归,会更改arr的值,所以保存为局部变量
var arr2 = settings.arr;
// 非showed
for (var i = 0; i < arr2.length; i++) {
// 如果添加小红旗标识 就跳过该次循环
// console.log($(arr2[i]).hasClass('tag'));
if ($(arr2[i]).hasClass('tag')) {
continue;
}
if ($(arr2[i]).attr('class') != 'showed') {
// value == 0
// 判断周边8个是否有雷,没有就显示并递归
if ($(arr2[i]).attr('value') == 0) {
// true 递归
// arr2[i].className = 'showed';
$(arr2[i]).attr('class', 'showed');
// console.log($(arr2[i]).index());
showAll($(arr2[i]).attr('value'));
} else {
// false 设置为showed并显示value
// arr2[i].className = 'showed';
$(arr2[i]).attr('class', 'showed');
// arr2[i].innerHTML = arr2[i].getAttribute('value');
$(arr2[i]).html($(arr2[i]).attr('value'));
}
}
}
}
}
/**
* 生成雷,val 表示,1是雷,0不是雷
*/
function setMineCraft() {
// 雷的个数
var num = settings.mine_num;
// 遍历所有div 设置不是雷
// for (var i = 0; i < settings.tiles.length; i++) {
// settings.tiles[i].setAttribute('val', 0);
// }
// 随机生成雷
for (var i = 0; i < num; i++) {
// 随机的雷的索引
var index_Mine = Math.floor(Math.random() * settings.tiles.length);
// 判断生成的索引 是否生产过雷
// console.log(settings.tiles[index_Mine].getAttribute("val"));
if (!$(settings.tiles[index_Mine]).attr("val")) {
// 没有 就设置为 雷
$(settings.tiles[index_Mine]).attr('val', 1);
} else {
// 如果生产过 就不搭理,但是 i要-1 否则 最终雷的个数就会少
i--;
}
}
// 设置value值,点击之后 显示周围有几个雷
showValue();
}
/**
* 设置value值,点击之后 显示周围有几个雷
*
* 比如周围8个有一个类 就显示1
*/
function showValue() {
// 1 对所有不是雷的元素 设置内容
// 2 获取每个非雷元素的周边8个盒子
// console.log(settings.tiles.length);
for (var i = 0; i < settings.tiles.length; i++) {
// 判断是否是雷,是就跳过
if ($(settings.tiles[i]).attr('val') == 1) {
continue;
}
// 如果不是雷,就获取周边8个元素,传递当前元素的索引 index
store($(settings.tiles[i]).index());
// console.log(settings.arr);
// 3 遍历8个盒子,对雷的个数进行计数 arr
var count = 0;
for (var j = 0; j < settings.arr.length; j++) {
if ($(settings.arr[j]).attr('val') == 1) {
count++;
}
}
// 4 把计数结果 设置到 当前div的内容当中
// if (count != 0) {
// settings.tiles[i].innerHTML = count;
// settings.tiles[i].setAttribute('value', count);
$(settings.tiles[i]).attr('value', count);
// }
}
}
/**
* 获取周围八个元素
* @param {点击的元素的索引} num
*/
function store(num) {
/**
* settings.tiles 转换为二维数组,方便查找周边八个元素
*/
// var tiles_2d = [];
// 当做 settings.tiles的下标
// var indexs = 0;
// 遍历settings.tiles 封装到二维数组中
// for (var i = 0; i < settings.row; i++) {
// // 二维数组中 添加一个空的一维数组
// tiles_2d.push([]);
// for (var j = 0; j < settings.column; j++) {
// tiles_2d[i].push(settings.tiles[indexs]);
// indexs++;
// }
// }
// 根据点击的元素的索引 获取在二维数组中的下标
// var j = num % settings.column;
// var i = (num - j) / settings.column;
// 对settings.arr 初始化
settings.arr = [];
var index = num;
var c = settings.column;
var r = settings.row;
// 左上
if (index % c > 0 && index - c >= 0) {
settings.arr.push(settings.tiles[index - c - 1]);
}
// 正上
if (index - c >= 0) {
settings.arr.push(settings.tiles[index - c]);
}
// 右上
if (index - c >= 0 && index % c < c - 1) {
settings.arr.push(settings.tiles[index - c + 1]);
}
// 左边
if (index % c > 0) {
settings.arr.push(settings.tiles[index - 1]);
}
// 右边
if (index % c < c - 1) {
settings.arr.push(settings.tiles[index + 1]);
}
// 左下
if (index % c > 0 && index + c < c * r) {
settings.arr.push(settings.tiles[index + c - 1]);
}
// 正下
if (index + c < c * r) {
settings.arr.push(settings.tiles[index + c]);
}
// 右下
if (index % c < c - 1 && index + c < c * r) {
settings.arr.push(settings.tiles[index + c + 1]);
}
// console.log(settings.arr);
}
}
})(jQuery);