canvas + jquery 實現掃雷小遊戲

遊戲試玩git

前言github

這個小遊戲主要思路是canvas與數組的映射,每個小網格對應二維數組的一個元素,利用數組來存儲網格的信息,如 某網格是否有雷,周圍九宮格雷的個數,是否已經被打開canvas

這裏定義了三個數組數組

let gridStatus_arr = [];          //存儲格子身份狀態,狀態1爲雷
let mineNum_arr = [];            //存儲格子周圍八個格子雷的數量
let click_arr = [];           //存儲格子點擊狀態,點擊過的爲1
複製代碼
  1. 佈局

先添加三個難度的按鈕dom

<button class="type" data-row="9" data-col="9" data-mine="10">簡單</button>
<button class="type" data-row="14" data-col="14" data-mine="36">中級</button>
<button class="type" data-row="14" data-col="22" data-mine="56">高級</button>
複製代碼

點擊相應按鈕經過 js 獲取對應的 data 屬性, 而後動態的生成相應的方格, 而後動態計算包裹全部小方格的寬度和高度佈局

而後建立一個canvas元素this

<canvas id="canvas"></canvas>
複製代碼

canvas畫布的大小屬性width和height先不設置,後面經過js動態設置spa

  1. 按鈕點擊事件,並初始化畫布

點擊難度按鈕,動態初始化畫布code

//獲取canvas元素
    context = $("#canvas")[0].getContext("2d");
    
    $(".type").click(function(){
        row = $(this).data('row');
        col = $(this).data('col');
        mine = $(this).data('mine');
        init(mine);
    })

    //初始化
    function init(mine){
        createGrid();      //建立網格
        createMine(mine);     //隨機生成雷
        countArountMine();      //計算每一個格子周圍八個格子雷的數量
        createClickEvent();    //添加點擊事件
    }
複製代碼

3.canvas建立網格對象

利用canvas畫網格,先畫一個相應大小的矩形,而後在矩形內畫線造成網格

function createGrid(){
        //計算畫布寬高
        let width = GAID_WIDTH*col;
        let height = GAID_HEIGHT*row;

        //設置畫布寬高
        canvas.setAttribute("width",width)
        canvas.setAttribute("height",height)
        //描繪邊框
        context.beginPath();
        context.linewidth = 1; 
        context.rect(0,0,width,height);
        context.stroke();
        context.fillStyle = '#909090';
        context.fill();

        //準備畫橫線
        for(let row_i = 1; row_i<row; row_i++){
            var y = row_i*GAID_HEIGHT; 
            context.strokeStyle = 'white';            
            context.moveTo(0,y);  
            context.lineTo(width,y);
        }
        //準備畫豎線
        for(let col_i = 1; col_i<col; col_i++){
            var x = col_i*GAID_WIDTH;  
            context.strokeStyle = 'white';                        
            context.moveTo(x,0);  
            context.lineTo(x,height);
        }
        //完成描繪  
        context.stroke();
    }
複製代碼
  1. 隨機生成雷

添加雷,改變格子身份狀態 ,1表明雷區

這裏是利用二維數組和網格的映射來實現的

function createMine(mine){
        $('#mine').text(mine);
        //將數組變爲二維
        for(let i=0; i<row; i++){
            gridStatus_arr[i] = [];
            mineNum_arr[i] = [];
            click_arr[i] = [];
        }
        //初始化二維數組
        for(let i=0; i<row; i++){
            for(let j=0; j<col; j++){
                gridStatus_arr[i][j] = 0;
                mineNum_arr[i][j] = 0;
                click_arr[i][j] = 0;
            }
        }
        //添加雷,改變格子身份狀態
        while(mine!=0){
            let mine_row = Math.floor(Math.random() * row);
            let mine_col = Math.floor(Math.random() * col);
            mine--;
            //預防生成位置相同
            if(gridStatus_arr[mine_row][mine_col] == 1){
                mine++;
                continue;
            }
            gridStatus_arr[mine_row][mine_col] = 1;
        }
    }
複製代碼

5.計算每一個格子周圍八個格子雷的數量

利用對象來取當前格子周圍九宮格的範圍,遍歷查看對應數組的身份狀態

function countArountMine(){
        for(let i=0; i<row; i++){
            for(let j=0; j<col; j++){
                let around = aroundGrid(i,j);
                let nx = around.nx,
                    sx = around.sx,
                    wy = around.wy,
                    ey = around.ey;
                
                let mineNum = 0; 

                for(let x=nx; x<=sx; x++){
                    for(let y=wy; y<ey; y++){
                        if(gridStatus_arr[x][y]==1){
                            mineNum++;
                        }
                    }
                }
                mineNum_arr[i][j] = mineNum;                            
            }
        }
    }
複製代碼
  1. 添加點擊事件

要先去掉默認的contextmenu事件,不然會和默認右鍵事件同時出現。

document.oncontextmenu = function (e) {
        e.preventDefault();
};
複製代碼

再添加鼠標點擊事件,e.which = 1爲鼠標左鍵 ,e.which = 3爲鼠標右鍵

function createClickEvent(){     
        $("#canvas").off();
        $("#canvas").mousedown(function(e){
            //由於canvas的X,Y座標和數組的行列相反,這裏直接轉換了一下
            let x = Math.floor(e.offsetY / GAID_HEIGHT);
            let y = Math.floor(e.offsetX / GAID_WIDTH);

            if(e.which == 1){
                judgeGridStatus(x,y);
            }else if(e.which == 3){
                signMine(x,y);
            }
        })
    }
複製代碼
  1. 判斷輸贏

對比身份狀態是否爲1 來判斷是否點擊到雷。

經過 已打開的格子個數 和 row*col - mine 對比判斷是否掃雷成功

這裏就不貼代碼了,詳細可參考個人GitHub倉庫

最後

在canvas的用法上可能有一些不規範,由於花的時間比較短, 可能裏面還存在一些問題,還請大佬們多多包涵,也歡迎大佬們來指正。本小白感激涕零。

項目GitHub地址

相關文章
相關標籤/搜索