扫雷

Javascript扫雷游戏 http://calefy.org/demos/minesweeper.html

by calefy

HTML

<h2>扫雷</h2>

    <!--操作-->
    <div class="l">
        <ul id="options">
            <li><label>行数:</label><input id="row" name="" type="text" value="10"/></li>
            <li><label>列数:</label><input id="col" name="" type="text" value="10"/></li>
            <li><label>雷数:</label><input id="mine" name="" type="text" value="20"/></li>
            <li><input type="button" value="开局" id="begin" /></li>
        </ul>

        <dl>
            <dt>玩法:</dt>
            <dd>1. 左键单击显示结果,右键标记小旗</dd>
            <dd>2. 会自动弹出结果,如果没有结果,说明有些标记是错误的</dd>
            <dd>3. 点击按钮“开局”会重新开始一局</dd>
        </dl>
    </div>

    <!--实际操作区域-->
    <div id="canvas"></div>

CSS

body{background-color:#eee;}
div.l{float:left;width:280px;margin-right:15px;}
ul{list-style:none;margin:0;padding:0;background-color:#eee;}
li{margin:8px;}
label{margin-right:10px;}
dl{font-size:12px;margin-top:20px;}
dd{margin:5px 10px;}

    /* 雷区样式定义 */
    #canvas.mines{display:inline-block;*display:inline;*zoom:1;border-width:3px;border-style:solid;border-color:#999 #fff #fff #999;}
    #canvas a{display:block;float:left;width:25px;height:25px;text-decoration:none;text-align:center;font-weight:bold;font-size:110%;line-height:25px;cursor:default;border-width:2px;border-style:solid;border-color:#fff #999 #999 #fff;background-color:#ccc; }
    #canvas a:active,
    #canvas .ok,
    #canvas .flag{border-color:#999 #ccc #ccc #999;}

JavaScript

/*
        Class MineSweeper
            generateMetricsData() ------ 根据行列雷数生成随机矩阵雷区
            isWin() -------------------- 是否获胜
            setCellData(i, j, v) ------- 设置某个区块内容值
            getCellData(i, j) ---------- 得到某个区块内容值
            getMetricsData() ----------- 得到所有雷区矩阵数据

            _init()
            updateValueOfMineAround(i, j) 更新雷周围区域的计数
            showAroundEmpty(i, j)         显示空块周围区域的空块
            showResult()                  显示结果
            drawMineArea()                绘制雷区
            onMousedown(evt)              处理点击事件
*/

/**
 * @constructor
 *
 * 1. 在 row*col 的区域内随机布置指定的雷数
 * 2. 每随机生成一个雷的位置,遍历周边8个区域,累加周边的提示数值
 * 3. 绘制矩阵,监视每个雷区的左右点击事件
 */
var MineSweeper = function(config) {
    $.extend(this, {
        'container': '#canvas',
        // 雷区容器
        'row': 10,
        // 要布置的雷区的行数
        'col': 10,
        // 要布置的雷区的列数
        'mineNumber': 20,
        // 雷区中的雷的数量
        'openClass': 'ok',
        // 打开的区块要添加的类名
        'flagClass': 'flag' // 插旗标的区块要添加的类名
    }, config);

    this._init();
};
MineSweeper.VALUE_MINE = -1; // 区块中是雷
MineSweeper.VALUE_NULL = 0; // 区块为空
MineSweeper.STATUS_CLOSE = 0; // 区块的状态是“未打开”
MineSweeper.STATUS_OPEN = 1; // 区块的状态是“已打开”
MineSweeper.STATUS_FLAG = 2; // 区块的状态是“插旗标”
/**
 * 初始化
 */
MineSweeper.prototype._init = function() {
    // 检测雷数比例
    if (this.mineNumber / (this.row * this.col) > 0.8) {
        alert('80%以上的区域都是雷。\n雷数太多了!');
        return;
    }

    this.container = $(this.container);

    // 生成雷区对应的矩阵
    this.generateMetricsData();

    // 用矩阵绘制
    this.drawMineArea(this.getMetricsData());

    // 注册事件
    this.container.undelegate().delegate('a', 'click contextmenu', $.proxy(this.onMousedown, this));
};

/**
 * 点击事件
 */
MineSweeper.prototype.onMousedown = function(evt) {
    var target = $(evt.currentTarget),
        pos = target.data('index').split(','),
        i = pos[0] - 0,
        j = pos[1] - 0,
        v = this.getCellData(i, j),
        isOver;

    switch (evt.type) {
       ...