Bootstrap

微信小程序实验四 —— 扫雷游戏

实验小提醒,打开微信小程序模板时,一定要看清楚,要选js模板,不要选ts模板,因为ts中对数据类型检查更严格,同样的代码在ts中可能无法运行!

实验内容:

编写如下扫雷游戏,基本要求如下:

(1)方块数为10行7列;

(2)有游戏计时(计时单位为秒);

(3)有一个“开始游戏”按钮,按该按钮能重新开始一局游戏。

可依据个人能力自由发挥点:

(1)让玩家可以自由设定方块数;

(2)让玩家可以自由设定地雷数;

实验效果:

        

程序优势:

1,必须点击开始游戏,才能点击方块,避免用户误碰影响玩的体验

2,游戏玩到中途,可以新开一局,也可以在点击新开一局后,点击取消,继续玩

3,可以点击设置,设置行数,列数或者地雷数任意一个参数,游戏怎么玩儿,由你定

代码目录:

这里面index目录下面四个文件,放的是扫雷相关的代码; 而setUp目录中的四个文件放的是设置页面相关的代码!

 

 

实验代码:

     index目录下的代码文件

     index.wxml

<!--index.wxml-->
<view class="time">
  <view class="using-time">当前用时:{{timeformat}}</view>
   <view class="start-game" bindtap="start"> 开始游戏 </view>
   
</view>
<view bindtap="setUp" class="set-up">设置</view>
<view class="main">
  <view wx:for="{{bts}}" wx:for-item="itemRow" class="yy"> 
    <view wx:for="{{itemRow}}" wx:for-item="bt" class="xx" id="{{bt.id}}" style="background-color:{{bt.bgcolor}};color:{{bt.ftcolor}}" bindtap="click">
       {{bt.text}}
    </view>
  </view>
</view>

 index.js

