经典版扫雷
前言
此次游戏为非常经典的游戏 —— 扫雷。
直接上代码
1、游戏界面
<template>
<!-- 扫雷 -->
<view class="bomb z-height flexColumn">
<!-- 时间、雷数 -->
<view class="bomb-head flexItems boxtb">
<view class="bomb-head-time flexCenter flex1">
<view class="bomb-head-icon flexCenter">
<u-icon name="clock" size="80" color="#999"></u-icon>
</view>
<view class="bomb-head-box">{{time}}</view>
</view>
<view class="bomb-head-number flexCenter flex1">
<view class="bomb-head-icon flexCenter">
<u-icon name="/static/image/home/index-bomb.png" size="70"></u-icon>
</view>
<view class="bomb-head-box">{{showBomb}}</view>
</view>
</view>
<!-- 游戏区 -->
<view class="bomb-main flex1 flexCenter">
<scroll-view scroll-y="true" style="width: 100%;height: 100%;">
<view class="bomb-main-box">
<view class="bomb-tr flex" v-for="(item1, index1) in bombList" :key="index1">
<view class="bomb-td" v-for="(item2, index2) in item1" :key="index2" @click="bindBlock(index1,index2)">
<view class="bomb-td-box bomb-td-close" v-if="!item2.is_open">
<u-icon name="/static/image/bomb/flag.png" size="44" v-show="item2.is_flag" />
</view>
<view class="bomb-td-box bomb-td-open" :class="{'bomb-td-boom' : item2.is_bomb}">
<u-icon name="/static/image/home/index-bomb.png" size="50" v-if="item2.is_bomb" />
<text v-else>{{item2.num > 0 ? item2.num : ''}}</text>
</view>
</view>
</view>
</view>
</scroll-view>
</view>
<!-- 插旗、翻开、等级 -->
<view class="bomb-foot" v-if="!is_end">
<view class="bomb-foot-btn" :class="{'bomb-foot-btn-hover': bind == 0}" @click="bindBottom(0)">翻 开</view>
<view class="bomb-foot-btn" :class="{'bomb-foot-btn-hover': bind == 1}" @click="bindBottom(1)">插 旗</view>
<view class="bomb-foot-btn" :class="{'bomb-foot-btn-hover': bind == 2}" @click="bindBottom(2)">等 级</view>
</view>
<!-- 重新开始 -->
<view class="bomb-foot" v-else>
<view class="bomb-foot-btn" @click="bindRestart">重新开始</view>
</view>
<!-- 等级选择 -->
<u-popup v-model="showLevel" mode="center" borderRadius="10">
<view class="bomb-level">
<view class="bomb-level-item fontBold flexColumn flexCenter" @click="bindLevel(0)">
<view class="bomb-level-item-title u-font-40">入 门</view>
<view class="flexItems u-m-t-10">(<u-icon name="/static/image/home/index-bomb.png" size="40"></u-icon>10个<text class="u-m-l-20">10*10</text>)</view>
</view>
<view class="bomb-level-item fontBold flexColumn flexCenter" @click="bindLevel(1)">
<view class="bomb-level-item-title u-font-40">普 通</view>
<view class="flexItems u-m-t-10">(<u-icon name="/static/image/home/index-bomb.png" size="40"></u-icon>30个<text class="u-m-l-20">15*10</text>)</view>
</view>
<view class="bomb-level-item fontBold flexColumn flexCenter" @click="bindLevel(2)">
<view class="bomb-level-item-title u-font-40">地 狱</view>
<view class="flexItems u-m-t-10">(<u-icon name="/static/image/home/index-bomb.png" size="40"></u-icon>50个<text class="u-m-l-20">20*10</text>)</view>
</view>
</view>
</u-popup>
</view>
</template>
2、游戏样式
<style lang="scss" scoped>
.bomb-head{
background-color: rgb(198,212,231);box-shadow: 0 4rpx 20rpx rgba(133,155,200,.5);position: relative;
.bomb-head-icon{width: 80rpx;height: 80rpx;background-color: #fff;border-radius: 50%;border: 2rpx solid rgba(0,0,0,.2);box-shadow: 0 0 10rpx 0 rgba(0,0,0,.1);}
.bomb-head-box{width: 140rpx;padding: 4rpx 0;text-align: center;background: linear-gradient(to bottom, rgb(58,93,156), rgb(72,108,192));margin-left: 20rpx;color: #fff;font-size: 40rpx;border-radius: 20rpx;box-shadow: inset 4rpx 4rpx 10rpx rgba(0,0,0,.5);}
}
.bomb-main{
background-color: rgb(212,219,230);overflow: hidden;
.bomb-main-box{width: 100%;}
.bomb-td{
height: 75rpx;position: relative;display: flex;align-items: center;justify-content: center;flex: 1;border-radius: 10rpx;font-weight: bold;font-size: 34rpx;color: rgb(34,72,168);
.bomb-td-box{position: absolute;width: 100%;height: 100%;top: 0;left: 0;display: flex;align-items: center;justify-content: center;}
.bomb-td-close{
background: linear-gradient(to bottom, rgb(145,207,249), rgb(55,117,212));
border-top: 8rpx solid rgb(214,238,254);
border-bottom: 8rpx solid rgb(13,78,210);
border-right: 8rpx solid rgb(27,114,231);
border-left: 8rpx solid rgb(144,206,248);
z-index: 10;
}
.bomb-td-open{
background: rgb(222,229,240);
border-top: 4rpx solid rgb(176,191,220);
border-right: 4rpx solid rgb(176,191,220);
border-left: 4rpx solid rgb(116,137,186);
border-bottom: 4rpx solid rgb(116,137,186);
box-shadow: inset 0 0 4rpx rgba(176,191,220,1);
z-index: 5;
}
.bomb-td-boom{background: #ff2424;}
}
}
.bomb-foot{
display: flex;align-items: center;justify-content: space-around;padding: 30rpx 20rpx;background: linear-gradient(to bottom, rgb(224,234,248), rgb(206,219,236));box-shadow: 0 -4rpx 10rpx rgba(206,219,236,1);position: relative;
.bomb-foot-btn{width: 200rpx;height: 90rpx;display: flex;align-items: center;justify-content: center;border: 4rpx solid rgb(67,110,194);border-radius: 10rpx;font-size: 40rpx;font-weight: bold;color: rgb(28,43,71);}
.bomb-foot-btn-hover{background: radial-gradient(rgb(255,255,255), rgb(67,110,194));}
}
.bomb-level{
padding: 40rpx 70rpx;
.bomb-level-item{
width: 400rpx;padding: 20rpx 0;margin: 30rpx 0;border: 4rpx solid rgb(67, 110, 194);border-radius: 20rpx;
.bomb-level-item-title{color: rgb(37, 85, 167);}
}
}
</style>
3、游戏逻辑
<script>
export default {
data() {
return {
is_pause: false, // 是否暂停
is_end: false, // 是否结束
row: 10, // 行
col: 10, // 列
bombList: [],
bomb: 10, // 地雷数量
showBomb: 10, // 地雷数字展示
bind: 0, // 0=翻开 1=插旗 2=暂停
time: 0, // 时间
timer: null,
level: 0, // 等级
showLevel: false, // 等级选择
};
},
onLoad() {
this.init();
},
onUnload() {
clearInterval(this.timer);
},
watch:{
showLevel(newVal, oldVal) {
this.bind = newVal ? 2 : 0;
},
},
methods:{
// 初始化
init(){
this.bombList = [];
// 布置战场
for(let i = 0; i < this.row; i++){
this.bombList[i] = [];
for(let j = 0; j < this.col; j++){
this.bombList[i][j] = {
is_open: false, // 是否翻开
is_bomb: false, // 是否有雷
is_flag: false, // 是否插旗
num: 0, // 提示数字
};
}
}
// 埋地雷;
let num = 0;
for(let a = 1; a > 0; a++){
let bomb_x = Math.floor(Math.random() * this.row);
let bomb_y = Math.floor(Math.random() * this.col);
if(!this.bombList[bomb_x][bomb_y].is_bomb){
this.bombList[bomb_x][bomb_y].is_bomb = true;
num++;
}
if(num == this.bomb) break;
}
// 计算雷周围的数字
this.bombList.forEach((item1, index1) => {
item1.forEach((item2, index2) => {
if((index1 - 1 >= 0 && index2 - 1 >= 0) && this.bombList[index1 - 1][index2 - 1].is_bomb){
item2.num++;
}
if((index1 - 1 >= 0) && this.bombList[index1 - 1][index2].is_bomb){
item2.num++;
}
if((index1 - 1 >= 0 && index2 + 1 < this.col) && this.bombList[index1 - 1][index2 + 1].is_bomb){
item2.num++;
}
if((index2 - 1 >= 0) && this.bombList[index1][index2 - 1].is_bomb){
item2.num++;
}
if((index2 + 1 < this.col) && this.bombList[index1][index2 + 1].is_bomb){
item2.num++;
}
if((index1 + 1 < this.row && index2-1 >= 0) && this.bombList[index1 + 1][index2 - 1].is_bomb){
item2.num++;
}
if((index1 + 1 < this.row) && this.bombList[index1 + 1][index2].is_bomb){
item2.num++;
}
if((index1 + 1 < this.row && index2 + 1 < this.col) && this.bombList[index1 + 1][index2 + 1].is_bomb){
item2.num++;
}
});
});
// 计时器
clearInterval(this.timer)
this.timer = setInterval(() => {
this.time++;
},1000)
},
// 底部按钮
bindBottom(index){
this.bind = index;
this.showLevel = index == 2 ? true : false;
},
// 选择等级
bindLevel(index){
this.level = index
this.showLevel = false;
this.bindRestart();
},
// 重新开始
bindRestart(){
this.row = this.level == 0 ? 10 : this.level == 1 ? 15 : 20;
this.bomb = this.level == 0 ? 10 : this.level == 1 ? 30 : 50;
this.showBomb = this.level == 0 ? 10 : this.level == 1 ? 30 : 50;
this.is_pause = false;
this.is_end = false;
this.time = 0;
clearInterval(this.timer)
this.init();
},
// 点击方块
bindBlock(x, y){
// 是否结束
if(this.is_end){
return;
}
// 翻开
if(this.bind == 0 && !this.bombList[x][y].is_flag && !this.bombList[x][y].is_open){
this.bombList[x][y].is_open = true;
this.$forceUpdate();
// 判断是否有雷
if(this.bombList[x][y].is_bomb){
// 如果点到雷了,就把所有雷都展示出来
this.bombList.forEach(item1 => {
item1.forEach(item2 => {
if(item2.is_bomb) item2.is_open = true;
})
});
uni.showModal({showCancel: false, content: "你输了"});
this.is_end = true;
clearInterval(this.timer);
return;
}
// 判断是否是空白
if(this.bombList[x][y].num == 0){
this.blockExtend(x, y);
}
// 判断是否赢了
if(this.getWin()){
uni.showModal({showCancel: false, content: "你!终!于!赢!了!"});
this.is_end = true;
clearInterval(this.timer);
return;
}
}
// 插旗子
if(this.bind == 1 && !this.bombList[x][y].is_open){
this.bombList[x][y].is_flag = !this.bombList[x][y].is_flag;
this.bombList[x][y].is_flag ? this.showBomb-- : this.showBomb++;
this.$forceUpdate();
}
},
// 方块延伸
blockExtend(x, y){
// [x-1, y], [x+1, y], [x, y-1], [x, y+1], [x-1, y-1], [x+1, y+1], [x-1, y+1], [x+1, y-1]
if(x - 1 >= 0 && !this.bombList[x - 1][y].is_bomb && !this.bombList[x - 1][y].is_open && !this.bombList[x - 1][y].is_flag){
this.bombList[x - 1][y].is_open = true;
if(this.bombList[x - 1][y].num == 0){
this.blockExtend(x - 1, y);
}
}
if(x + 1 < this.row && !this.bombList[x + 1][y].is_bomb && !this.bombList[x + 1][y].is_open && !this.bombList[x + 1][y].is_flag){
this.bombList[x + 1][y].is_open = true;
if(this.bombList[x + 1][y].num == 0){
this.blockExtend(x + 1, y);
}
}
if(y - 1 >= 0 && !this.bombList[x][y - 1].is_bomb && !this.bombList[x][y - 1].is_open && !this.bombList[x][y - 1].is_flag){
this.bombList[x][y - 1].is_open = true;
if(this.bombList[x][y - 1].num == 0){
this.blockExtend(x, y - 1);
}
}
if((y + 1 < this.col) && !this.bombList[x][y + 1].is_bomb && !this.bombList[x][y + 1].is_open && !this.bombList[x][y + 1].is_flag){
this.bombList[x][y + 1].is_open = true;
if(this.bombList[x][y + 1].num == 0){
this.blockExtend(x, y + 1);
}
}
if((x - 1 >=0 && y - 1 >= 0) && !this.bombList[x - 1][y - 1].is_bomb && !this.bombList[x - 1][y - 1].is_open && !this.bombList[x - 1][y - 1].is_flag){
this.bombList[x - 1][y - 1].is_open = true;
if(this.bombList[x - 1][y - 1].num == 0){
this.blockExtend(x - 1, y - 1);
}
}
if((x + 1 < this.row && y + 1 < this.col) && !this.bombList[x + 1][y + 1].is_bomb && !this.bombList[x + 1][y + 1].is_open && !this.bombList[x + 1][y + 1].is_flag){
this.bombList[x + 1][y + 1].is_open = true;
if(this.bombList[x + 1][y + 1].num == 0){
this.blockExtend(x + 1, y + 1);
}
}
if((x - 1 >= 0 && y + 1 < this.col) && !this.bombList[x - 1][y + 1].is_bomb && !this.bombList[x - 1][y + 1].is_open && !this.bombList[x - 1][y + 1].is_flag){
this.bombList[x - 1][y + 1].is_open = true;
if(this.bombList[x - 1][y + 1].num == 0){
this.blockExtend(x - 1, y + 1);
}
}
if((x + 1 < this.row && y - 1 >= 0) && !this.bombList[x + 1][y - 1].is_bomb && !this.bombList[x + 1][y - 1].is_open && !this.bombList[x + 1][y - 1].is_flag){
this.bombList[x + 1][y - 1].is_open = true;
if(this.bombList[x + 1][y - 1].num == 0){
this.blockExtend(x + 1, y - 1);
}
}
},
// 是否赢了
getWin(){
let arr = [];
this.bombList.forEach(item1 => {
item1.forEach(item2 => {
if(!item2.is_open){
arr.push(item2);
}
});
});
return arr.length == this.bomb ? true : false;
},
}
}
</script>