网页版俄罗斯方块

兼容性

兼容IE10,现代浏览器

效果图

在这里插入图片描述

项目结构

tetris
  css
    tetris.css
  js
    tetris.js
  tetris.html

tetris.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>俄罗斯方块</title>
    <link rel="stylesheet" type="text/css" href="css/tetris.css">
</head>
<body>
<div class="container">
    <div class="left">
        <div id="score-panel" class="score-panel">
            <span class="score-label">得分:</span>
            <span class="score">0</span>
        </div>
        <div id="main-panel" class="panel">
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
            <div class="panel-cell"></div>
        </div>
        <div id="fail" class="fail hidden">
            <div class="fail-down">失败了</div>
            <div class="fail-up">失败了</div>
        </div>
    </div>
    <div class="right">
        <div id="preview" class="preview"></div>
        <div class="key-summary">
            <div class="key-summary-row"><!--
             --><div id="left-turn" class="key-summary-show key-summary-left-turn"><span>Q</span>&nbsp;<span>左转</span></div><!--
             --><div id="right-turn" class="key-summary-show key-summary-right-turn"><span>E</span>&nbsp;<span>右转</span></div><!--
         --></div>
            <div class="key-summary-row"><!--
             --><div id="left-move" class="key-summary-show key-summary-left-move"><span>A</span>&nbsp;<span>左移</span></div><!--
             --><div id="bottom-move" class="key-summary-show key-summary-bottom-move"><span>S</span>&nbsp;<span>下移</span></div><!--
             --><div id="right-move" class="key-summary-show key-summary-right-move"><span>D</span>&nbsp;<span>右移</span></div><!--
         --></div>
            <div class="key-summary-row"><!--
             --><div id="pause-restore" class="key-summary-show key-summary-pause-restore"><!--
             --><span>SPACE</span>&nbsp;<span class="show-pause-restore">暂停</span><!--
             --></div><!--
         --></div>
        </div>
        <div class="start-container"><!--
         --><div id="start-normal" class="start start-normal">重新开始</div><!--
     --></div>
        <div class="start-container"><!--
         --><div id="start-random" class="start start-random">随机玩法</div><!--
     --></div>
    </div>
</div>
</body>
<script type="text/javascript" src="js/tetris.js"></script>
</html>

tetris.css

html,body {height: 100%;}
.container {
    position: fixed;
    left: 0;
    right: 0;
    top: 0;
    bottom: 0;
    margin: auto;
    width: 460px;
    height: 514px;
    background-color: #00AA00;
    font-family: "Microsoft YaHei", "微软雅黑", serif;
}
.left {
    position: absolute;
    left: 0;
    top: 0;
    width: 244px;
    height: 514px;
}
.left .score-panel {
    height: 30px;
    -webkit-box-sizing: border-box;-moz-box-sizing: border-box;box-sizing: border-box;
    border: 2px solid #202020;
    border-bottom: none;
    line-height: 28px;
    font-size: 16px;
    background-color: #00FFFF;
}
.left .score-panel .score-label {
    margin-left: 10px;
}
.left .score-panel .score {
    font-weight: bold;
}
.left .panel {
    position: relative;
    left: 0;
    top: 0;
    overflow: hidden;
    -webkit-box-sizing: border-box;-moz-box-sizing: border-box;box-sizing: border-box;
    border: 2px solid #202020;
    height: 484px;
}
.left .panel-cell {
    float: left;
    width: 24px;
    height: 24px;
    -webkit-box-sizing: border-box;-moz-box-sizing: border-box;box-sizing: border-box;
    border: 1px solid #f0f0f0;
    background-color: #D0D0D0;
}
.left .fail {
    position: absolute;
    z-index: 3;
    width: 160px;
    height: 40px;
    left: 0;
    right: 0;
    top: 30px;
    bottom: 0;
    margin: auto;
    text-align: center;
    line-height: 40px;
    font-size: 30px;
    letter-spacing: 8px;
    text-indent: 8px;
    color: #ffffff;
    -webkit-user-select: none;-ms-user-select: none;user-select: none;
}
.left .fail-down {
    position: absolute;
    width: 100%;
    color: #202020;
    left: 2px;
    top: 2px;
    opacity: 0.35;
}
.left .fail-up {
    position: absolute;
    width: 100%;
    left: 0;
    top: 0;
    text-shadow: 0 0 5px #202020;
}
.left .hidden {
    display: none;
}

.right {
    position: absolute;
    right: 0;
    top: 0;
    width: 216px;
    height: 514px;
    -webkit-box-sizing: border-box;-moz-box-sizing: border-box;box-sizing: border-box;
    border: 2px solid #202020;
    border-left: none;
    background-color: #d5c9f0;
    -webkit-user-select: none;-ms-user-select: none;user-select: none;
}
.right .preview {
    position: relative;
    left: 0;
    top: 0;
    overflow: hidden;
    height: 214px;
    -webkit-box-sizing: border-box;-moz-box-sizing: border-box;box-sizing: border-box;
    border-bottom: 2px solid #202020;
}
.right .preview .preview-shape {
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    margin: auto;
}
.right .preview .preview-cell {
    float: left;
    width: 24px;
    height: 24px;
    -webkit-box-sizing: border-box;-moz-box-sizing: border-box;box-sizing: border-box;
    border: 1px solid #d5c9f0;
}
.right .key-summary {
    -webkit-box-sizing: border-box;-moz-box-sizing: border-box;box-sizing: border-box;
    border-bottom: 2px solid #202020;
    cursor: default;
}
.right .key-summary .key-summary-row {
    text-align: center;
    margin: 10px 0;
}
.right .key-summary .key-summary-show {
    display: inline-block;
    height: 36px;
    border: 2px solid #5cffa8;
    background-color: #122b40;
    -webkit-box-sizing: border-box;-moz-box-sizing: border-box;box-sizing: border-box;
    padding: 4px 10px;
    overflow: hidden;
    color: #f0f0f0;
    font-size: 14px;
    line-height: 24px;
    border-radius: 16px;
    margin: 0 2px;
    cursor: pointer;
}
.right .key-summary .key-summary-left-turn,
.right .key-summary .key-summary-right-turn {
    padding: 4px 27px;
}
.right .key-summary .key-summary-pause-restore {
    padding: 4px 62px;
    background-color: #d58a05;
}
.right .key-summary .down {
    line-height: 26px;
}
.right .start-container {
    text-align: center;
    margin: 18px 0;
}
.right .start {
    display: inline-block;
    height: 40px;
    -webkit-box-sizing: border-box;-moz-box-sizing: border-box;box-sizing: border-box;
    padding: 4px 12px;
    color: #f0f0f0;
    font-size: 18px;
    font-weight: bold;
    letter-spacing: 4px;
    text-indent: 4px;
    line-height: 28px;
    border: 2px solid #0000FF;
    border-radius: 20px;
    margin: 0 2px;
    cursor: pointer;
}
.right .start.down {
    line-height: 30px;
}
.right .start-normal {
    background-color: #00e000;
}
.right .start-random {
    background-color: #FF00FF;
}

tetris.js

(function (window, document) {
    var scoreDom = document.querySelector('#score-panel .score');
    var panelCellDoms = document.querySelectorAll('#main-panel .panel-cell');
    var previewDom = document.querySelector('#preview');
    var failDom = document.querySelector('#fail');
    var leftTurn = document.querySelector('#left-turn');
    var rightTurn = document.querySelector('#right-turn');
    var leftMove = document.querySelector('#left-move');
    var bottomMove = document.querySelector('#bottom-move');
    var rightMove = document.querySelector('#right-move');
    var pauseRestoreDom = document.querySelector('#pause-restore');
    var showPauseRestore = pauseRestoreDom.querySelector('.show-pause-restore');
    var startNormalDom = document.querySelector('#start-normal');
    var startRandomDom = document.querySelector('#start-random');

    var mainCells = [
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
    ];
    var shapes = {
        //O
        0: {
            0: {point: [[1, 1], [1, 1]], x: 0, y: 0},
            length: 1, type: 'O', color: '#ff0096'
        },
        //I
        1: {
            0: {point: [[1, 1, 1, 1]], x: 1, y: 0},
            1: {point: [[1], [1], [1], [1]], x: 0, y: 2},
            length: 2, type: 'I', color: '#00ee0c'
        },
        //T
        2: {
            0: {point: [[1, 1, 1], [0, 1, 0]], x: 1, y: 0},
            1: {point: [[0, 1], [1, 1], [0, 1]], x: 1, y: 1},
            2: {point: [[0, 1, 0], [1, 1, 1]], x: 1, y: 1},
            3: {point: [[1, 0], [1, 1], [1, 0]], x: 0, y: 1},
            length: 4, type: 'T', color: '#ffa905'
        },
        //L1
        3: {
            0: {point: [[1, 0], [1, 0], [1, 1]], x: 0, y: 1},
            1: {point: [[1, 1, 1], [1, 0, 0]], x: 1, y: 0},
            2: {point: [[1, 1], [0, 1], [0, 1]], x: 1, y: 1},
            3: {point: [[0, 0, 1], [1, 1, 1]], x: 1, y: 1},
            length: 4, type: 'L', color: '#ff000a'
        },
        //L2
        4: {
            0: {point: [[0, 1], [0, 1], [1, 1]], x: 1, y: 1},
            1: {point: [[1, 0, 0], [1, 1, 1]], x: 1, y: 1},
            2: {point: [[1, 1], [1, 0], [1, 0]], x: 0, y: 1},
            3: {point: [[1, 1, 1], [0, 0, 1]], x: 1, y: 0},
            length: 4, type: 'L', color: '#00d1b4'
        },
        //S
        5: {
            0: {point: [[1, 0], [1, 1], [0, 1]], x: 0, y: 1},
            1: {point: [[0, 1, 1], [1, 1, 0]], x: 1, y: 0},
            length: 2, type: 'S', color: '#0660ff'
        },
        //Z
        6: {
            0: {point: [[0, 1], [1, 1], [1, 0]], x: 0, y: 1},
            1: {point: [[1, 1, 0], [0, 1, 1]], x: 1, y: 0},
            length: 2, type: 'Z', color: '#a745ff'
        },
        length: 7
    };

    var Cell = (function () {
        function Cell(shape, index, x, y) {
            this.shape = shape;
            this.index = index;
            this.x = x || 0;
            this.y = y || 0;
        }
        Cell.prototype.getX = function () {
            return this.x;
        };
        Cell.prototype.getY = function () {
            return this.y;
        };
        Cell.prototype.setX = function (x) {
            this.x = x;
        };
        Cell.prototype.setY = function (y) {
            this.y = y;
        };
        Cell.prototype.incrX = function (x) {
            this.x += x;
        };
        Cell.prototype.incrY = function (y) {
            this.y += y;
        };
        Cell.prototype.decrX = function (x) {
            this.x -= x;
        };
        Cell.prototype.decrY = function (y) {
            this.y += y;
        };
        return Cell;
    })();

    var CellUtil = (function () {
        var score = 0;
        var cellQueue = [];
        var currentCell = null;
        var isPause = false, isStart = false;
        var nextTimeout = null, moveTimeout = null;
        var magic = 0, loopEventTime = null;
        function Util() {}
        Util.prototype.setMagic = function (num) {
            magic = num;
        };
        Util.prototype.getMagic = function () {
            return magic;
        };
        Util.prototype.clearLoopEventTime = function () {
            this.setMagic(0);
            window.clearTimeout(loopEventTime);
        };
        Util.prototype.initNormal = function () {
            this._clear();
            for (var i = 0; i < mainCells.length; i++) {
                mainCells[i] = 0;
            }
            this._init();
        };
        Util.prototype.initRandom = function () {
            this._clear();
            var count = 0;
            for (var i = 0; i < mainCells.length; i++) {
                var act = i < 50 || count >= 9 ? 0 : (Math.random() + 0.15) | 0;
                act > 0 ? count++ : count = 0;
                mainCells[i] = act;
            }
            this._init();
        };
        Util.prototype.pauseOrRestore = function () {
            if (!isStart) {
                return;
            }
            if (isPause) {
                isPause = false;
                showPauseRestore.innerText = '暂停';
                this._loopMoveBottom();
            } else {
                isPause = true;
                showPauseRestore.innerText = '恢复';
                window.clearTimeout(moveTimeout);
            }
        };
        Util.prototype._clear = function () {
            isPause = false;
            isStart = true;
            this.setMagic(0);
            window.clearTimeout(nextTimeout);
            window.clearTimeout(moveTimeout);
            cellQueue = [];
            currentCell = null;
            failDom.classList.add('hidden');
            scoreDom.innerText = score = 0;
            previewDom.innerHTML = '';
            showPauseRestore.innerText = '暂停';
        };
        Util.prototype._alertFail = function () {
            isStart = false;
            this.setMagic(0);
            window.clearTimeout(nextTimeout);
            window.clearTimeout(moveTimeout);
            cellQueue = [];
            currentCell = null;
            failDom.classList.remove('hidden');
        };
        Util.prototype._init = function () {
            scoreDom.innerText = 0;
            previewDom.innerHTML = '';
            for (var i = 0; i < mainCells.length; i++) {
                if (mainCells[i] === 1) {
                    panelCellDoms[i].style.backgroundColor = '#204060';
                } else {
                    panelCellDoms[i].style.backgroundColor = '#D0D0D0';
                }
            }
            this._start();
        };
        Util.prototype._start = function () {
            this.previewCell();
            this._next();
        };
        Util.prototype._next = function () {
            var that = this;
            window.clearTimeout(nextTimeout);
            nextTimeout = window.setTimeout(function () {
                currentCell = cellQueue.shift();
                that.previewCell();
                that._refresh(currentCell, function (cell) {
                    var shape = cell.shape[cell.index];
                    var point = shape.point;
                    var wCnt = point[0].length, hCnt = point.length;
                    cell.setX(((10 - wCnt) / 2) | 0);
                    cell.setY(0 - hCnt);
                });
                if (isPause) {
                    return;
                }
                that._loopMoveBottom();
            }, 1800);
        };
        Util.prototype._loopMoveBottom = function () {
            var that = this;
            window.clearTimeout(moveTimeout);
            if (currentCell == null) {
                return;
            }
            var delay = Math.max(1200 - ((score / 10) | 0), 200);
            moveTimeout = window.setTimeout(function () {
                if (currentCell !== null) {
                    that.moveToBottom();
                    that._loopMoveBottom();
                }
            }, delay);
        };
        Util.prototype.previewCell = function () {
            var cell = this._createCell();
            cellQueue.push(cell);
            previewDom.innerHTML = '';
            var shapeColor = cell.shape.color;
            var shape = cell.shape[cell.index];
            var point = shape.point;
            var previewShape = document.createElement('div');
            previewShape.classList.add('preview-shape');
            var hCnt = point.length, wCnt = point[0].length;
            for (var i = 0; i < hCnt; i++) {
                var pointSub = point[i];
                for (var j = 0; j < wCnt; j++) {
                    var previewCell = document.createElement('div');
                    previewCell.classList.add('preview-cell');
                    if (pointSub[j] === 1) {
                        previewCell.style.backgroundColor = shapeColor;
                    }
                    previewShape.appendChild(previewCell);
                }
            }
            previewShape.style.width = wCnt * 24 + 'px';
            previewShape.style.height = hCnt * 24 + 'px';
            previewDom.appendChild(previewShape);
        };
        Util.prototype._createCell = function () {
            var shapesIndex = (Math.random() * shapes.length) | 0;
            var shape = shapes[shapesIndex];
            var cell = new Cell(shape, (Math.random() * shape.length) | 0);
            var subShape = shape[cell.index];
            var point = subShape.point;
            cell.x = Math.round((10 - point[0].length) / 2);
            cell.y = 0 - point.length;
            return cell;
        };
        Util.prototype._refresh = function (cell, func) {
            var originalCell = new Cell(cell.shape, cell.index, cell.x, cell.y);
            var preIndexes = this.getPanelCellDomIndexes(cell);
            var check = func(cell);
            var postIndexes = this.getPanelCellDomIndexes(cell);
            if (check) {
                if (this._isOutBottom(cell) || this._isCover(postIndexes)) {
                    cell.shape = originalCell.shape;
                    cell.index = originalCell.index;
                    cell.setX(originalCell.getX());
                    cell.setY(originalCell.getY());
                    this._fixCell(cell);
                    currentCell = null;
                    if (this._isFail(originalCell, this._eliminate())) {
                        this._alertFail();
                    } else {
                        this._next();
                    }
                    return;
                }
            } else {
                if (originalCell.index === cell.index) {
                    if (!this._checkMove(cell, postIndexes)) {
                        cell.shape = originalCell.shape;
                        cell.index = originalCell.index;
                        cell.setX(originalCell.getX());
                        cell.setY(originalCell.getY());
                        return;
                    }
                } else {
                    //旋转边缘检查
                    if (!this._checkRotate(cell)) {
                        cell.shape = originalCell.shape;
                        cell.index = originalCell.index;
                        cell.setX(originalCell.getX());
                        cell.setY(originalCell.getY());
                        return;
                    }
                }
            }
            postIndexes = this.getPanelCellDomIndexes(cell);
            var pasIndexes = this.arrayExcept(preIndexes, postIndexes);

            this._refreshDom(cell, pasIndexes, postIndexes);
        };
        Util.prototype._fixCell = function (cell) {
            var postIndexes = this.getPanelCellDomIndexes(cell);
            for (var i = 0; i < postIndexes.length; i++) {
                mainCells[postIndexes[i]] = 1;
            }
        };
        Util.prototype._eliminate = function () {
            var indexs = [];
            for (var i = 0; i < mainCells.length; i++) {
                if (i % 10 === 0) {
                    if (mainCells[i] === 1) {
                        indexs.push(i);
                    } else {
                        i = ((i / 10 + 1) | 0) * 10 - 1;
                    }
                } else {
                    if (mainCells[i] === 1) {
                        indexs.push(i);
                    } else {
                        indexs.splice(indexs.length - i % 10);
                        i = ((i / 10 + 1) | 0) * 10 - 1;
                    }
                }
            }
            if (!indexs.length) {
                return 0;
            }
            scoreDom.innerText = this._incrScore(indexs.length / 10);
            for (var i = 0; i < indexs.length; i++) {
                var index = indexs[i];
                for (var j = index; j >= 0; j -= 10) {
                    if (j < 10) {
                        mainCells[j] = 0;
                        panelCellDoms[j].style.backgroundColor = '#D0D0D0';
                    } else {
                        mainCells[j] = mainCells[j - 10];
                        panelCellDoms[j].style.backgroundColor = panelCellDoms[j - 10].style.backgroundColor;
                    }
                }
            }
            return indexs.length / 10;
        };
        Util.prototype._isFail = function (cell, rows) {
            return cell.y + rows < 0;
        };
        Util.prototype._incrScore = function (rows) {
            if (rows === 1) {
                score += 10;
            } else if (rows === 2) {
                score += 20;
            } else if (rows === 3) {
                score += 40;
            } else if (rows === 4) {
                score += 80;
            }
            return score;
        };
        Util.prototype._checkMove = function (cell, postIndexes) {
            if (!this._isInnerMain(cell)) {
                return false;
            }
            //平移边缘检查, 如果无覆盖,则返回true,否则返回false
            return !this._isCover(postIndexes);
        };
        Util.prototype._isOutBottom = function (cell) {
            var subShape = cell.shape[cell.index], point = subShape.point;
            var hCnt = point.length;
            return cell.y + hCnt > 20;
        };
        Util.prototype._isCover = function (postIndexes) {
            //平移边缘检查, 如果无覆盖,则返回true,否则返回false
            for (var i = 0; i < postIndexes.length; i++) {
                if (mainCells[postIndexes[i]] === 1) {
                    return true;
                }
            }
            return false;
        };
        Util.prototype._checkRotate = function (cell) {
            //旋转边缘检查, 如果无覆盖,则返回true,否则返回false
            var innerMain = this._isInnerMain(cell);
            var subShape = cell.shape[cell.index], point = subShape.point;
            var hCnt = point.length, wCnt = point[0].length;
            if (!innerMain) {
                cell.x < 0 ? cell.setX(0) : cell.setX(10 - wCnt);
            }
            var outBottom = cell.y + hCnt > 20, isBottom = cell.y + hCnt >= 20;
            if (outBottom) {
                cell.setY(20 - hCnt);
            }
            var indexes = this.getPanelCellDomIndexes(cell);
            var x = cell.x, y = cell.y;
            if (innerMain) {
                if (x > 0 && this._isCover(indexes) && (cell.shape.type !== 'T' || (cell.shape.type === 'S' || cell.shape.type === 'Z') && cell.index === 0)) {
                    cell.setY(y);
                    cell.setX(x - 1);
                    indexes = this.getPanelCellDomIndexes(cell);
                }
                if (x + wCnt < 20 && this._isCover(indexes) && (cell.shape.type !== 'T' && cell.shape.type !== 'I' || (cell.shape.type === 'S' || cell.shape.type === 'Z') && cell.index === 1)) {
                    cell.setY(y);
                    cell.setX(x + 1);
                    indexes = this.getPanelCellDomIndexes(cell);
                }
            }
            return !this._isCover(indexes);

        };
        Util.prototype._isInnerMain = function (cell) {
            var shape = cell.shape[cell.index], point = shape.point;
            var wCnt = point[0].length;
            return cell.x >= 0 && cell.x + wCnt <= 10;

        };
        Util.prototype._refreshDom = function (cell, pasIndexes, postIndexes) {
            for (var i = 0; i < pasIndexes.length; i++) {
                panelCellDoms[pasIndexes[i]].style.backgroundColor = '';
            }
            for (var i = 0; i < postIndexes.length; i++) {
                panelCellDoms[postIndexes[i]].style.backgroundColor = cell.shape.color;
            }
        };
        Util.prototype.getPanelCellDomIndexes = function (cell) {
            var shape = cell.shape[cell.index], x = cell.x, y = cell.y, point = shape.point;
            var panelCellDomIndexes = [];
            var hCnt = point.length, wCnt = point[0].length;
            for (var i = 0; i < hCnt; i++) {
                var pY = i + y;
                if (pY < 0 || pY >= 20) {
                    continue;
                }
                var pointSub = point[i];
                for (var j = 0; j < wCnt; j++) {
                    var pX = j + x;
                    if (pX < 0 || pX >= 10) {
                        continue;
                    }
                    if (pointSub[j] === 1) {
                        panelCellDomIndexes.push(pX + pY * 10);
                    }
                }
            }
            return panelCellDomIndexes;
        };
        Util.prototype.arrayExcept = function (arr1, arr2) {
            var except = [];
            loop:
                for (var i = 0; i < arr1.length; i++) {
                    for (var j = 0; j < arr2.length; j++) {
                        if (arr1[i] === arr2[j]) {
                            continue loop;
                        }
                    }
                    except.push(arr1[i]);
                }
            return except;
        };
        Util.prototype.moveToLeft = function () {
            if (currentCell == null || isPause) {
                return;
            }
            var shape = currentCell.shape[currentCell.index], hCnt = shape.point.length;
            if (currentCell.y + hCnt < 1) {
                return;
            }
            this._refresh(currentCell, function (cell) {
                cell.decrX(1);
                return false;
            });
        };
        Util.prototype.moveToRight = function () {
            if (currentCell == null || isPause) {
                return;
            }
            var shape = currentCell.shape[currentCell.index], hCnt = shape.point.length;
            if (currentCell.y + hCnt < 1) {
                return;
            }
            this._refresh(currentCell, function (cell) {
                cell.incrX(1);
                return false;
            });
        };
        Util.prototype.moveToBottom = function () {
            if (currentCell == null || isPause) {
                return;
            }
            this._refresh(currentCell, function (cell) {
                cell.incrY(1);
                return true;
            });
        };
        Util.prototype.turnToLeft = function () {
            if (currentCell == null || isPause) {
                return;
            }
            var shape = currentCell.shape[currentCell.index], hCnt = shape.point.length;
            if (currentCell.y + hCnt < 1) {
                return;
            }
            this._refresh(currentCell, function (cell) {
                var shape = cell.shape;
                var preCell = shape[cell.index];
                cell.index = (cell.index + shape.length - 1) % shape.length;
                var postCell = shape[cell.index];
                cell.incrX(preCell.x - postCell.x);
                cell.incrY(preCell.y - postCell.y);
                return false;
            });
        };
        Util.prototype.turnToRight = function () {
            if (currentCell == null || isPause) {
                return;
            }
            var shape = currentCell.shape[currentCell.index], hCnt = shape.point.length;
            if (currentCell.y + hCnt < 1) {
                return;
            }
            this._refresh(currentCell, function (cell) {
                var shape = cell.shape;
                var preCell = shape[cell.index];
                cell.index = (cell.index + 1) % shape.length;
                var postCell = shape[cell.index];
                cell.incrX(preCell.x - postCell.x);
                cell.incrY(preCell.y - postCell.y);
                return false;
            });
        };
        Util.prototype.loopEvent = function (delay) {
            var that = this;
            loopEventTime = window.setTimeout(function () {
                if (magic === 3) {
                    delay = Math.max(delay - 30, 30);
                }
                that.loopEvent(delay);
                switch (magic) {
                    case 1:
                        that.moveToLeft();
                        break;
                    case 2:
                        that.moveToRight();
                        break;
                    case 3:
                        that.moveToBottom();
                        break;
                    case 4:
                        that.turnToLeft();
                        break;
                    case 5:
                        that.turnToRight();
                        break;
                }
            }, delay);
        };
        Util.prototype.keyDown = function (magic) {
            if (this.getMagic() !== magic) {
                CellUtil.clearLoopEventTime();
                CellUtil.setMagic(magic);
                switch (magic) {
                    case 1:
                        this.moveToLeft();
                        CellUtil.loopEvent(150);
                        break;
                    case 2:
                        this.moveToRight();
                        CellUtil.loopEvent(150);
                        break;
                    case 3:
                        this.moveToBottom();
                        CellUtil.loopEvent(150);
                        break;
                    case 4:
                        this.turnToLeft();
                        CellUtil.loopEvent(250);
                        break;
                    case 5:
                        this.turnToRight();
                        CellUtil.loopEvent(250);
                        break;
                }
            }
        };
        return new Util();
    })();

    document.onkeydown = (function () {
        return function (e) {
            var code = (e.code || e.key).toLowerCase();
            switch (code) {
                case 'keyq':
                case 'q':
                case 'keyw':
                case 'w':
                case 'arrowup':
                case 'up':
                    CellUtil.keyDown(4);
                    break;
                case 'keye':
                case 'e':
                    CellUtil.keyDown(5);
                    break;
                case 'keya':
                case 'a':
                case 'arrowleft':
                case 'left':
                    CellUtil.keyDown(1);
                    break;
                case 'keys':
                case 's':
                case 'arrowdown':
                case 'down':
                    CellUtil.keyDown(3);
                    break;
                case 'keyd':
                case 'd':
                case 'arrowright':
                case 'right':
                    CellUtil.keyDown(2);
                    break;
            }
            document.onkeyup = function (e) {
                var code = (e.code || e.key).toLowerCase();
                switch (code) {
                    case 'keyq':
                    case 'q':
                    case 'keyw':
                    case 'w':
                    case 'arrowup':
                    case 'up':
                    case 'keye':
                    case 'e':
                    case 'keya':
                    case 'a':
                    case 'arrowleft':
                    case 'left':
                    case 'keys':
                    case 's':
                    case 'arrowdown':
                    case 'down':
                    case 'keyd':
                    case 'd':
                    case 'arrowright':
                    case 'right':
                        CellUtil.clearLoopEventTime();
                        break;
                    case 'space':
                    case 'spacebar':
                        CellUtil.clearLoopEventTime();
                        CellUtil.pauseOrRestore();
                        break;
                }
            };
            return false;
        }
    })();

    (function () {
        function click(dom, downFunc, upFunc) {
            var el = dom.setCapture ? dom : document;
            dom.onmousedown = function (ev) {
                dom.focus();
                var oEvent = ev || window.event;
                downFunc(oEvent);
                el.onmouseup = function (ev) {
                    var oEvent = ev || window.event;
                    if(oEvent.stopPropagation) {
                        oEvent.stopPropagation();
                    } else {
                        oEvent.cancelBubble = true;
                    }
                    upFunc(oEvent);
                    el.onmousemove = null; el.onmouseup = null; if(dom.releaseCapture) {dom.releaseCapture();}
                };
                if(dom.setCapture) {dom.setCapture();}
                return false;
            };
        }
        click(leftTurn, function (e) {
            leftTurn.classList.add('down');
            CellUtil.keyDown(4);
        }, function (e) {
            leftTurn.classList.remove('down');
            CellUtil.clearLoopEventTime();
        });
        click(rightTurn, function (e) {
            rightTurn.classList.add('down');
            CellUtil.keyDown(5);
        }, function (e) {
            rightTurn.classList.remove('down');
            CellUtil.clearLoopEventTime();
        });
        click(leftMove, function (e) {
            leftMove.classList.add('down');
            CellUtil.keyDown(1);
        }, function (e) {
            leftMove.classList.remove('down');
            CellUtil.clearLoopEventTime();
        });
        click(bottomMove, function (e) {
            bottomMove.classList.add('down');
            CellUtil.keyDown(3);
        }, function (e) {
            bottomMove.classList.remove('down');
            CellUtil.clearLoopEventTime();
        });
        click(rightMove, function (e) {
            rightMove.classList.add('down');
            CellUtil.keyDown(2);
        }, function (e) {
            rightMove.classList.remove('down');
            CellUtil.clearLoopEventTime();
        });
        click(startNormalDom, function (e) {
            startNormalDom.classList.add('down');
        }, function (e) {
            startNormalDom.classList.remove('down');
            CellUtil.initNormal();
        });
        click(startRandomDom, function (e) {
            startRandomDom.classList.add('down');
        }, function (e) {
            startRandomDom.classList.remove('down');
            CellUtil.initRandom();
        });

        click(pauseRestoreDom, function (e) {
            pauseRestoreDom.classList.add('down');
        }, function (e) {
            pauseRestoreDom.classList.remove('down');
            CellUtil.clearLoopEventTime();
            CellUtil.pauseOrRestore();
        });
    })();
})(window, document);
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值