ホームページ > ウェブフロントエンド > jsチュートリアル > マインスイーパ アプレットを実装するための js サンプル コード

マインスイーパ アプレットを実装するための js サンプル コード

韦小宝
リリース: 2018-01-17 10:34:42
オリジナル
1623 人が閲覧しました

この記事では、主に js でマインスイーパ アプレットを実装するためのサンプル コードを紹介します。編集者がそれが非常に優れていると考えたので、参考として js ソース コードを共有します。 js に興味がある方は、ぜひエディターをフォローして見てください

私は JavaScript の初心者で、練習のためにマインスイーパー プログラムを書きました。

マインスイーパのルールと機能

マインスイーパは Windows 上のクリックツークリック ゲームです。その主なルールは

1 です。地雷である場合、地雷でない場合はゲームオーバーです。このグリッドには周囲の 8 つのグリッド内の地雷の数が表示されます。

2. マウスを右クリックして地雷の可能性をマークします。キャンセルするには、グリッドを再度右クリックする必要があります。
3. マウスの中ボタン (ホイール) を押すと、すぐに地雷をクリアできます (周囲の地雷の数がマークされていないグリッドと同じであれば、これらのグリッドも一緒に開きます)

主な機能は基本的に完全に機能しますWindows 7 マインスイーパの機能が刻まれています


マインスイーパ github アドレス: マインスイーパ github アドレス


マインスイーパ アルゴリズム

1 まず、一連の属性を含む

コンストラクターを定義しました:

  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();           //创建游戏函数
  };
ログイン後にコピー

2. ページ上にマインスイーパ インターフェイス関数 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();            //点击事件
    },
ログイン後にコピー

3. イベント関数をバインドします:


    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);
        }
      }
    },
ログイン後にコピー

4. クリックして関数を呼び出します:


    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();
        }
      }
    },
ログイン後にコピー

5. 以前の bray は、ページのときに buildTiles にありました。がロードされました () が、これにより、モーターの最初のグリッドが私のものである可能性が生じます (ゲームプレイは強力ではありません)。その後、最初のクリックが完了した後に私のものになるように変更されました (最初のクリックが完了していることを確認してください)。私のものではありません)。したがって、後続のイベントの後にトリガーされるchangeStyle関数に呼び出しを入れます:


    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()
    },
ログイン後にコピー

7.showAll関数: 関数はifです。周囲にグリッドが存在しないThunderは、周囲の8グリッドを自動的に開き、再帰的方法を使用して周囲8グリッドに地雷があるかどうかを判断します


    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]);
      }
    },
ログイン後にコピー

8.show_zj関数:主に中クリックボタンのクリックに使用されます。関数、show_zj1 はマウスボタンを押した後の表示効果、

show_zj2 関数は

    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");
            }
          }
        }
      }
    },
ログイン後にコピー

9 終了判定:

    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;
    },
ログイン後にコピー


10 終了後の表示関数:



    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;
    },
ログイン後にコピー

11 統計情報: 非常に完成度が高く、判定項目は Windows 7 マインスイーパ版と同じです


    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;
    },
ログイン後にコピー

マインスイーパの主な部分は次のとおりです。一部の小さな機能はここには書かれていません。完全なバージョンを見たい場合は、gitHub をご覧ください


以前、本を読んで勉強すると、学んだことを忘れてしまうように感じていました。公式は理解できましたが、その使い方がわかりませんでした。マインスイーパー ミニ プログラムを書いた後、多くのことを学んだように感じました

関連のおすすめ:


JavaScript 学習の最も完全なまとめ

非同期 JavaScript を体験するためのより良いソリューション

JavaScript での多重継承の例の詳細な説明

以上がマインスイーパ アプレットを実装するための js サンプル コードの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート