手记

用JS实现的俄罗斯方块

一边练习一下javascript,一边搞的稍微有趣一点。
这次的界面就是个table表格。其实所有的操作只要操作tabel的class就可以了。我这里把颜色直接用 cell.style.backgroundColor 来设置内联样式的属性了。
完整代码如下,预先显示下一个方块的功能没做。Game Over也没有写。

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>俄罗斯方块</title>    <style>        p.tips {margin-top: 20px; text-align: center;}        table#gameUI {margin: 30px auto;}        td {width: 20px; height: 20px; border: 1px solid red;}        td.wall {background-color: red;}    </style></head><body><p class="tips">按回车开始游戏</p><table id="gameUI"></table></body><script>    // 参数设置    var rows = 22, cells = 14;  // 界面的高度和宽度    // 获取元素    var tab = document.getElementById('gameUI');    var tips = document.getElementsByClassName('tips')[0];    // 设置变量    var control;  // 当前控制的方块    var score = 0;  // 分数    var scoreConf = [100, 200, 300, 350];  // 一次小几行,分数不同    init();    function init() {        // 为了页面时的初始化        createTab();        bindKeyEnter();        // gameStart()    }    function bindKeyEnter() {        // 按下回车处理的事件        document.onkeydown = function (ev) {            if (ev.keyCode===13){                tips.innerHTML ='游戏开始';                document.onkeydown = null;                gameStart();            }        }    }    function gameStart() {        // 开始游戏        bindKeysForGame();        tips.innerHTML = '按 Z 或 X 旋转方块';        control = createSqu();        control.position = [1, 4];  // 添加blocks[0]的位置属性        map(control);        setInterval("move('down')", 500)    }    function createSqu() {        // 创建一个方块        var types = [            {'name': "方块", 'color': 'saddlebrown', 'blocks': [[0, 0], [0, 1], [1, 0], [1, 1]],                'styleIndex': 0, 'styles': [                    [[0, 0], [0, 1], [1, 0], [1, 1]]                ]},            {'name': "7形", 'color': 'green', 'blocks': [[0, 0], [0, 1], [1, 1], [2, 1]],                'styleIndex': 0, 'styles': [                    [[0, 0], [0, 1], [1, 1], [2, 1]],                    [[1, 0], [1, 1], [1, 2], [0, 2]],                    [[0, 0], [1, 0], [2, 0], [2, 1]],                    [[0, 0], [1, 0], [0, 1], [0, 2]]                ]},            {'name': "反7", 'color': 'green', 'blocks': [[0, 0], [0, 1], [1, 0], [2, 0]],                'styleIndex': 0, 'styles': [                    [[0, 0], [0, 1], [1, 0], [2, 0]],                    [[0, 0], [0, 1], [0, 2], [1, 2]],                    [[0, 1], [1, 1], [2, 0], [2, 1]],                    [[0, 0], [1, 0], [1, 1], [1, 2]]                ]},            {'name': "长条", 'color': 'darkorange', 'blocks': [[0, 0], [0, 1], [0, 2], [0, 3]],                'styleIndex': 0, 'styles': [                    [[0, 0], [0, 1], [0, 2], [0, 3]],                    [[0, 0], [1, 0], [2, 0], [3, 0]]                ]},            {'name': "丁字", 'color': 'blue', 'blocks': [[0, 0], [0, 1], [1, 1], [0, 2]],                'styleIndex': 0, 'styles': [                    [[0, 0], [0, 1], [1, 1], [0, 2]],                    [[1, 0], [0, 1], [1, 1], [2, 1]],                    [[1, 0], [1, 1], [0, 1], [1, 2]],                    [[0, 0], [1, 0], [1, 1], [2, 0]]                ]},            {'name': "Z字", 'color': 'gold', 'blocks': [[0, 0], [0, 1], [1, 1], [1, 2]],                'styleIndex': 0, 'styles': [                    [[0, 0], [0, 1], [1, 1], [1, 2]],                    [[0, 1], [1, 0], [1, 1], [2, 0]]                ]},            {'name': "反Z", 'color': 'gold', 'blocks': [[1, 0], [1, 1], [0, 1], [0, 2]],                'styleIndex': 0, 'styles': [                    [[1, 0], [1, 1], [0, 1], [0, 2]],                    [[0, 0], [1, 0], [1, 1], [2, 1]]                ]}        ];        var index = Math.floor(Math.random()*types.length+1);        return types[index-1]    }    function map(square) {        // 把方块画在表格里        var rubber = arguments[1] ? arguments[1] : false;        for (var i=0; i<square.blocks.length; i++) {            var cell = tab.rows[square.blocks[i][0]+square.position[0]].cells[square.blocks[i][1]+square.position[1]];            if (rubber){                cell.style.backgroundColor = '';                cell.classList.remove('control')            } else {                cell.style.backgroundColor = square.color;                cell.classList.add('control')            }        }    }    function fixed(square){        // 固定方块        for (var i=0; i<square.blocks.length; i++) {            var cell = tab.rows[square.blocks[i][0]+square.position[0]].cells[square.blocks[i][1]+square.position[1]];            cell.classList.remove('control');            cell.classList.add('fixed')        }    }    function bindKeysForGame() {        // 游戏时候需要绑定的按键        document.onkeydown = function (ev) {            switch (ev.keyCode) {                case 37:  // 向左                    move('left');                    break;                case 38:  // 向上                    // move('up');                    change();                    break;                case 39:  // 向右                    move('right');                    break;                case 40:  // 向下                    move('down');                    break;                case 90:  // 字母Z                    change(true);                    break;                case 88:  // 字母X                    change();                    break;                // default:                //     tips.innerHTML = ev.keyCode;            }        }    }    function change() {        // 改变形状        var contrarotate = arguments[0] ? arguments[0] : false;        if (contrarotate) {            control.styleIndex -= 1;            if (control.styleIndex < 0) {                control.styleIndex = control.styles.length-1;            }        } else {            control.styleIndex += 1;            if (control.styleIndex > control.styles.length-1){                control.styleIndex = 0;            }        }        var target = [[0,0],[0,0],[0,0],[0,0]];        for (var i=0; i<control.styles[control.styleIndex].length; i++){            target[i][0] = control.styles[control.styleIndex][i][0]+control.position[0];            target[i][1] = control.styles[control.styleIndex][i][1]+control.position[1];        }        if (canMove(target)){            map(control, true);            for (var j=0; j<control.blocks.length; j++){                control.blocks[j][0] = control.styles[control.styleIndex][j][0];                control.blocks[j][1] = control.styles[control.styleIndex][j][1];            }            map(control)        }    }    function move(mode) {        var row, cell;        switch (mode){            case 'left':                row = 0;                cell = -1;                break;            case 'right':                row = 0;                cell = 1;                break;            case 'up':                row = -1;                cell = 0;                break;            case 'down':                row = 1;                cell = 0;                break;        }        var target = [[0,0],[0,0],[0,0],[0,0]];        for (var i=0; i<control.blocks.length; i++){            target[i][0] = control.blocks[i][0]+control.position[0]+row;            target[i][1] = control.blocks[i][1]+control.position[1]+cell;        }        if (canMove(target)){            map(control, true);            control.position[0] += row;            control.position[1] += cell;            map(control)        } else {            if (mode==='down') {                //  向下移动,并且判定为不可移动,则固定                fixed(control);  // 固定住方块                checkAndClean(control);  // 检查消行                control = createSqu();                control.position = [1, 4];  // 添加blocks[0]的位置属性                map(control);            }        }    }    function checkAndClean(square) {        // 检查并消除        var checked = [];        var cleaned = [];        var row;        for (var i=0; i<square.blocks.length; i++){            row = square.blocks[i][0] + square.position[0];            if (checked.indexOf(row) === -1){                checked.push(row);                var needClean = true;                for (var j=1; j<cells-1; j++ ) {                    var cell = tab.rows[row].cells[j];                    if(cell.className.search(/\b(fixed)\b/) === -1){                        needClean = false;                        break;                    }                }                if (needClean) {                    // 消除一行                    cleaned.push(row);                    for (var k=1; k<cells-1; k++) {                        cell = tab.rows[row].cells[k];                        cell.classList.remove('fixed');                        cell.style.backgroundColor = '';                    }                }            }        }        cleaned.length && addScore(cleaned.length) && goDown(cleaned);  // 结算分数,然后下沉    }    function addScore(n) {        n = n<=scoreConf.length ? n : scoreConf[scoreConf.length-1];        score += scoreConf[n-1];        tips.innerHTML = "分数:" + score;        return true    }    function goDown(list) {        // 消行后的沉降        var count = 0;        for (var i=list.length; i--;){            for (var r=list[i]-1; r--;){                tab.rows[r+2+count].innerHTML = tab.rows[r+1+count].innerHTML            }            count += 1;        }    }    function canMove(target) {        // 是否可以移动        for (var j=0; j<target.length; j++){            var cell = tab.rows[target[j][0]].cells[target[j][1]];            if(cell.className.search(/\b(wall|fixed)\b/) > -1){                return false            }        }        return true    }    function createTab() {        // 绘制游戏界面        for (var r=rows; r--;){            var row = tab.insertRow();            for (var c=cells; c--;){                var cell = row.insertCell();                if (r===0 || r===rows-1 || c===0 || c===cells-1){                    cell.classList.add('wall');                }            }        }    }</script></html>

0人推荐
随时随地看视频
慕课网APP