累了休息一會兒吧——分享一個JavaScript版掃雷游戲


  周末閑來無事寫了一個JavaScript版掃雷游戲,現在把源代碼分享出來,共同學習。

  掃雷游戲的原理大家可以參考這篇文章:http://www.cnblogs.com/goodwin/archive/2010/03/22/1691871.html

  JavaScript代碼:

(function () {
    var FLM = function (id,rowCount,colCount, minLandMineCount, maxLandMineCount) {
        if (!(this instanceof FLM))
            return new FLM(id, rowCount, colCount, minLandMineCount, maxLandMineCount);
        this.doc = document;
        this.table = this.doc.getElementById(id);
        this.cells = this.table.getElementsByTagName("td");//小格子
        this.rowCount = rowCount || 10;//格子行數
        this.colCount = colCount || 10;//格子列數
        this.landMineCount = 0;//地雷個數
        this.markLandMineCount = 0;//標記的地雷個數
        this.minLandMineCount = minLandMineCount || 10;//地雷最少個數
        this.maxLandMineCount = maxLandMineCount || 20;//地雷最多個數
        this.arrs = [];//格子對應的數組
        this.beginTime = null;//游戲開始時間
        this.endTime = null;//游戲結束時間
        this.currentSetpCount = 0;//當前走的步數
        this.endCallBack = null;//游戲結束時的回調函數
        this.landMineCallBack = null;//標記為地雷時更新剩余地雷個數的回調函數
        this.doc.oncontextmenu = function () {//禁用右鍵菜單
            return false;
        };
        this.drawMap();
    };

    FLM.prototype = {
        //獲取元素
        $: function (id) {
            return this.doc.getElementById(id);
        },
        //畫地圖
        drawMap: function () {
            var tds = [];
            for (var i = 0; i < this.rowCount; i++) {
                tds.push("<tr>");
                for (var j = 0; j < this.colCount; j++) {
                    tds.push("<td id='m" + i + "" + j + "'></td>");
                }
                tds.push("</td>");
            }
            this.table.innerHTML = tds.join("");
        },
        //初始化,一是設置數組默認值為0,二是確定地雷個數
        init: function () {
            for (var i = 0; i < this.rowCount; i++) {
                this.arrs[i] = [];
                for (var j = 0; j < this.colCount; j++) {
                    this.arrs[i][j] = 0;
                }
            }
            this.landMineCount = this.selectFrom(this.minLandMineCount, this.maxLandMineCount);
        },
        //把是地雷的數組項的值設置為9
        landMine: function () {
            var allCount = this.rowCount * this.colCount - 1,
                tempArr = {};
            for (var i = 0; i < this.landMineCount; i++) {
                var randomNum = this.selectFrom(0, allCount),
                    rowCol = this.getRowCol(randomNum);
                if (randomNum in tempArr) {
                    i--;
                    continue;
                }
                this.arrs[rowCol.row][rowCol.col] = 9;
                tempArr[randomNum] = randomNum;
            }
        },
        //計算其他格子中的數字
        calculateNoLandMineCount: function () {
            for (var i = 0; i < this.rowCount; i++) {
                for (var j = 0; j < this.colCount; j++) {
                    if (this.arrs[i][j] == 9)
                        continue;
                    if (i > 0 && j > 0) {
                        if (this.arrs[i - 1][j - 1] == 9)
                            this.arrs[i][j]++;
                    }
                    if (i > 0) {
                        if (this.arrs[i - 1][j] == 9)
                            this.arrs[i][j]++;
                    }
                    if (i > 0 && j < this.colCount - 1) {
                        if (this.arrs[i - 1][j + 1] == 9)
                            this.arrs[i][j]++;
                    }
                    if (j > 0) {
                        if (this.arrs[i][j - 1] == 9)
                            this.arrs[i][j]++;
                    }
                    if (j < this.colCount - 1) {
                        if (this.arrs[i][j + 1] == 9)
                            this.arrs[i][j]++;
                    }
                    if (i < this.rowCount - 1 && j > 0) {
                        if (this.arrs[i + 1][j - 1] == 9)
                            this.arrs[i][j]++;
                    }
                    if (i < this.rowCount - 1) {
                        if (this.arrs[i + 1][j] == 9)
                            this.arrs[i][j]++;
                    }
                    if (i < this.rowCount - 1 && j < this.colCount - 1) {
                        if (this.arrs[i + 1][j + 1] == 9)
                            this.arrs[i][j]++;
                    }
                }
            }
        },
        //給每個格子綁定點擊事件(左鍵和右鍵)
        bindCells: function () {
            var self = this;
            for (var i = 0; i < this.rowCount; i++) {
                for (var j = 0; j < this.colCount; j++) {
                    (function (row, col) {
                        self.$("m" + i + "" + j).onmousedown = function (e) {
                            e = e || window.event;
                            var mouseNum = e.button;
                            var className = this.className;
                            if (mouseNum == 2) {
                                if (className == "flag") {
                                    this.className = "";
                                    self.markLandMineCount--;
                                } else {
                                    this.className = "flag";
                                    self.markLandMineCount++;
                                }
                                if (self.landMineCallBack) {
                                    self.landMineCallBack(self.landMineCount - self.markLandMineCount);
                                }
                            } else if (className != "flag") {
                                self.openBlock.call(self, this, row, col);
                            }
                        };
                    })(i,j);
                }
            }
        },
        //展開無雷區域
        showNoLandMine: function (x, y) {
            for (var i = x - 1; i < x + 2; i++)
                for (var j = y - 1; j < y + 2; j++) {
                    if (!(i == x && j == y)) {
                        var ele = this.$("m" + i + "" + j);
                        if (ele && ele.className == "") {
                            this.openBlock.call(this, ele, i, j);
                        }
                    }
                }
        },
        //顯示
        openBlock: function (obj, x, y) {
            if (this.arrs[x][y] != 9) {
                this.currentSetpCount++;
                if (this.arrs[x][y] != 0) {
                    obj.innerHTML = this.arrs[x][y];
                }
                obj.style.backgroundColor = "green";
                obj.className = "normal";
                if (this.currentSetpCount + this.landMineCount == this.rowCount * this.colCount) {
                    this.success();
                }
                if (this.arrs[x][y] == 0) {
                    this.showNoLandMine.call(this, x, y);
                }
            } else {
                this.failed();
            }
        },
        //顯示地雷
        showLandMine: function () {
            for (var i = 0; i < this.rowCount; i++) {
                for (var j = 0; j < this.colCount; j++) {
                    if (this.arrs[i][j] == 9) {
                        this.$("m" + i.toString() + j).className = "landMine";
                    }
                }
            }
        },
        //顯示所有格子信息
        showAll: function () {
            for (var i = 0; i < this.rowCount; i++) {
                for (var j = 0; j < this.colCount; j++) {
                    if (this.arrs[i][j] == 9) {
                        this.$("m" + i.toString() + j).className = "landMine";
                    } else {
                        if (this.arrs[i][j] != 0)
                            this.$("m" + i.toString() + j).innerHTML = this.arrs[i][j];
                    }
                }
            }
        },
        //清除顯示的格子信息
        hideAll: function () {
            for (var i = 0; i < this.rowCount; i++) {
                for (var j = 0; j < this.colCount; j++) {
                    var tdCell = this.$("m" + i.toString() + j);
                    tdCell.className = "";
                    tdCell.innerHTML = "";
                }
            }
        },
        //刪除格子綁定的事件
        disableAll: function () {
            for (var i = 0; i < this.rowCount; i++) {
                for (var j = 0; j < this.colCount; j++) {
                    var tdCell = this.$("m" + i.toString() + j);
                    tdCell.onmousedown = null;
                }
            }
        },
        //游戲開始
        begin: function () {
            this.currentSetpCount = 0;//開始的步數清零
            this.markLandMineCount = 0;
            this.beginTime = new Date();//游戲開始時間
            this.hideAll();
            this.bindCells();
        },
        //游戲結束
        end: function () {
            this.endTime = new Date();//游戲結束時間
            if (this.endCallBack) {//如果有回調函數則調用
                this.endCallBack();
            }
        },
        //游戲成功
        success: function () {
            this.end();
            this.showAll();
            this.disableAll();
            alert("Congratulation!");
        },
        //游戲失敗
        failed: function () {
            this.end();
            this.showAll();
            this.disableAll();
            alert("GAME OVER!");
        },
        //通數值找到行數和列數
        getRowCol: function (val) {
            return {
                row: parseInt(val / this.colCount),
                col: val % this.colCount
            };
        },
        //獲取一個隨機數
        selectFrom: function (iFirstValue, iLastValue) {
            var iChoices = iLastValue - iFirstValue + 1;
            return Math.floor(Math.random() * iChoices + iFirstValue);
        },
        eventFire: function (el, etype) {
            if (el.fireEvent) {
                (el.fireEvent('on' + etype));
            } else {
                var evObj = document.createEvent('Events');
                evObj.initEvent(etype, false, false);
                el.dispatchEvent(evObj);
            }
        },
        //入口函數
        play: function () {
            this.init();
            this.landMine();
            this.calculateNoLandMineCount();
        }
    };

    window.FLM = FLM;
})();

  HTML部分:

