SOURCE

console 命令行工具 X clear

                    
>
console
        var data = [];
        var blockEvt = false;

        /**
         * 同步data到dom上(更新颜色) 
         */
        function refresh() {
            for (let i = 0; i < 10; i++) {
                for (let j = 0; j < 10; j++) {
                    $(`#N_${i}_${j}`).attr("cr", data[i][j]);
                }
            }
        }

        /**
         * 点击事件
         */
        function doClick(oid) {
            if (blockEvt) return;
            blockEvt = true;

            // 从id中取出坐标
            let row = parseInt(oid.split('_')[1]);
            let col = parseInt(oid.split('_')[2]);

            // 用一个set存储找到的方块
            let stock = new Set();
            findBlocks(data[row][col], stock, row, col);

            // 没有连续的不处理
            if (stock.size < 2) {
                console.log('single!');
                blockEvt = false;
                return;
            }
            $("#stepCount").val(parseInt($("#stepCount").val()) + 1);

            // 加个样式标记出来
            markup(stock);
            setTimeout(() => {
                // 延时删除,懒得弄动画
                removeBlock(stock);
            }, 500);
        }

        /**
         * 递归查找
         */
        function findBlocks(val, stock, row, col) {
            // 存放在set中的key值
            let k = `${row}_${col}`;
            // 判断超出范围
            if (row < 0 || row > 9) return;
            if (col < 0 || col > 9) return;
            // 判断已存在
            if (stock.has(k)) return;
            // 判断颜色是否相同
            if (data[row][col] != val) return;

            // 存入set中
            stock.add(k);
            // 再继续判断上下左右的方块
            findBlocks(val, stock, row, col - 1);
            findBlocks(val, stock, row, col + 1);
            findBlocks(val, stock, row - 1, col);
            findBlocks(val, stock, row + 1, col);
        }

        function markup(stock) {
            console.log(stock)
            for (let pt of stock) {
                $('#N_' + pt).toggleClass('active');
            }
        }

        function removeBlock(stock) {
            // 数值改成0
            for (let pt of stock) {
                let row = parseInt(pt.split('_')[0]);
                let col = parseInt(pt.split('_')[1]);
                data[row][col] = 0;
            }
            // 刷新颜色
            refresh();
            // 取消标记
            markup(stock);
            // 延时处理掉落逻辑
            setTimeout(() => {
                fallDown();
            }, 1000);
        }

        function fallDown() {
            // 很low的冒泡法
            // 按列,从下往上处理
            for (let col = 0; col < 10; col++) {
                for (let row = 9; row >= 0; row--) {
                    // 如果某格是0
                    if (data[row][col] == 0) {
                        // 就找到它上面最近一个非0的方格
                        for (let p = row - 1; p >= 0; p--) {
                            if (data[p][col] > 0) {
                                // 并和它交换
                                data[row][col] = data[p][col];
                                data[p][col] = 0;
                                break;
                            }
                        }
                    }
                }
            }
            refresh();
            blockEvt = false;
        }

        function initEvent() {
            $("#panel").delegate("span", "click", function () {
                doClick(this.id);
            });
        }

        function init() {
            $("#panel").empty();
            for (let i = 0; i < 10; i++) {
                data.push(Array.from({
                    length: 10
                }));
                for (let j = 0; j < 10; j++) {
                    $("#panel").append(
                        `<span id="N_${i}_${j}" cr="${data[i][j]}"></span>`
                    );
                }
            }
            createGame();
            initEvent();
        }

        function createGame() {
            $("#stepCount").val(0);
            for (let i = 0; i < 10; i++) {
                for (let j = 0; j < 10; j++) {
                    data[i][j] = 1 + Math.round(Math.random() * 10000) % 5;
                }
            }
            refresh();
        }

        init();
    <div id="panel">

    </div>
    <div id="action">
        <button onClick="createGame()">重新开始</button>
        <label for="stepCount">计数</label>
        <input type="text" id="stepCount" readonly="true">
    </div>
        #panel {
            margin: 10px;
            width: 200px;
            height: 200px;
            box-shadow: 0 0 5px #000;
        }

        #panel>span {
            box-sizing: border-box;
            border: 1px solid #fff;
            height: 20px;
            width: 20px;
            float: left;
        }

        #panel>span[cr="1"] {
            background: MediumVioletRed;
        }

        #panel>span[cr="2"] {
            background: CadetBlue;
        }

        #panel>span[cr="3"] {
            background: Coral;
        }

        #panel>span[cr="4"] {
            background: LimeGreen;
        }

        #panel>span[cr="5"] {
            background: Gold;
        }

        #panel>span.active {
            border-color: #000;
        }