喜欢就给我点个星吧:https://github.com/Chenyating/easyGame
先了解一下扫雷这个游戏规则:我们可以先,打开你的电脑——》程序——》游戏——》扫雷,先玩几分钟,你就会得到规律:
点击任意方块,会出现2种结果:
-
如果是炸弹就引爆,游戏则结束。
-
如果不是炸弹,那么游戏继续。
游戏继续的同时,我们会发现,我才按了一下
就会出现两种情况:
-
有的的区域只出现了一个小白空格,如红色区域。
-
有的区域是出现很多空白边,如橙色区域。
1、红色区域你会发现,小方格显示数字2。这个方格不是炸弹,变白。然后计算以该方格四周的炸弹数,存在则游戏结束;
2、橙色区域你会发现,我所点击小方格不是炸弹,并且它四周的炸弹数为0,该方格变白后,它四周的小方格继续计算他们四周的炸弹数。以此类推,直到四周存在炸弹,或者以到边界;
如下图所示:以左上小方格为例子。这样有8种结果;
现在我们算是明白,扫雷应该怎么玩了对吧。
现在我们开始挽起袖子,写代码:
这是我的游戏界面:http://www.yating.online/game/mine.html
2.1、我们先开始画雷区。
我用all数组表示雷区,all【i】【j】=【1,-1】;表示第i行,j列的小方格。
【1,-1】
第一个数值表示,该方格是不是炸弹,大于0为炸弹;
第二个则表示,它周围存在的炸弹数。默认为-1,这里的数值一会要在方格上显示;
// 开始画雷区
painBomb() {
for (let i = 0; i < this.height; i++) {
this.all[i] = [];
for (let j = 0; j < this.width; j++) {
this.all[i][j] = [0, -1];
}
}
},
我的小方块是由无数个div放在游戏区域:对应all,显示我的雷区,小方格则就显示all【n】【m】【1】即它周围的炸弹数;
<div class="playStage">
<div class="coverY" v-for="n in height-2" v-if="all.length">
<!-- x值 -->
<div class="coverX titlex" v-for="m in width-2" v-if="all[n-1]" @click="click(n,m)" :class="{safe: all[n][m][1]>=0,whiteText: all[n][m][1]==0,bered: all[n][m][0]==2}">
{{all[n][m][1]}}
</div>
</div>
</div>
为了省去一些麻烦,我把雷区的上下左右边去掉,不显示。
这里的麻烦是:若我点击蓝色方块,那么我就得多一道工序,去计算除去靠近它的5个小方格的炸弹数。
这样得不偿失,还多写几行代码。所以我就默认最外框不可点击,并且不存在炸弹;
这样,小红框内区域的任何一个小方格点击以后都可以用同一个方法来判断了。
2.2、接下来就是写点击一个小方格,用到的方法:
// 点击小方格
click(x, y) {
if (this.all[x][y][0] == 1) {
this.showBomb();
alert("你踩到雷啦!")
return;
} else {
this.andThen(x, y);
this.ifOk();
}
},
如果这个小方格是炸弹,那么就结束游戏。并且显示我的所有炸弹:showBomb()。
这里我把炸弹的值改成2.在页面上便会显示红色;
:class="{safe: all[n][m][1]>=0,whiteText: all[n][m][1]==0,bered: all[n][m][0]==2}"
// 显示炸弹
showBomb() {
for (var i = 1; i < this.height - 1; i++) {
for (var j = 1; j < this.width - 1; j++) {
if (this.all[i][j][1] == -1 && this.all[i][j][0] == 1) {
this.$set(this.all, i, this.all[i])
this.$set(this.all[i], j, this.all[i][j]);
this.$set(this.all[i][j], 0, 2);
}
}
}
}
如果该小方块不是炸弹的话,那么我们就可以进行一步,andThen()方法;
开始之前都要先判断一下,这个它是否是炸弹,或者它是否已经写上它周围的炸弹数,若满足,那我们就不需要白忙活了,直接return;
在使用andThen()方法,要开始计算该小方格四周的炸弹数,一共有8个小方格,都分别判断一下。(这里自己也要判断一下,因为一会还要在调用自身;)
若自己是炸弹的话,那么就停止。
andThen(x, y) {
if (this.all[x][y][0] == 1 || this.all[x][y][1] > -1) {
return;
}
this.num = 0;
try {
if (this.all[x - 1][y - 1][0] == 1) {
this.num += 1;
}
if (this.all[x - 1][y][0] == 1) {
this.num += 1;
}
if (this.all[x - 1][y + 1][0] == 1) {
this.num += 1;
}
if (this.all[x][y - 1][0] == 1) {
this.num += 1;
}
if (this.all[x][y][0] == 1) {
return;
}
if (this.all[x][y + 1][0] == 1) {
this.num += 1;
}
if (this.all[x + 1][y - 1][0] == 1) {
this.num += 1;
}
if (this.all[x + 1][y][0] == 1) {
this.num += 1;
}
if (this.all[x + 1][y + 1][0] == 1) {
this.num += 1;
}
this.$set(this.all, x, this.all[x])
this.$set(this.all[x], y, this.all[x][y]);
this.$set(this.all[x][y], 1, this.num);
if (this.num == 0) {
this.andThen(x - 1, y - 1);
this.andThen(x - 1, y);
this.andThen(x - 1, y + 1);
this.andThen(x, y - 1);
this.andThen(x, y + 1);
this.andThen(x + 1, y - 1);
this.andThen(x + 1, y);
this.andThen(x + 1, y + 1);
} else {
return;
}
} catch (error) {}
},
因为x的取值范围在1~width-2;y的取值范围在1~height-2。这里我就直接用try{ }catch(){ } 。
最后把得出的炸弹数赋值给自己的第二个数值;这时候div对应的小方格也会展示周围的炸弹数:
每次点击完成以后,我们都要算一下,现场剩下的小方格是不是只有炸弹了。这里就用isOk()来判断一下;每调用一次click()都要重新计算一遍;
// 是否成功
ifOk() {
var lastNum = 0;
for (var i = 1; i < this.height - 1; i++) {
for (var j = 1; j < this.width - 1; j++) {
if (this.all[i][j][1] == -1) {
lastNum += 1;
}
}
}
if (lastNum == this.bombNum&&this.pass==false) {
this.showBomb();
alert("完全没有踩到地雷,你好棒棒哦")
this.pass=true;
}
},
这样,我们的扫雷就大功告成了。
最后就随机隐藏几个炸弹吧。记住了啊。我们雷区的外边都不要有炸弹哦。所以随机的范围必须要在小红框里;
// 开始随机游戏
randomBegin(bombNumber) {
this.painBomb();
this.bombNum = bombNumber;
this.bomb = 0;
for (let i = 0; i < this.height; i++) {
for (let j = 0; j < this.width; j++) {
this.$set(this.all, i, this.all[i])
this.$set(this.all[i], j, this.all[i][j]);
this.$set(this.all[i][j], 0, 0);
this.$set(this.all[i][j], 1, -1);
}
}
this.random();
},
// 随便上色
random() {
this.pass=false;
var a, b;
a = parseInt(Math.random() * (this.height - 2) + 1);
b = parseInt(Math.random() * (this.width - 2) + 1);
if (this.bomb < this.bombNum) {
// 如果这个数炸弹,那么重新随机
if (this.all[a][b][0] == 1) {
this.random();
}
// 否则给他设置为炸弹
else {
this.bomb = this.bomb + 1;
this.$set(this.all, a, this.all[a])
this.$set(this.all[a], b, this.all[a][b]);
this.$set(this.all[a][b], 0, 1);
this.random();
}
} else {
return;
}
},
最后放上js代码:
var mine = new Vue({
el: "#mine",
data: {
width: 12,
height: 25,
all: [],
bomb: 0,
num: 0,
bombNum: 20,
pass:false
},
methods: {
// 开始画炸弹
painBomb() {
for (let i = 0; i < this.height; i++) {
this.all[i] = [];
for (let j = 0; j < this.width; j++) {
this.all[i][j] = [0, -1];
}
}
},
// 点击空白
click(x, y) {
if (this.all[x][y][0] == 1) {
this.showBomb();
alert("你踩到雷啦!")
return;
} else {
this.andThen(x, y);
this.ifOk();
}
},
andThen(x, y) {
if (this.all[x][y][0] == 1 || this.all[x][y][1] > -1) {
return;
}
this.num = 0;
try {
if (this.all[x - 1][y - 1][0] == 1) {
this.num += 1;
}
if (this.all[x - 1][y][0] == 1) {
this.num += 1;
}
if (this.all[x - 1][y + 1][0] == 1) {
this.num += 1;
}
if (this.all[x][y - 1][0] == 1) {
this.num += 1;
}
if (this.all[x][y][0] == 1) {
return;
}
if (this.all[x][y + 1][0] == 1) {
this.num += 1;
}
if (this.all[x + 1][y - 1][0] == 1) {
this.num += 1;
}
if (this.all[x + 1][y][0] == 1) {
this.num += 1;
}
if (this.all[x + 1][y + 1][0] == 1) {
this.num += 1;
}
this.$set(this.all, x, this.all[x])
this.$set(this.all[x], y, this.all[x][y]);
this.$set(this.all[x][y], 1, this.num);
if (this.num == 0) {
this.andThen(x - 1, y - 1);
this.andThen(x - 1, y);
this.andThen(x - 1, y + 1);
this.andThen(x, y - 1);
this.andThen(x, y + 1);
this.andThen(x + 1, y - 1);
this.andThen(x + 1, y);
this.andThen(x + 1, y + 1);
} else {
return;
}
} catch (error) {}
},
// 开始随机游戏
randomBegin(bombNumber) {
this.painBomb();
this.bombNum = bombNumber;
this.bomb = 0;
for (let i = 0; i < this.height; i++) {
for (let j = 0; j < this.width; j++) {
this.$set(this.all, i, this.all[i])
this.$set(this.all[i], j, this.all[i][j]);
this.$set(this.all[i][j], 0, 0);
this.$set(this.all[i][j], 1, -1);
}
}
this.random();
},
// 随便上色
random() {
this.pass=false;
var a, b;
a = parseInt(Math.random() * (this.height - 2) + 1);
b = parseInt(Math.random() * (this.width - 2) + 1);
if (this.bomb < this.bombNum) {
// 如果这个数炸弹,那么重新随机
if (this.all[a][b][0] == 1) {
this.random();
}
// 否则给他设置为炸弹
else {
this.bomb = this.bomb + 1;
this.$set(this.all, a, this.all[a])
this.$set(this.all[a], b, this.all[a][b]);
this.$set(this.all[a][b], 0, 1);
this.random();
}
} else {
return;
}
},
// 是否成功
ifOk() {
var lastNum = 0;
for (var i = 1; i < this.height - 1; i++) {
for (var j = 1; j < this.width - 1; j++) {
if (this.all[i][j][1] == -1) {
lastNum += 1;
}
}
}
if (lastNum == this.bombNum&&this.pass==false) {
this.showBomb();
alert("完全没有踩到地雷,你好棒棒哦")
this.pass=true;
}
},
// 显示炸弹
showBomb() {
for (var i = 1; i < this.height - 1; i++) {
for (var j = 1; j < this.width - 1; j++) {
if (this.all[i][j][1] == -1 && this.all[i][j][0] == 1) {
this.$set(this.all, i, this.all[i])
this.$set(this.all[i], j, this.all[i][j]);
this.$set(this.all[i][j], 0, 2);
}
}
}
}
},
mounted() {
},
})
放上html代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=yes">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>扫雷-YATING</title>
<!-- <meta name="viewport" content="width=device-width, initial-scale=1"> -->
<link rel="stylesheet" href="css/mine.css" />
<script src="js/vue.js"></script>
<script src="js/jquery.js"></script>
</head>
<body>
<div id="mine">
<div class="title">MINE-扫雷</div>
<div class="stage">
<div class="playStage">
<div class="coverY" v-for="n in height-2" v-if="all.length">
<!-- x值 -->
<div class="coverX titlex" v-for="m in width-2" v-if="all[n-1]" @click="click(n,m)" :class="{safe: all[n][m][1]>=0,whiteText: all[n][m][1]==0,bered: all[n][m][0]==2}">
{{all[n][m][1]}}
</div>
</div>
</div>
<div class="operation">
<p>随机20个炸弹</p>
<div class="inf" @click="randomBegin(20)">
开始
</div>
<p>随机30个炸弹</p>
<div class="inf" @click="randomBegin(30)">
开始
</div>
<p>随机40个炸弹</p>
<div class="inf" @click="randomBegin(40)">
开始
</div>
<p>随机50个炸弹</p>
<div class="inf" @click="randomBegin(50)">
开始
</div>
<p>随机60个炸弹</p>
<div class="inf" @click="randomBegin(60)">
开始
</div>
</div>
</div>
<div class="explain">
Fingers click on diamonds, red as bombs
<div class="chinese">手指点击方块,红色为炸弹</div>
</div>
</div>
<script src="js/mine.js"></script>
<script>
document.body.addEventListener('touchmove', function (e) {
e.preventDefault(); //阻止默认的处理方式(阻止下拉滑动的效果)
}, {
passive: false
}); //passive 参数不能省略,用来兼容ios和android
</script>
</body>
</html>
结束~本人小白菜,欢迎留言~