Page({
  data: {
    bts: null, //9*6数组  54个方块,根方块有关的属性全部存储起来
    timer:null,
    hour:0,
    minute:0,
    second:0,
    timeformat:'00:00:00',
    clickButton:false,
    cancelButton:false
  },
   
  
   start:function(){
    var that=this
    clearInterval(that.data.timer);
     wx.showModal({
        title:'提示',
        content:'开始游戏',
       showCancel:true,
       
        如何让用户点击取消按钮后,还能继续玩(已解决)
        success(res){
          // 刚开局点击取消后,什么也不做
          if(res.cancel ){
            if(!that.data.cancelButton){

            }else{
             that.data.timer = setInterval(that.counter,1000)
            }

            // 点击确定后,初始化界面,并回调时间函数
          }else{
            that.data.cancelButton = true
            that.init()
            // clearInterval(this.data.timer)
            that.data.timer = setInterval(that.counter,1000)
            that.data.clickButton = true
          }
        } 
    
     })
       
    
   },
    second:'',
    minute:'',
    hour:'',
   counter:function(){
     var second = this.data.second
     var minute = this.data.minute
     var hour = this.data.hour
     this.setData({
       second:second+1
     })
     if(second == 60){
       this.setData({
         second:0,
         minute:minute+1
       })
     }
     if(minute == 60){
       this.setData({
         minute:0,
         hour:hour+1
       })
     }
     // 下面三个全局变量用于保证时间格式
     this.second = second
     this.minute = minute
     this.hour = hour
     if(second < 10){
       this.second="0"+second
     }
     if(minute < 10){
       this.minute = "0"+minute
     }
     if(hour < 10){
       this.hour="0"+hour
     }
 
    
     this.setData({
    
       timeformat:this.hour+":"+this.minute+":"+this.second
     })
   },
   // 跳转到设置页面的函数
    setUp:function () {
      wx.navigateTo({
        url: '../index/setUp/setUpPage',
      })
      // 设置完以后应该重新开始游戏
      this.defaultRow = 10
      this.defaultColumn = 7
      this.defaultDilei = 10
      this.init()
    },
    // 设置默认数据,用户不设置也能玩
   defaultRow:10,
   defaultColumn:7,
   defaultDilei:10,
  //初始化函数
  init: function () {
    //初始化时间
    this.counter()

     // 下面代码用于获取全局变量数据(只能函数中用)
    var app = getApp()
    var setRow = app.globalData.row
    var setColumn = app.globalData.column
    var setDilei = app.globalData.dilei

    this.setData({
      hour:0,
      minute:0,
      second:0,
      timeformat:"00"+":"+"00"+":"+"00"
    })

    // 检查用户修改了哪方面数据
    if(typeof(setRow) != 'undefined'){
      this.defaultRow = setRow
    }
    if(typeof(setColumn) != 'undefined'){
      this.defaultColumn = setColumn
    }
    if(typeof(setDilei) != 'undefined'){
      this.defaultDilei = setDilei
    }

    //生成指定行和列的方块数组,并初始化
    var ds = new Array()
    for (var i = 0; i <this.defaultRow; i++) {
      ds[i] = new Array();
      for (var j = 0; j < this.defaultColumn; j++) {
        ds[i][j] = {
          id: "" + i + j, //方块id
          bgcolor: "yellow", //方块背景色
          ftcolor: "red", //方块文字颜色
          text: "", //方块显示的文本信息
          dilei: 0 //方块下是否有雷 0:无雷,1有雷
        }
      }
    }
    this.data.bts=ds;
    //随机产生地雷
    for (var v = 0; v < this.defaultDilei; v++) {
      var i = Math.floor(Math.random() * (this.defaultRow-1))
      var j = Math.floor(Math.random() * (this.defaultColumn-1))
      this.data.bts[i][j].dilei = 1
      this.data.bts[i][j].text = ""
      this.data.bts[i][j].ftcolor = "red"
    }
    this.setData({ bts: this.data.bts })
    this.data.clickButton = false
     clearInterval(this.data.timer)
  },
  onLoad: function () {
    this.counter()
    this.init() 
    
  },
  countDilei:function(i,j){
     var N=0
     if(i>0 && j>0) N=N+this.data.bts[i-1][j-1].dilei//左上 
     if(i>0) N=N+this.data.bts[i-1][j].dilei//上
     if(i>0 && j<this.defaultColumn-1) N=N+this.data.bts[i-1][j+1].dilei //右上
     if(j>0) N=N+this.data.bts[i][j-1].dilei//左
     if(j<this.defaultColumn-1) N=N+this.data.bts[i][j+1].dilei//右
     if(i<this.defaultRow-1 && j>0) N=N+this.data.bts[i+1][j-1].dilei
     if(i<this.defaultRow-1) N=N+this.data.bts[i+1][j].dilei
     if(i<this.defaultRow-1 && j<this.defaultColumn-1) N=N+this.data.bts[i+1][j+1].dilei
     return N;
  },
  aotoClick: function (i, j) {
    var n = this.countDilei(i, j)
    //无论周围是否有雷都首先将当前翻开,这样递归才可以作为条件判断
    this.data.bts[i][j].bgcolor = "white"
    this.data.bts[i][j].ftcolor = "blue"
    //再根据周围是否有雷决定是否递归
    if (n != 0) {
      this.data.bts[i][j].text = n
    }else{//三个条件:存在、未翻开、不是雷
      if (i > 0 && j > 0 && this.data.bts[i - 1][j - 1].bgcolor == "yellow" && this.data.bts[i - 1][j - 1].dilei != 1) this.aotoClick(i - 1, j - 1) //左上 
      if (i > 0 && this.data.bts[i - 1][j].bgcolor == "yellow" && this.data.bts[i - 1][j].dilei != 1) this.aotoClick(i - 1, j) //上
      if (i > 0 && j < this.defaultColumn-1 && this.data.bts[i - 1][j + 1].bgcolor == "yellow" && this.data.bts[i - 1][j + 1].dilei != 1) this.aotoClick(i - 1, j + 1) //右上
      if (j > 0 && this.data.bts[i][j - 1].bgcolor == "yellow" && this.data.bts[i][j - 1].dilei != 1) this.aotoClick(i, j - 1) //左
      if (j < this.defaultColumn-1 && this.data.bts[i][j + 1].bgcolor == "yellow" && this.data.bts[i][j + 1].dilei != 1) this.aotoClick(i, j + 1) //右
      if (i < this.defaultRow-1 && j > 0 && this.data.bts[i + 1][j - 1].bgcolor == "yellow" && this.data.bts[i + 1][j - 1].dilei != 1) this.aotoClick(i + 1, j - 1)
      if (i < this.defaultRow-1 && this.data.bts[i + 1][j].bgcolor == "yellow" && this.data.bts[i + 1][j].dilei != 1) this.aotoClick(i + 1, j)
      if (i <this.defaultRow-1 && j <this.defaultColumn-1 && this.data.bts[i + 1][j + 1].bgcolor == "yellow" && this.data.bts[i + 1][j + 1].dilei != 1) this.aotoClick(i + 1, j + 1)
    }
  }
  ,
  click: function (e) {
       //要求用户必须点击开始游戏 才能开始玩
    if(this.data.clickButton == false){
      wx.showModal({
        title:'提示',
        content:'请点击开始游戏,才能玩',
        
      })
      return
    }
    //找到点击位置
    var ds = e.target.id 
    var i = Number(ds.substr(0, 1))
    var j = Number(ds.substr(1, 2))
     
    // this.data.bts[i][j].bgcolor="white"
    // this.data.bts[i][j].text=""
    // // this.data.bts[i][j].ftcolor=""
    //如果点到地雷
    if (this.data.bts[i][j].dilei == 1) {
      this.data.bts[i][j].bgcolor="white"
      this.data.bts[i][j].text="*"
      this.data.bts[i][j].ftcolor="red"
      wx.showModal({
        title: '提示',
        content: '你点到地雷了,游戏结束!'+'\n'+'所用时间为:'+this.data.timeformat,

      })
    
        clearInterval(this.data.timer)
      this.init()

    }else{ //没点到地雷
      this.aotoClick(i,j)//开始递归当前的周围
      //每次点击后都检查是否胜利
      if(this.isVictory()==true){
        wx.showModal({
          title: '提示',
          content: '恭喜你翻开所有地雷!',
        })
        this.init()

      }
    }
    this.setData({ bts: this.data.bts })
   
  },
  isVictory:function(){
    var flag = true;
    for (var i = 0; i < this.defaultRow; i++) {
      for (var j = 0; j < this.defaultColumn; j++) { 
        if(this.data.bts[i][j].dilei==0 && this.data.bts[i][j].bgcolor=="yellow") 
        {
          flag=false
          break
        }
      }
    }
    return flag
  }
})

