Home > Web Front-end > JS Tutorial > body text

js code to implement minesweeper

小云云
Release: 2018-01-30 13:26:52
Original
2129 people have browsed it

This article mainly introduces the sample code for implementing the minesweeper applet in js. The editor thinks it is quite good, so I will share it with you now and give it as a reference. Let’s follow the editor to take a look, I hope it can help everyone.

I am new to JavaScript and wrote a minesweeper program to practice my skills!

Minesweeper Rules and Functions

Minesweeper must be familiar to everyone. It is a click-to-click minesweeper game on Windows. Its main rules are

1. Left-click to display whether the current grid is a mine. If it is a mine, it will be GameOver. If it is not a mine, the grid will display the number of mines in the eight surrounding grids.
2. Right-click the mouse to mark possible mines. After marking, you need to right-click the grid again to cancel. The left-click has no effect.
3. After pressing the middle mouse button (scroll wheel), you can quickly clear mines (if the number of surrounding mines is equal to the unmarked and unopened grids, these grids will be opened together)

The main function basically completely replicates the function of Windows 7 Minesweeper

Minesweeper github address: Minesweeper github address

Minesweeper algorithm

1. First, I defined a constructor, which contains a series of attributes:


  var mineCraft = function(num1,num2,mine_num,obj,type){
    this.num1 = num1;            //整个扫雷的行数
    this.num2 = num2;            //整个扫雷的列数 
    this.mine_num = mine_num;        //雷的个数
    this.tiles = [];             //数组里面存放的是每个小格子
    this.obj = obj;             //扫雷放置的对象
    this.flag = true;            
    this.arr = [];
    this.arr_2 = [];
    this.time_dsq = null;     
    this.time_dc ='';
    this.time_arr = [[],[],[]];       //时间统计信息
    this.details = [[],[],[]];       // 游戏统计详情
    this.type = type;           //游戏类型:初级/中级/高级/自定义
    this.buildTiles();           //创建游戏函数
  };
Copy after login

