累了休息一会儿吧——分享一个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、游戏过程中点击“显示地雷”或“显示全部”游戏将会结束

 

  各位朋友们,果断地把你们的成绩截图晒出来吧!!!

你可能感兴趣的:(JavaScript)