用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>

原文地址:http://blog.51cto.com/steed/2129105

时间: 2024-11-08 22:38:49

用JS实现的俄罗斯方块的相关文章

HTML+JS版本的俄罗斯方块

<!doctype html><html><head></head><body> <div id="box" style="width:252px;font:25px/25px 宋体;background:#000;color:#9f9;border:#999 20px ridge;text-shadow:2px 3px 1px #0f0;"></div> <script>

JS 写的俄罗斯方块游戏

http://www.htmleaf.com/html5/html5youxi/201501201236.html https://github.com/Aerolab/blockrain.js/blob/gh-pages/src/blockrain.jquery.src.js <!doctype html> <html lang="zh"> <meta charset="UTF-8"> <link rel="st

JS编写的俄罗斯方块

IEEE Spectrum 杂志发布了一年一度的编程语言排行榜,这也是他们发布的第四届编程语言 Top 榜. 据介绍,IEEE Spectrum 的排序是来自 10 个重要线上数据源的综合,例如 Stack Overflow.Twitter.Reddit.IEEE Xplore.GitHub.CareerBuilder 等,对 48 种语言进行排行. 与其他排行榜不同的是,IEEE Spectrum 可以让读者自己选择参数组合时的权重,得到不同的排序结果.考虑到典型的 Spectrum 读者需求

CSS+js打造的网页版俄罗斯方块游戏

<HTML> <SCRIPT> parent.moveTo((screen.width-775)/2,(screen.height-540)/2); parent.resizeTo(775,540) </SCRIPT> <HEAD> <META NAME="Title" CONTENT="JScript Simple Tetris"> <TITLE>CSS+js打造的网页版俄罗斯方块游戏丨石家庄

js俄罗斯方块

<html> <style>.c {margin :1px;width:19px;height:19px;background:red;position:absolute;} .d {margin :1px;width:19px;height:19px;background:gray;position:absolute;} .f {top:0px;left:0px;background:black;position:absolute;} </style> <bod

用纯JS做俄罗斯方块 - 简要思路介绍(1)

大家都知道俄罗斯方块是一款大众化的游戏了,我很小的时候就玩过,今年已经25岁了,可以说俄罗斯方块确实是历史悠久,做俄罗斯方块是我上个星期开始的想法.也许是由于自己从来没有写过这种东西吧,所以有生疏.代码的话,只完成了一小部分,大概1/5左右吧.今天还是决定先写一部分思路. 至于俄罗斯方块的话,有很多的难点,如果有JS去写的话,要考虑到碰撞啊,边界啊,下落等问题,本文这些问题大部分不会考虑到,只是提供一部分思路而已,开始已经说了,因为自己还没写完这个游戏,但是又出于想写博客记录,所以才有了这一系列

js 俄罗斯方块

纯JS实现俄罗斯方块,打造属于你的游戏帝国 纯JS俄罗斯方块,打造属于你的游戏帝国. 本文原始作者博客 http://www.cnblogs.com/toutou 俄罗斯方块(Tetris, 俄文:Тетрис)是一款电视游戏机和掌上游戏机游戏,它由俄罗斯人阿列克谢·帕基特诺夫发明,故得此名.俄罗斯方块的基本规则是移动.旋转和摆放游戏自动输出的各种方块,使之排列成完整的一行或多行并且消除得分.由于上手简单.老少皆宜,从而家喻户晓,风靡世界.那么,我们的问题来了,学挖掘机技术哪家强? 俄罗斯方块可

JS实现——俄罗斯方块

把以下代码保存成Tetris.html文件,使用Google或360浏览器打开 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 4.0 Transitional//EN"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta name="charset-8"/> <title> new doc

js实现一款俄罗斯方块

代码下载地址:https://gitee.com/luckiness/jsGame/blob/master/tetris.html 可在移动端和PC端运行,效果如下图. 玩法:拖动下方的形状到方框内,填满一行或一列可消除,消除一行或一列得一分.当方框内无法放置下方的形状时,结束,可开始新一轮. 原文地址:https://blog.51cto.com/7266799/2440892