index.wxss


    .main{
      display: flex;
      flex-direction: column;
      border: 1px solid black;
    }

   .yy{
     display: flex;
     flex-direction: row;
   }
  .xx{
    border: 1px solid black;
    width: 100%;
    height: 60px;
    margin: 2px;
    text-align: center;
    line-height: 60px;
    font-size: 35px;
  }
   .time{
     display: flex;
     background: blueviolet;
     padding-left: 2vw;
     height: 7vh;
     line-height: 7vh;
   }
   .using-time{
     width: 150px;
     font-weight: 700;
   }
   .start-game{
     /* position: relative; */
     font-size: 15px;
     padding-left: 80px;
     font-weight: 700;
     color: rgb(63, 204, 34);
   }
   .set-up{
     padding-left: 85vw;
     margin-bottom: 2vh;
     height: 20px;
     
   }

 setUp目录下的代码文件

   setUp.wxml  (微信中所有页面代码它默认名叫 index.wxml,不用管它)

<!--index.wxml-->

<label class="title">你可以只设置一个数据,其他数据为系统默认数据</label>
<view class="firstNum">
    <!-- <text>请输入第一个运算数:</text> -->
    <label class="text" >请输入方块数的行数: </label>
    <input type="digit" bindinput="input1"     style=" border: 2rpx solid #ccc; width:150px;  margin-left: 5px; "/>
</view>
<view class="secondNum">
    <text class="text">请设置方块数的列数:</text>
    <input type="digit" bindinput="input2"     style=" border: 2rpx solid #ccc; width:150px;  margin-left: 5px;"/>
</view>
<view class="dilei">
    <text class="text">请设置地雷数:</text>
    <input type="digit" bindinput="input3"    style=" border: 2rpx solid #ccc; width:150px;  margin-left: 5px;"/>
</view>


<button bindtap="jump" class="jump">确定</button>

 setUp.js

// index.js

const app = getApp()

Page({
  // data: {
  //     num1: 0,
  //     num2: 0,
  //     result: 0
  // },
 
      input1(e) {
        // 下面代码将本页面数据传给全局变量
        // var app = getApp()
        app.globalData.row = e.detail.value
      // this.setData({
      //         num1: parseFloat(e.detail.value)
      //     })
          
  },
     input2(e) {
      app.globalData.column = e.detail.value
      // this.setData({
      //         num2: parseFloat(e.detail.value)
      //     })
  },
    input3(e){
      app.globalData.dilei = e.detail.value
    },

  jump:function(){
      wx.navigateTo({
        url: '../index'
      })
  }

})

setUp.wxss

/**index.wxss**/
.text{
  font-size: 13px;
  font-weight: 600;
}
.firstNum,
.secondNum {
  margin: 50rpx;
  display: flex;
  flex-direction: row;
  height:50px;
}
.dilei{
   display: flex;
   font-size: 13px;
   font-weight: 600;
   padding-left: 18vw;
}

.jump{
  background: rgb(204, 19, 221);
  margin-top: 50px;
}
.title{
  font-size: 13px;
  color:crimson;
  padding-left: 6vw;
}

由于涉及页面传递数据,所以还有一个app代码

app.js

// app.js
App({
  globalData:{
      row:0,
      column:0,
      dilei:0
  },
  onLaunch() {
    // 展示本地存储能力
    const logs = wx.getStorageSync('logs') || []
    logs.unshift(Date.now())
    wx.setStorageSync('logs', logs)

    // 登录
    wx.login({
      success: res => {
        // 发送 res.code 到后台换取 openId, sessionKey, unionId
      }
    })
  },
  globalData: {
    userInfo: null
  }
})

;