2. Create a minesweeper on the page Interface function buildTiles


    buildTiles:function(){
      this.obj.style.width = 51*this.num1+'px'; //在传进来的对象上画整体格子,每个小格子51px大小,总大小就为个数*单个大小
      this.obj.style.height = 51*this.num2+'px';
      var indexOfp = 0;           
      for(var i = 0;i<this.num2;i++){
        for(var j = 0;j<this.num1;j++){
          var tile = document.createElement(&#39;p&#39;);
          tile.className = &#39;tile&#39;;     //定义小格子class
          tile.index = indexOfp;     //为每个小格子添加索引
          this.tiles[indexOfp] = tile;  //将小格子存入数组中
          indexOfp++;
          this.obj.appendChild(tile);    //将小格子插入到整个扫雷界面中 
        }
      }
      this.obj.oncontextmenu = function(){  //取消浏览器的默认右键菜单事件
        return false;
      }
      this.event();            //点击事件
    },
Copy after login

3. Bind event function:


    event : function(){
      var _this = this;
      this.obj.onmouseover = function(e){    //鼠标悬停事件---
        if(e.target.className == &#39;tile&#39;){
          e.target.className = &#39;tile current&#39;;
        }
      }
      this.obj.onmouseout = function(e){    //鼠标移出事件--
        if(e.target.className == &#39;tile current&#39;){
          e.target.className = &#39;tile&#39;;
        }
      }
      this.obj.onmousedown = function(e){    //鼠标按下事件
        var index = e.target.index;
        if(e.button == 1){          //e.button属性 左键0/中键1/右键2
          event.preventDefault();    //取消默认
        }
        _this.changeStyle(e.button,e.target,index);
      }
      this.obj.onmouseup = function(e){   //鼠标弹起事件
        if(e.button == 1){
          _this.changeStyle(3,e.target);
        }
      }
    },
Copy after login

4. Click Called function:


    changeStyle:function(num1,obj,num_index){     
      if(num1 == 0){         //是左键的话
        if(this.flag){       //this.flag 是之前定义的用于判断是否为第一次点击
          this.store(num_index);     //store函数,存放被点击的格子周围的8个格子
          this.setMineCraft(this.mine_num,this.arr,num_index); //如果是第一次点击 即调用布雷函数 更改flag状态
          this.flag = false;
          this.detail_statistics(0,false);   //开始信息统计函数
        }        
        if(obj.className != &#39;tile&#39;&&obj.className !=&#39;tile current&#39;){//如果不是第一次点击,被点击的格子不是未点击状态,无效
          return false;
        }
        if(obj.getAttribute(&#39;val&#39;) == 0){  //如果不是雷。改为翻开状态
          obj.className = "showed";    
          obj.innerHTML = obj.getAttribute(&#39;value&#39;) == 0?&#39;&#39;:obj.getAttribute(&#39;value&#39;);          //显示周围雷数
          this.showAll(obj.index);   //递归函数判断周围格子的情况,就是扫雷游戏上一点开会出现一片的那种
        }
        if(this.over(obj)){       //判断游戏是否结束
          this.last();     
        }
      }
      if(num1 == 2){            //右键标记事件
        if(obj.className == &#39;biaoji&#39;){
          obj.className = &#39;tile&#39;;
        }else if(obj.className !=&#39;biaoji&#39;&&obj.className != &#39;showed&#39;){
          obj.className = &#39;biaoji&#39;;
        }
      }
      if(num1 == 1){           // 中键事件
        if(obj.className =="showed"){
          this.show_zj1(obj.index);
        }
      }
      if(num1 == 3){          //鼠标弹起事件
        
        if (obj.className == "showed") {
          var flag1 = this.show_zj2(obj.index,0);
        }else{
          this.show_zj2(obj.index,1)
          return false;
        }

        if(flag1&&this.over()){     //弹起判断是否结束
          this.last();
        }
      }
    },
Copy after login

5. Braking: My previous bracing was done when the page was loaded in buildTiles(), but this would lead to possible The first grid of your motor is mine (the game is not very good). It was later modified to mine after the first click is completed (make sure the first click is not mine) to avoid the phenomenon of being blown up directly. So put the call in In the changeStyle function triggered after the subsequent event


    setMineCraft:function(num,arr_first,num_first){ //雷的个数、最开始被点击的格子周围的八个、被点击的那个格子
      var arr_index = [];          
      for(var i = 0;i<arr_first.length;i++){
        arr_index.push(arr_first[i].index);
      }
      var length = this.tiles.length;
      for (var i = 0; i < length; i++) {
        this.tiles[i].setAttribute("val", 0);
      }
      for (var i = 0; i < num; i++) {       
        var index_Mine = Math.floor(Math.random() * this.tiles.length);
        if(index_Mine == num_first||arr_index.lastIndexOf(index_Mine)>-1){//如果是属于第一次点击的周围的直接跳过在该位置布雷
          num++;
          continue;
        }
        
        if (this.tiles[index_Mine].getAttribute("val") == 0) {
          this.tiles[index_Mine].setAttribute("val", 1);
        }else {
          num++;
        }
      }
      this.showValue();
      this.event()
    },
Copy after login

6. Function to store the surrounding grid:


    store : function(num) {  //传入格子的index.
      var tiles_2d = [];
      var indexs = 0;
      for(var i = 0;i<this.num2;i++){
        tiles_2d.push([]);
        for(var j = 0;j<this.num1;j++){
          tiles_2d[i].push(this.tiles[indexs]);
          indexs++;
        } 
      }
      var j = num % this.num1;
      var i = (num - j) / this.num1;
      this.arr = [];
        //左上
      if (i - 1 >= 0 && j - 1 >= 0) {
        this.arr.push(tiles_2d[i - 1][j - 1]);
      }
        //正上
      if (i - 1 >= 0) {
        this.arr.push(tiles_2d[i - 1][j]);
      }
        //右上
      if (i - 1 >= 0 && j + 1 <= this.num1-1) {
        this.arr.push(tiles_2d[i - 1][j + 1]);
      }
        //左边
      if (j - 1 >= 0) {
        this.arr.push(tiles_2d[i][j - 1]);
      }
        //右边
      if (j + 1 <= this.num1-1) {
        this.arr.push(tiles_2d[i][j + 1]);
      }
        //左下
      if (i + 1 <= this.num2-1 && j - 1 >= 0) {
        this.arr.push(tiles_2d[i + 1][j - 1]);
      }
        //正下
      if (i + 1 <= this.num2-1) {
        this.arr.push(tiles_2d[i + 1][j]);
      }
        //右下
      if (i + 1 <= this.num2-1 && j + 1 <= this.num1-1) {
        this.arr.push(tiles_2d[i + 1][j + 1]);
      }
    },
Copy after login

7.showAll function: if there are no mines around the grid, it will automatically open the surrounding 8 grids, and then determine whether there are mines in the 8 surrounding grids, using a recursive method


##

    showAll:function(num){
      if (this.tiles[num].className == "showed" && this.tiles[num].getAttribute("value") == 0){
        this.store(this.tiles[num].index);
        var arr2 = new Array();
        arr2 = this.arr;
        for (var i = 0; i < arr2.length; i++) {
          if (arr2[i].className != "showed"&&arr2[i].className !=&#39;biaoji&#39;) {
            if (arr2[i].getAttribute("value") == 0) {
              arr2[i].className = "showed";
              this.showAll(arr2[i].index);
            } else {
              arr2[i].className = "showed";
              arr2[i].innerHTML = arr2[i].getAttribute("value");
            }
          }
        }
      }
    },
Copy after login

8.show_zj function: mainly the function after the middle button is clicked. The show_zj1 here is the display effect after the mouse button is pressed. # The ##show_zj2 function is



##
    show_zj1:function(num){
      this.store(this.tiles[num].index);
      for (var i = 0; i < this.arr.length; i++) {
        if (this.arr[i].className == "tile") {
          this.arr_2.push(this.arr[i]);
          this.arr[i].className = "showed";
          // this.arr[i].className = "test";
        }
      }
    },
    show_zj2:function(num,zt){
      
      var count = 0;
      this.store(this.tiles[num].index);      
      
      for(var i = 0,len = this.arr_2.length;i<len;i++){
        this.arr_2[i].className = &#39;tile&#39;;     //按下效果恢复原状
      }

      this.arr_2.length = 0;
      for(var i = 0;i<this.arr.length;i++){
        this.arr[i].className == &#39;biaoji&#39;&&count++;
      }
      if(zt == 1){
        return false;
      }
      var numofmines = this.tiles[num].getAttribute("value");
      if(numofmines == count){               //如果周围雷数和周围被标记数相等就翻开周围的格子
          var arr = new Array(this.arr.length);
          for(var i = 0;i<this.arr.length;i++){
            arr[i] = this.arr[i];
          }
          for (var i = 0,length = arr.length; i < length; i++) { 
            if (arr[i].className == "tile" && arr[i].getAttribute("val") != 1) {//如果周围格子无雷则继续。
              arr[i].className = "showed";
              arr[i].innerHTML = arr[i].getAttribute("value") == 0?"":arr[i].getAttribute("value");
              this.showAll(arr[i].index);
            } else if (arr[i].className == "tile" && arr[i].getAttribute("val") == 1) {  //如果周围格子有雷,游戏结束
              this.over(arr[i]);
              this.last();
              return false;
            }
          }
      }
      return true;
    },
Copy after login

9. End judgment:


    over:function(obj){
      var flag = false;
      var showed = document.getElementsByClassName(&#39;showed&#39;);  
      var num = this.tiles.length - this.mine_num;     
      if(showed.length == num){           //如果被排出来的格子数等于总格子数-雷数,这游戏成功结束  
        this.detail_statistics(1,true);      //游戏统计 ,true代表胜,false,代表失败
        alert(&#39;恭喜你获得成功&#39;);
        flag = true;
      }else if(obj&&obj.getAttribute(&#39;val&#39;) == 1){   //如果被点击的是雷,则炸死
        this.detail_statistics(1,false);
        alert(&#39;被炸死!&#39;);
        flag = true;

      }
      return flag;
    },
Copy after login

10. Display function after completion:


    last:function(){   
      var len = this.tiles.length;
      for(var i = 0;i<len;i++){
        this.tiles[i].className = this.tiles[i].getAttribute(&#39;val&#39;) == 1?&#39;boom&#39;:&#39;showed&#39;;
        if(this.tiles[i].className != &#39;boom&#39;){  //
          this.tiles[i].innerHTML = this.tiles[i].getAttribute(&#39;value&#39;) == 0?&#39;&#39;:this.tiles[i].getAttribute(&#39;value&#39;);
        }
      }
      this.obj.onclick = null;
      this.obj.oncontextmenu = null;
    },
Copy after login

11 Statistical information: It is still relatively complete and is the same as the judgment items of Windows 7 Minesweeper version. It is used every time it ends. After the game, the data is stored in localStorage.


    //已玩游戏,已胜游戏,胜率,最多连胜,最多连败,当前连局;
    detail_statistics:function(num,zt){
      var time_pay = 1;
      var _this = this;
      if(num == 0){
        this.time_dsq = setInterval(function(){
          $(&#39;#time_need&#39;).text(time_pay);
          _this.time_dc =time_pay;
          time_pay++;
         },1000);
    
      }
      else if(num == 1){
        clearInterval(this.time_dsq);
        if(this.type == 4){return false;}
        if(localStorage.details == undefined){          
          localStorage.details = JSON.stringify([[0,0,0,0,0,0],[0,0,0,0,0,0],[0,0,0,0,0,0]]); //这里存放的就是上面注释中的六项数据
        }
        if(JSON.parse(localStorage.details) instanceof Array){
          this.details = JSON.parse(localStorage.details);       
        }
        this.details[this.type][0] += 1;
        if(zt == false){
          if(this.details[this.type][5]>=0){
            this.details[this.type][5] = -1;
          }else{
            this.details[this.type][5] -= 1;
          }  
          if(this.details[this.type][5]<this.details[this.type][4]){
            this.details[this.type][4] = this.details[this.type][5];
          }
          this.details[this.type][2] = this.toPercent(this.details[this.type][2]/this.details[this.type][0]);        
          localStorage.details = JSON.stringify(this.details);
          return false;
        }

        if(this.details[this.type][5]>=0){
          this.details[this.type][5] += 1;
        }else{
          this.details[this.type][5] = 1;
        }
        if(this.details[this.type][5]>this.details[this.type][3]){
          this.details[this.type][3] = this.details[this.type][5];
        }
        this.details[this.type][3] += 1;
        this.details[this.type][2] = this.toPercent(this.details[this.type][4]/this.details[this.type][0]);
        localStorage.details = JSON.stringify(this.details);
        
        var time1 = new Date();        
        var time_str = time1.getFullYear()+&#39;/&#39;+time1.getMonth()+&#39;/&#39;+time1.getDate()+&#39; &#39;+time1.getHours()+&#39;:&#39;+time1.getMinutes();
        if(localStorage.time == undefined){
          localStorage.time = JSON.stringify([[],[],[]]);
        }
        if(JSON.parse(localStorage.time) instanceof Array){
          this.time_arr = JSON.parse(localStorage.time);
        }

        this.time_arr[this.type].push([this.time_dc,time_str]);
        this.time_arr[this.type].sort(function(a,b){
          return a[0]-b[0];
        });
        if(this.time_arr[this.type].length>5){
          this.time_arr[this.type].pop();
        }
        localStorage.time = JSON.stringify(this.time_arr);
      
      }
    },
Copy after login

These are the main parts of Minesweeper. There are also some small functions that are not written here. Please read the complete You can see gitHub

Related recommendations:

Technical Points of Five WeChat Mini Games

JQuery Implementation of Snake Mini Game Method Example

js push box mini game implementation tutorial

The above is the detailed content of js code to implement minesweeper. For more information, please follow other related articles on the PHP Chinese website!

Related labels:
source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template