vue+canvasパズルを実現します。


vue+canvasを使ってパズルのミニゲームを実現します。参考にしてください。具体的な内容は以下の通りです。
考え方のステップ
  • パズルの盛り合わせと原図を参照してください。
  • 元の図の切断およびランダム順序
  • は、W/A/D/Sまたは上下左右を介して移動する
  • 難易度の自主選択
  • パズルが完成したかどうかの判定

  • JS実現部分
    データ解析
  • row:パズルの行数。パズルの総列数。パズルの難易度を設定するためのものであり、各パズルのピースの幅の高い設定ルールでもあります。
  • pic[{x,y,row,column,index]]:ジグソーパズルのセットは、その中の要素が小さいジグソーパズルのデータ構造である。x、y:ジグソーパズルのcanvasでの描画ルールは、初期化後は変更されません。row、column:原図をカットして描くルール。index:ジグソーパズルが完了したかどうかを判定するためのルールの一つで、空白のブロックのindex=-1)
  • が描画されます。
  • num:ランダム配列の回数。
  • sign:パズルのセットpic内の空白のブロックのインデックス。数字の種類は、空白のブロックを特定し、空白のブロックの移動に従って変化することで、移動するルールの一つである。デフォルトは:15)
  • isWin:パズルが完成したかどうかを判断するための条件です。ブールタイプ、デフォルトはfalseです。
  • ステップ:移動の有効ステップ数を表します。数字の種類、デフォルトは0で、再びゲームをしておよびゲームを完成して清零になります)
  • マスターショー:ゲームの判定条件を編集します。ブールタイプは、編集ゲームのダイアログを表示して非表示にします。デフォルトはfalseです。
  • 方法の分析
    パズルセットpicの初期化とランダム配列
    
    randomHandler() {
     // pic    
     for(let i=0;i<this.row*this.column;i++) {
     //              
     let row = parseInt(i/this.row);
     let column = i - row*this.column;
     //   canvas        ,        
     let x = parseInt(i/this.row);
     let y = i - x*this.column;
     this.pic[i] = {...this.pic[i],x:x,y:y,row:row,column:column,index:i};
     //             ,index = -1
     if(i == (this.row*this.column-1)) {
      this.pic[i] = {...this.pic[i],row:row,column:column,index:-1};
     }
     }
     //      pic  
     for(let i=0;i<this.num;i++) {
     let ran1,ran2,temp={};
     //     0-14
     ran1 = parseInt((this.row*this.column-1)*Math.random())
     ran2 = parseInt((this.row*this.column-1)*Math.random())
     temp.row = this.pic[ran1].row
     temp.column = this.pic[ran1].column
     this.pic[ran1] = {...this.pic[ran1],row:this.pic[ran2].row,column:this.pic[ran2].column}
     this.pic[ran2] = {...this.pic[ran2],...temp}
     }
    }
    ジグソーパズルの描画(ランダムpicのセットで描画)
    
    drawHandler() {
     //    canvas DOM  
     let canvas = this.$refs.can;
     let ctx = canvas.getContext('2d');
     canvas.width = 400;
     canvas.height = 400;
     ctx.clearRect(0,0,400,400);
     //         ,  canvas        row  column     
     //               
     let width = canvas.width/this.column;
     let height = canvas.width/this.row;
     //      Image         ,       DOM   , onload     ,      
     let img = new Image();
     img.src = require('../../public/image/test.png');
     img.onload = () => {
     for(let i=0;i<this.row*this.column;i++) {
      //    canvas         
      let dx = this.pic[i].y * width;
      let dy = this.pic[i].x * height;
      //              
      let cx = this.pic[i].column * width;
      let cy = this.pic[i].row * height;
      //   :img  ,        ,     ,        ,     
      ctx.drawImage(img,cx,cy,width,height,dx,dy,width,height);
      if(this.pic[i].index == -1) {
      this.sign = i;
      ctx.clearRect(dx,dy,width,height);
      }
     }
     }
    }
    その中にはImageコンストラクタを通じて動的に作成しなければならない。
    パズルの移動
    
    //   mounted            
    mounted() {
     this.newGame();
     document.onkeydown = (event) => {
     let key = event.keyCode;
     if(key==38 || key==87) this.moveHandler('up');
     else if (key==40 || key==83 ) this.moveHandler('down');
     else if (key==37 || key==65 ) this.moveHandler('left');
     else if (key==39 || key==68 ) this.moveHandler('right');
     }
     }
    methods: {
     moveHandler(dir) {
     // re:                  
     let re,temp = {};
     if(dir == 'up' && this.pic[this.sign].x>0) {
     //       row column            
     //              ,   row、column、index
     //     this.sign(         :  15)
     re = (this.pic[this.sign].x-1) * this.row + this.pic[this.sign].y;
     temp.row = this.pic[re].row;
     temp.column = this.pic[re].column;
     temp.index = this.pic[re].index;
     this.pic[re] = {...this.pic[re],row:this.pic[this.sign].row,column:this.pic[this.sign].column,index:this.pic[this.sign].index};
     this.pic[this.sign] = {...this.pic[this.sign],...temp};
     this.step = this.step + 1;
     }
     else if(dir == 'down' && this.pic[this.sign].x<this.row-1) {
     re = (this.pic[this.sign].x+1) * this.row + this.pic[this.sign].y;
     temp.row = this.pic[re].row;
     temp.column = this.pic[re].column;
     temp.index = this.pic[re].index;
     this.pic[re] = {...this.pic[re],row:this.pic[this.sign].row,column:this.pic[this.sign].column,index:this.pic[this.sign].index};
     this.pic[this.sign] = {...this.pic[this.sign],...temp};
     this.step = this.step + 1;
     }
     else if(dir == 'left' && this.pic[this.sign].y>0) {
     re = (this.pic[this.sign].x) * this.row + this.pic[this.sign].y-1;
     temp.row = this.pic[re].row;
     temp.column = this.pic[re].column;
     temp.index = this.pic[re].index;
     this.pic[re] = {...this.pic[re],row:this.pic[this.sign].row,column:this.pic[this.sign].column,index:this.pic[this.sign].index};
     this.pic[this.sign] = {...this.pic[this.sign],...temp};
     this.step = this.step + 1;
     }
     else if(dir == 'right' && this.pic[this.sign].y<this.column-1) {
     re = (this.pic[this.sign].x) * this.row + this.pic[this.sign].y+1;
     temp.row = this.pic[re].row;
     temp.column = this.pic[re].column;
     temp.index = this.pic[re].index;
     this.pic[re] = {...this.pic[re],row:this.pic[this.sign].row,column:this.pic[this.sign].column,index:this.pic[this.sign].index};
     this.pic[this.sign] = {...this.pic[this.sign],...temp};
     this.step = this.step + 1;
     }
     //       ,                   
     this.drawHandler();
     }
    }
    パズルを完成させる判定
    
    isWinHandler() {
     //          x、y row、column      ,     index   
     for(let i=0;i<this.row*this.column;i++) {
     if(this.pic[i].x == this.pic[i].row && this.pic[i].y == this.pic[i].column) {
      //              
      this.isWin = true;
      this.step = 0;
     }
     }
    }
    ゲームをやり直す
    
    newGame() {
     //   mounted     
     //       ,    ,      ,      
     this.isWin = false;
     this.step = 0;
     this.randomHandler();
     this.drawHandler();
     }
    JS総合
    
    <script>
    export default {
     data() {
     return {
     // row:      ,column:      
     row:2,
     column:2,
     //        
     num:100,
     // pic:        ;
     //   :index:        
     // row/column:           
     // x/y: canvas      (    )
     pic:[{x:0,y:0,row:0,column:0,index:0}],
     sign:15,
     isWin: false,
     step:0,
     maskShow:false
     }
     },
     mounted() {            },
     methods: {
     //         
     isWinHandler() { ... },
     //        
     moveHandler(dir) { ... },
     //     
     drawHandler() { ... },
     //       
     randomHandler() { ... },
     newGame() { ... }
    }
    </script>
    HTML部分
    
    <template>
     <div class="index">
     <div class="contain">
     <canvas class="can" ref="can"></canvas>
     <!--           -->
     <div v-if="isWin" class="win">    !</div>
     <div class="btns">
     <span @click="newGame">    </span>
     <span @click="maskShow = true">    </span>
     <span @click="isWinHandler">  </span>
     <span>{{step}}</span>
     </div>
     <!--            -->
     <div v-show="maskShow" class="mask">
      :<input type="text" v-model="row" placeholder="     ">
      :<input type="text" v-model="column" placeholder="     ">
     <button @click="maskShow = false">  </button>
     </div>
     </div>
     <img ref="img" class="img" src="../../public/image/test.png" alt="error">
     </div>
    </template>
    CSS部分
    
    <style scoped>
    /*        */
    .mask {
     width: 200px;
     height: 200px;
     background-color: rosybrown;
     position: absolute;
     left: 510px;
     top: 0;
    }
    /*      */
    .btns > span {
     display: inline-block;
     width: 80px;
     font-size: 12px;
     height: 24px;
     text-align: center;
     line-height: 24px;
     margin-bottom: 5px;
     background-color: thistle;
     cursor: pointer;
    }
    /*       */
    .btns {
     width: 80px;
     height: 400px;
     border: 1px solid tan;
     border-radius: 5px;
     background-origin: border-box;
     padding: 5px;
     position: absolute;
     left: 412px;
     top: 0;
    }
    /*         */
    .win {
     width: 402px;
     height: 402px;
     line-height: 402px;
     text-align: center;
     font: 24px;
     opacity: 0.5;
     background-color: paleturquoise;
     position: absolute;
     top: 0;
     left: 0;
    }
    .img {
     display: inline-block;
    }
    /* canvas */
    .can {
     border: 1px solid teal;
    }
    /* canvas   */
    .contain {
     position: relative;
    }
    </style>
    最終の完成結果図

    コードアドレス:パズルゲーム
    以上が本文の全部です。皆さんの勉強に役に立つように、私たちを応援してください。