经典版扫雷

前言

此次游戏为非常经典的游戏 —— 扫雷。

直接上代码

 

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>

 

posted @ 2021-12-27 16:39  007的张大炮  阅读(102)  评论(0编辑  收藏  举报