掃雷小遊戲-網頁版

Yokeqi發表於2019-06-14

這兩天在惡補前端的相關知識,看到JQuery的動畫部分時,突然心血來潮想做一個掃雷的網頁版,於是花了一整天的時間完成了一個初始版本,權當對這幾天學習成果的一個回顧,若某處功能有更好實現方式歡迎留言一起討論。

先看看最後實現的效果:如何內嵌一個頁面?

 一、知識點介紹

1. Html + CSS + JQuery庫

  • 要建立介面UI,所以需要用到各類Html標籤還有CSS的佈局美化。
  • 要實現各類邏輯功能,所以需要用到JQuery的選擇器、事件等知識。

2. 掃雷遊戲的玩法

  • 翻開某個格子,如果是雷,那麼就會Boom,遊戲結束。
  • 如果是空白,則代表以這個格子為中心的九宮格範圍內沒有雷。
  • 如果是數字,則根據數字代表這個格子為中心的九宮格範圍記憶體在多少顆雷。
  • 正確標記出所有的雷,並翻開多餘的格子,則遊戲勝利。

二、關鍵程式碼說明

1. 建立資料地圖,接下來只需要根據資料地圖建立對應UI就可以了。

function createMap() {
    //初始化為0
    for (var i = 0; i < num; i++) {
        map[i] = new Array();
        mark[i] = new Array();
        for (var j = 0; j < num; j++) {
            map[i][j] = 0;
            mark[i][j] = 0;
        }
    }

    var count = 0;
    // 生成雷
    while (count < boomNum) {
        var row = Math.floor(Math.random() * (num - 1));
        var col = Math.floor(Math.random() * (num - 1));
        if (isMine(row, col)) {
            // 這個位置已經有雷,重新生成位置
            continue;
        }
        count++;
        map[row][col] = 100;

        // 周圍的雷數標記+1
        searchAround(row, col, function (posX, posY) {
            map[posX][posY]++;
        });
        //for (var i = 0; i < at.length; i++) {
        //    var posX = row + at[i][0];
        //    var posY = col + at[i][1];
        //    // 不要超出地圖範圍
        //    if (posX < 0 || posY < 0 || posX > map.length || posY > map[0].length)
        //        continue;

        //    map[posX][posY]++;
        //}
    }
}
View Code

2. 建立介面UI

function createUI() {
    // 生成介面
    for (var i = 0; i < num; i++) {
        for (var j = 0; j < num; j++) {
            var l = offsetX + i * boxSize;
            var t = offsetY + j * boxSize;
            // 建立容器Box
            var box = $("<div></div>").addClass("box").css({ "left": l + "px", "top": t + "px" }).attr({ "row": i, "col": j });
            // 建立遮罩層
            var cover = $("<div></div>").addClass("cover").width(boxSize - 1).height(boxSize - 1);// 遮罩層,這樣就直接看不到底下是不是雷
            // 建立實際內容
            var content = $("<div></div>").addClass("content").width(boxSize - 1).height(boxSize - 1).hide();// 內容,可能是空白,可能是個提示數字,也可能就是個雷

            if (map[i][j] >= 100) {
                // 如果是雷,則把格子資料替換成一張Gif圖。
                var boom = $("<img></img>").attr("src", "./imgs/boom.gif").width(40).height(40);
                content.css("margin", "0px").html(boom);
            } else if (map[i][j] > 0) {
                content.text(map[i][j]);
            }

            box.append(cover).append(content);
            $("#panel").append(box);
        }
    };
}
View Code

3. 註冊幾個核心事件

function registerEvents() {
    $(".box").hover(function () {
        var row = $(this).attr("row");
        var col = $(this).attr("col");
        if (mark[row][col] == 0)
            $(this).children(".cover").css("backgroundColor", "lightgray");
    });
    $(".box").mouseleave(function () {
        var row = $(this).attr("row");
        var col = $(this).attr("col");
        if (mark[row][col] == 0)
            $(this).children(".cover").css("backgroundColor", "black");
    });
    $(".box").dblclick(function () {
        // 挖格子,看運氣是不是雷
        sweeper($(this));
    });

    $(".box").click(function () {
        var row = $(this).attr("row");
        var col = $(this).attr("col");
        mark[row][col] = mark[row][col] == 1 ? 0 : 1; // 旗子標記

        var color = mark[row][col] == 1 ? "red" : "black";
        $(this).children(".cover").css("backgroundColor", color);

        valid(); // 驗證是否成功通關。
    });
}
View Code

4. 挖格子功能

function isMine(row, col) {
    return map[row][col] >= 100;
}

function sweeper(box) {
    var row = box.attr("row");
    var col = box.attr("col");
    if (isMine(row, col)) {
        $(".cover").fadeOut("slow").siblings(".content").fadeIn("slow");
        box.delay(1).queue(function () {
            $("#msg").text("Boom!!!遊戲結束.").show("slow");
        });

        return;
    }

    // 如果遇到空白,則自動挖開以此為中心的九宮格,並且遞迴搜尋。
    autoSweeper(row, col);

    valid();
}
View Code

5. 增加了一個簡單的深搜,挖到空白格子則自動挖出以此為中心的九宮格,並且遇到同樣空白格子會繼續挖。

function autoSweeper(row, col) {
    var cover = $(".box[row=" + row + "][col=" + col + "]").children(".cover");

    if (cover.is(":hidden"))
        return;

    cover.hide("fast").siblings(".content").show("fast", function () {
        if (map[row][col] != 0)
            return;

        // 如果挖到空白格子,則自動挖四周
        searchAround(row, col, autoSweeper);
    });
}

function searchAround(row, col, action) {
    for (var i = 0; i < at.length; i++) {
        var posX = parseInt(row) + at[i][0];
        var posY = parseInt(col) + at[i][1];
        // 不要超出地圖範圍
        if (posX < 0 || posY < 0 || posX >= map.length || posY >= map[0].length)
            continue;

        action(posX, posY);
    }
}
View Code

6. 簡單驗證下是否達成通關條件

function valid() {

    var count = boomNum;
    for (var i = 0; i < num; i++) {
        for (var j = 0; j < num; j++) {
            if (mark[i][j] == 1 && map[i][j] >= 100) {
                count--;
            }
        }
    }

    if (count == 0) {
        $(".cover").fadeOut("fast").siblings(".content").fadeIn("fast");
        $(".cover").delay(1).queue(function () {
            $("#msg").text("恭喜你!成功過關.").show("slow");
        });
    }
}
View Code

三、參考資料

相關文章