Maison > interface Web > js tutoriel > code js pour implémenter le dragueur de mines

code js pour implémenter le dragueur de mines

小云云
Libérer: 2018-01-30 13:26:52
original
2180 Les gens l'ont consulté

Cet article présente principalement l'exemple de code pour implémenter l'applet démineur dans js. L'éditeur pense que c'est plutôt bon, je vais donc le partager avec vous maintenant et le donner comme référence. Suivons l'éditeur pour y jeter un œil, j'espère que cela pourra aider tout le monde.

Je suis nouveau sur JavaScript et j'ai écrit un programme de dragueur de mines pour mettre en pratique mes compétences !

Règles et fonctions du démineur

Tout le monde doit être familier avec Démineur, c'est un petit jeu de déminage en un clic sous Windows. Les règles principales sont

1. Cliquez avec le bouton gauche pour afficher si la grille actuelle est une mine. Si c'est une mine, GameOver se produit. Si ce n'est pas une mine, la grille affichera le nombre de mines présentes. huit grilles environnantes.
2. Cliquez avec le bouton droit de la souris pour marquer les mines possibles. Après le marquage, vous devez à nouveau cliquer avec le bouton droit sur la grille pour annuler.
3. Appuyez sur le bouton central de la souris (molette) pour éliminer rapidement les mines (si le nombre de mines environnantes est égal aux grilles non marquées et non ouvertes, ces grilles seront ouvertes ensemble)

Le les fonctions principales reproduisent essentiellement complètement la fonction du dragueur de mines de Windows 7

Adresse github du dragueur de mines : Adresse github du dragueur de mines

Algorithme du dragueur de mines

1. J'ai d'abord défini un constructeur, qui est une série d'attributs :


  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();           //创建游戏函数
  };
Copier après la connexion

2. Créez sur la page la fonction d'interface du démineur 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();            //点击事件
    },
Copier après la connexion

3. Fonction de liaison d'événement :


    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);
        }
      }
    },
Copier après la connexion

4. fonction appelée en cliquant :


    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();
        }
      }
    },
Copier après la connexion

5. Mise en page : Ma mise en page précédente était lorsque la page était chargée dans buildTiles() Oui, mais cela mènera à la possibilité que la première grille de votre moteur soit la mienne (le gameplay n'est pas fort). Plus tard, elle a été modifiée pour la mienne une fois le premier clic terminé (assurez-vous que le premier clic n'est pas le mien), évitant ainsi le phénomène d'explosion directe. Mettez donc l'appel dans la fonction changeStyle déclenchée après l'événement suivant


    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()
    },
Copier après la connexion

6. Fonction pour stocker la grille environnante :


    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]);
      }
    },
Copier après la connexion

7.fonction showAll : s'il n'y a pas de mines autour de la grille, elle ouvrira automatiquement les 8 grilles environnantes, puis déterminera si la grille a du tonnerre. ou non, la méthode récursive est utilisée


    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");
            }
          }
        }
      }
    },
Copier après la connexion

8.fonction show_zj : principalement la fonction du bouton du milieu après avoir cliqué sur le bouton du milieu. show_zj1 voici l'effet d'affichage après avoir appuyé sur le bouton de la souris. La fonction
show_zj2 est


    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;
    },
Copier après la connexion

9. Terminer le jugement :


    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;
    },
Copier après la connexion

10. Fonction d'affichage une fois terminé :


    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;
    },
Copier après la connexion

11 Statistiques : toujours les les éléments de jugement plus complets sont les mêmes que ceux de la version Windows 7 Minesweeper. Les données sont stockées dans localStorage après la fin de chaque jeu


    //已玩游戏,已胜游戏,胜率,最多连胜,最多连败,当前连局;
    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);
      
      }
    },
Copier après la connexion

Ceux-ci. sont les principales parties de Minesweeper. Il y a aussi quelques petites fonctions qui n'ont pas été écrites. Pour voir la liste complète, vous pouvez voir gitHub

Recommandations associées :

Techniques de cinq. Points clés des mini-jeux WeChat

Exemple de mise en œuvre JQuery de la méthode de jeu Snake

Tutoriel de mise en œuvre du jeu JS Push Box

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Étiquettes associées:
source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal