5

1、效果原理图片

效果图
坐标图
模块数据分析图

2、直接上代码

1、index.html

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
    <title>rasian square</title>
    <style type="text/css">
        *{margin: 0;padding: 0;}
        table{display: block;margin: 20px auto;width: 200px;}
        table,td{border: 1px solid #999999;border-collapse: collapse;}
        td{width: 20px;height: 20px;line-height: 20px;text-align: center;}
        .center{text-align: center;}
    </style>
</head>
<body>
    <div class="center">
        得分:<span id="score">0</span>
    </div>
    <table></table>
    <div class="center">
        <button onclick="start()">开始</button>
        <button onclick="reload()">重新开始</button>
        <button onclick="rotate()">旋转</button>
    </div>
    <script type="text/javascript" src="./js/common.js"></script>
    <script type="text/javascript" src="./js/data.js"></script>
    <script type="text/javascript" src="./js/game.js"></script>
    <script type="text/javascript" src="./js/block.js"></script>
    <script type="text/javascript">
        var rows = 20,
            verticals = 10,
            speed = 200,
            datas = Array.prototype.slice.call(Object.keys(data)),
            g = new Game(rows, verticals),
            block,
            fixedData = [],
            scores = 0;
        function start() {
            block = new square[datas[Math.floor(Math.random()*datas.length)]](speed);
            var timer = setInterval(function(){
                //触底
                for(var i = 0;i < 4;i++) {
                    if(block.body[i]["x"] >= rows - 1) {
                        fixedData = fixedData.concat(block.body);
                        clearInterval(block.move);
                        block = new square[datas[Math.floor(Math.random()*datas.length)]](speed);
                    };
                    for(var j = 0;j < fixedData.length; j++) {
                        //积累超出画布,游戏结束
                        if(block.body[i]["x"] + 1 == fixedData[j]["x"] && block.body[i]["y"] == fixedData[j]["y"] && block.body[i]["x"] < 0) {
                            clearInterval(block.move);
                            clearInterval(timer);
                        };
                        //碰到已有块
                        if(block.body[i]["x"] + 1 == fixedData[j]["x"] && block.body[i]["y"] == fixedData[j]["y"]) {
                            fixedData = fixedData.concat(block.body);
                            clearInterval(block.move);
                            block = new square[datas[Math.floor(Math.random()*datas.length)]](speed);
                        }
                    };
                };
                score();
                var renderData = fixedData.concat(block.body);
                g.render(renderData);
            },speed);
        };
        function rotate() {
            clearInterval(block.move);
            block.rotate();
            for(var i = 0;i < 4;i++) {
                if(block.body[i]["y"] < 0 || block.body[i]["y"] >= verticals || block.body[i]["x"] >= rows) {
                    block.body = block.preBody;
                };
            };
            block.move = setInterval(function(){block.down()}, speed);
        };
        function reload() {
            window.location.reload();
        };
        function judgeLeftOrRight(direction) {
            for(var i = 0;i < 4;i++) {
                if(direction == 'left' ? block.body[i]["y"] <= 0 : block.body[i]["y"] >= verticals - 1 ) {
                    return true;
                };
                for(var j = 0;j < fixedData.length; j++) {
                    if(block.body[i]["x"] == fixedData[j]["x"] && (direction == 'left' ? block.body[i]["y"] - 1 : block.body[i]["y"] + 1) == fixedData[j]["y"]) {
                        return true;
                    }
                };
            };
            return false;
        };
        function moveLeftOrRight(direction) {
            clearInterval(block.move);
            for(var i = 0;i < 4;i++) {
                direction == 'left' ? block.body[i].y -= 1 : block.body[i].y += 1;
            };
            block.move = setInterval(function(){block.down()}, speed);
        };
        function score() {
            var map = {};
            for(var j = 0;j < fixedData.length; j++) {
                var temp = fixedData[j]["x"];
                if(map[temp]) {
                    map[temp] += 1;
                }else{
                    map[temp] = 1;
                }
            };
            for(key in map) {
                if(map[key] == verticals) {
                    fixedData = fixedData.filter(function(item) {
                        return item.x != key;
                    });
                    for(var j = 0;j < fixedData.length; j++) {
                        if(fixedData[j]["x"] < key) {
                            fixedData[j]["x"] += 1;
                        }
                    };
                    scores += 100;
                    document.getElementById("score").innerHTML = scores;
                }
            };
        };
        document.onkeydown = function(event){
            event = event || window.event;
            if(event.keyCode == 37) { //left
                if(!judgeLeftOrRight('left')) {
                    moveLeftOrRight('left');
                }
            } else if (event.keyCode == 39) { //right
                if(!judgeLeftOrRight('right')) {
                    moveLeftOrRight('right');
                }
            } else if (event.keyCode == 32) { //space
                rotate();
            }
        };
    </script>
</body>
</html>

2、common.js 这个方法之前百度上面看到,就蛮用了

var util = (function () {
    var class2type = {};
    ["Null", "Undefined", "Number", "Boolean", "String", "Object", "Function", "Array", "RegExp", "Date"].forEach(function (item) {
        class2type["[object " + item + "]"] = item.toLowerCase();
    })

    function isType(obj, type) {
        return getType(obj) === type;
    }

    function getType(obj) {
        return class2type[Object.prototype.toString.call(obj)] || "object";
    }

    return {
        isType: isType,
        getType: getType
    }
})();
//对象深,浅拷贝
function copy(obj, deep) {
    if (obj === null || typeof obj !== "object") {
        return obj;
    }
    var i, target = this.util.isType(obj, "array") ? [] : {}, value, valueType;
    for (i in obj) {
        value = obj[i];
        valueType = this.util.getType(value);
        if (deep && (valueType === "array" || valueType === "object")) {
            target[i] = this.copy(value);
        } else {
            target[i] = value;
        }
    }
    return target;
}

3、data.js

var data = {
    /**
    *     ######
    *     ##
    *下折线
    **/

    DLine : {
        init: [
                {x: -2, y: 4},
                {x: -3, y: 4},
                {x: -3, y: 5},
                {x: -3, y: 6}
            ],
        degree0_90: [
                    {x: -1, y: 0},
                    {x: 0, y: 1},
                    {x: 1, y: 0},
                    {x: 2, y: -1}
                ],
        degree90_180: [
                    {x: 0, y: 1},
                    {x: 1, y: 0},
                    {x: 0, y: -1},
                    {x: -1, y: -2}
                ],
        degree180_270: [
                    {x: 1, y: 0},
                    {x: 0, y: -1},
                    {x: -1, y: 0},
                    {x: -2, y: 1}
                ],
        degree270_360: [
                    {x: 0, y: -1},
                    {x: -1, y: 0},
                    {x: 0, y: 1},
                    {x: 1, y: 2}
                ]
    },

    /**
    *     ##
    *     ######
    *上折线
    **/

    ULine : {
        init: [
                {x: -3, y: 4},
                {x: -3, y: 5},
                {x: -3, y: 6},
                {x: -4, y: 4}
            ],
        degree0_90: [
                    {x: 0, y: 1},
                    {x: 1, y: 0},
                    {x: 2, y: -1},
                    {x: 1, y: 2}
                ],
        degree90_180: [
                    {x: 1, y: 0},
                    {x: 0, y: -1},
                    {x: -1, y: -2},
                    {x: 2, y: -1}
                ],
        degree180_270: [
                    {x: 0, y: -1},
                    {x: -1, y: 0},
                    {x: -2, y: 1},
                    {x: -1, y: -2}
                ],
        degree270_360: [
                    {x: -1, y: 0},
                    {x: 0, y: 1},
                    {x: 1, y: 2},
                    {x: -2, y: 1}
                ]
    },

    /**
    *     ##
    *     ##
    *     ##
    *     ##
    *直线
    **/

    Line : {
        init: [
                {x: -1, y: 4},
                {x: -2, y: 4},
                {x: -3, y: 4},
                {x: -4, y: 4}
            ],
        degree0_90: [
                    {x: -2, y: -1},
                    {x: -1, y: 0},
                    {x: 0, y: 1},
                    {x: 1, y: 2}
                ],
        degree90_180: [
                    {x: -1, y: 2},
                    {x: 0, y: 1},
                    {x: 1, y: 0},
                    {x: 2, y: -1}
                ],
        degree180_270: [
                    {x: 2, y: 1},
                    {x: 1, y: 0},
                    {x: 0, y: -1},
                    {x: -1, y: -2}
                ],
        degree270_360: [
                    {x: 1, y: -2},
                    {x: 0, y: -1},
                    {x: -1, y: 0},
                    {x: -2, y: 1}
                ]
    },

    /**
    *       ##
    *     ######
    *凸
    **/

    Raised : {
        init: [
                {x: -2, y: 3},
                {x: -2, y: 4},
                {x: -2, y: 5},
                {x: -3, y: 4}
            ],
        degree0_90: [
                    {x: -2, y: 1},
                    {x: -1, y: 0},
                    {x: 0, y: -1},
                    {x: 0, y: 1}
                ],
        degree90_180: [
                    {x: 1, y: 2},
                    {x: 0, y: 1},
                    {x: -1, y: 0},
                    {x: 1, y: 0}
                ],
        degree180_270: [
                    {x: 2, y: -1},
                    {x: 1, y: 0},
                    {x: 0, y: 1},
                    {x: 0, y: -1}
                ],
        degree270_360: [
                    {x: -1, y: -2},
                    {x: 0, y: -1},
                    {x: 1, y: 0},
                    {x: -1, y: 0}
                ]
    },

    /**
    *     ####
    *     ####
    *方块
    **/

    Square : {
        init: [
                {x: -2, y: 4},
                {x: -2, y: 5},
                {x: -3, y: 4},
                {x: -3, y: 5}
            ],
        degree0_90: [
                    {x: 0, y: 0},
                    {x: 0, y: 0},
                    {x: 0, y: 0},
                    {x: 0, y: 0}
                ],
        degree90_180: [
                    {x: 0, y: 0},
                    {x: 0, y: 0},
                    {x: 0, y: 0},
                    {x: 0, y: 0}
                ],
        degree180_270: [
                    {x: 0, y: 0},
                    {x: 0, y: 0},
                    {x: 0, y: 0},
                    {x: 0, y: 0}
                ],
        degree270_360: [
                    {x: 0, y: 0},
                    {x: 0, y: 0},
                    {x: 0, y: 0},
                    {x: 0, y: 0}
                ]
    },

    /**
    *     ####
    *       ####
    *左移块
    **/

    LSquare : {
        init: [
                {x: -2, y: 4},
                {x: -2, y: 5},
                {x: -3, y: 3},
                {x: -3, y: 4}
            ],
        degree0_90: [
                    {x: -1, y: 0},
                    {x: 0, y: -1},
                    {x: -1, y: 2},
                    {x: 0, y: 1}
                ],
        degree90_180: [
                    {x: 1, y: 2},
                    {x: 0, y: 1},
                    {x: 1, y: 0},
                    {x: 0, y: -1}
                ],
        degree180_270: [
                    {x: 1, y: -2},
                    {x: 0, y: -1},
                    {x: 1, y: 0},
                    {x: 0, y: 1}
                ],
        degree270_360: [
                    {x: -1, y: 0},
                    {x: 0, y: 1},
                    {x: -1, y: -2},
                    {x: 0, y: -1}
                ]
    },

    /**
    *       ####
    *     ####
    *右移块
    **/

    RSquare : {
        init: [
                {x: -2, y: 4},
                {x: -2, y: 5},
                {x: -3, y: 5},
                {x: -3, y: 6}
            ],
        degree0_90: [
                    {x: -1, y: 0},
                    {x: 0, y: -1},
                    {x: 1, y: 0},
                    {x: 2, y: -1}
                ],
        degree90_180: [
                    {x: 0, y: 1},
                    {x: -1, y: 0},
                    {x: 0, y: -1},
                    {x: -1, y: -2}
                ],
        degree180_270: [
                    {x: 1, y: 0},
                    {x: 0, y: 1},
                    {x: -1, y: 0},
                    {x: -2, y: 1}
                ],
        degree270_360: [
                    {x: 0, y: -1},
                    {x: 1, y: 0},
                    {x: 0, y: 1},
                    {x: 1, y: 2}
                ]
    }
};

4、game.js


function Game(rows, verticals) {
    this.rows = rows;
    this.verticals = verticals;
    this.tds = [];
    this.init();
}
Game.prototype = {
    constructor: Game,
    init: function() {
        var table= document.getElementsByTagName('table')[0];
        for(var i = 0; i < this.rows; i++) {
            var tr = document.createElement('tr');
            var tdsTr = [];
            for(var j = 0;j < this.verticals; j++) {
                var td = document.createElement('td');
                tr.appendChild(td);
                tdsTr.push(td);
            };
            table.appendChild(tr);
            this.tds.push(tdsTr);
        };
    },
    render: function(array) {
        var self = this;
        if(!util.isType(array, "array")) {
            console.log('game render data must be array');
            return;
        };
        for(var i = 0;i < self.tds.length;i++) {
            for(var j = 0;j < self.tds[i].length;j++) {
                self.tds[i][j].style.background = '';
            }
        };
        for(var i = 0;i < array.length; i++) {
            if(self.tds[array[i].x] && self.tds[array[i].x][array[i].y]) {
                self.tds[array[i].x][array[i].y].style.background = '#999999';
            }
        };
    }
}

5、block.js

;
var square = {};
Object.keys(data).forEach(function(obj) {
    square[obj] = function(speed) {
        this.speed = speed;
        this.body = copy(data[obj]['init'],"deep");
        this.degree0_90 = data[obj]["degree0_90"];
        this.degree90_180 = data[obj]["degree90_180"];
        this.degree180_270 = data[obj]["degree180_270"];
        this.degree270_360 = data[obj]["degree270_360"];
        this.preBody = '';
        this.move = '';
        this.state = 0;
        this.init();
    };
    square[obj].prototype = {
        constructor: square[obj],
        init: function() {
            var self = this;
            self.move = setInterval(function() {
                self.down();
            }, self.speed);
        },
        down: function() {
            var self = this;
            self.preBody = copy(self.body,"deep");
            self.body[0]["x"]  += 1;
            self.body[1]["x"]  += 1;
            self.body[2]["x"]  += 1;
            self.body[3]["x"]  += 1;
            // console.log('self.body');
            // console.log(self.body);
        },
        rotate: function() {
            var self = this;
            self.body[0]["x"] += self['degree'+self.state+'_'+(self.state+90)][0]["x"];
            self.body[0]["y"] += self['degree'+self.state+'_'+(self.state+90)][0]["y"];
            self.body[1]["x"] += self['degree'+self.state+'_'+(self.state+90)][1]["x"];
            self.body[1]["y"] += self['degree'+self.state+'_'+(self.state+90)][1]["y"];
            self.body[2]["x"] += self['degree'+self.state+'_'+(self.state+90)][2]["x"];
            self.body[2]["y"] += self['degree'+self.state+'_'+(self.state+90)][2]["y"];
            self.body[3]["x"] += self['degree'+self.state+'_'+(self.state+90)][3]["x"];
            self.body[3]["y"] += self['degree'+self.state+'_'+(self.state+90)][3]["y"];
            self.state = self.state == 270 ? 0 : self.state + 90;
        }
    }
});

kalakalaxyz
123 声望6 粉丝