<div id="FLM_main">
    <table id="landmine">
    </table>
    <div id="operation">
        <div class="tip">剩余雷數:<span class="light red" id="landMineCount">0</span></div>
        <div class="tip">持續時間: <span class="light f60" id="costTime">0</span> s</div>
        <input type="button" id="showLandMine" value="顯示地雷" /><br />
        <input type="button" id="showAll" value="顯示全部" /><br />
        <input type="button" id="begin" value="開始游戲" /><br />
        <div class="tip txtleft">提示:
            <ul>
                <li>1、點擊“開始游戲”游戲開始計時</li>
                <li>2、游戲過程中點擊“顯示地雷”或“顯示全部”游戲將會結束</li>
            </ul>
        </div>
    </div>
</div>

  調用部分:

window.onload = function () {
    var flm = FLM("landmine", 10, 10),
        doc = document,
        landMineCountElement = doc.getElementById("landMineCount"),
        timeShow = doc.getElementById("costTime"),
        showLandMineButton = doc.getElementById("showLandMine"),
        showAllButton = doc.getElementById("showAll"),
        beginButton = doc.getElementById("begin"),
        timeHandle = null;
    flm.endCallBack = function () {
        clearInterval(timeHandle);
    };
    flm.landMineCallBack = function (count) {
        landMineCountElement.innerHTML = count;
    };

    //為“開始游戲”按鈕綁定事件
    beginButton.onclick = function () {
        flm.play();//初始化

        //顯示地雷個數
        landMineCountElement.innerHTML = flm.landMineCount;

        //為“顯示地址”按鈕綁定事件
        showLandMineButton.onclick = function () {
            if (confirm("顯示地雷游戲將結束?")) {
                flm.failed();
                flm.showLandMine();
            }
        };

        //為“顯示全部”按鈕綁定事件
        showAllButton.onclick = function () {
            if (confirm("顯示全部游戲將結束?")) {
                flm.failed();
                flm.showAll();
            }
        };

        //開始
        flm.begin();

        //更新花費時間
        timeHandle = setInterval(function () {
            timeShow.innerHTML = parseInt((new Date() - flm.beginTime) / 1000);
        }, 1000);
    };
}

  布局用的是table,所以FLM三個參數的第一個就是table的ID,第二個參數為最少地雷個數,第三個參數為最多地雷個數。

  運行效果:

Demo
剩余雷數: 0
持續時間: 0 s



提示:
  • 1、點擊“開始游戲”游戲開始計時
  • 2、游戲過程中點擊“顯示地雷”或“顯示全部”游戲將會結束

 

  各位朋友們,果斷地把你們的成績截圖曬出來吧!!!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM