俄罗斯方块(table+setInterval)

96 阅读1分钟

实现一个简易的俄罗斯方块

index.html

<!--

 * @Author: zhouwenbo 2660841146@qq.com

 * @Date: 2023-02-03 20:17:29

 * @LastEditors: zhouwenbo 2660841146@qq.com

 * @LastEditTime: 2023-02-05 19:34:54

 * @FilePath: \俄罗斯方块\index.html

 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE

-->

<!--

    主要思路:

    使用定时器,每秒渲染一次

    更新分数

    清空路径

    渲染单元格和预览单元格

    渲染地图

    判断下落

        若单元格停止

        判断游戏状态

        重新初始化下落时间

        判断消行

 -->

<!DOCTYPE html>

<html lang="en">

  


<head>

    <meta charset="UTF-8">

    <meta http-equiv="X-UA-Compatible" content="IE=edge">

    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <title>Document</title>

    <style>

        * {

            margin: 0;

            padding: 0;

        }

  


        body {

            overflow: hidden;

            height: 100%;

            padding-top: 20px;

            padding-left: 50px;

        }

  


        table {

            border-collapse: collapse;

            /*合并边框*/

            margin: 0 auto;

            float: left;

            margin-right: 20px;

        }

  


        td {

            border: 1px solid black;

            width: 25px;

            height: 25px;

        }

  


        .c1 {

            background: blue;

        }

    </style>

</head>

  


<body>

    <div>

        <div>

            <span onclick='start()'>Start Game</span>

            <span id='score' style="padding-left: 160px;">积分:0</span>

            <span style="padding-left: 20px;">Next</span>

        </div>

        <div id="tableDiv">

  


        </div>

    </div>

  


    <script src="js/jquery.min.js"></script>

    <script src="js/cellThreeList.js"></script>

    <script>

        // let button = $("<button onclick='start()'>开始</button>");

        // let span = $("<span id='score'>分数:0</span>");

        // $(button).appendTo("body")

        // $(span).appendTo("body")

        //初始化地图

        let table = $("<table></table>");

        table.addClass('tab1');

        //渲染表格

        for (let i = 0; i < 20; i++) {

            let tr = $("<tr></tr>")

            for (let j = 0; j < 12; j++) {

                let td = $("<td></td>")

                td.appendTo(tr);

            }

            tr.appendTo(table);

        }

        //初始化预览窗口

        let table2 = $("<table></table>");

        table2.addClass('tab2');

        for (let i = 0; i < 3; i++) {

            let tr = $("<tr></tr>")

            for (let j = 0; j < 3; j++) {

                let td = $("<td></td>")

                td.appendTo(tr);

            }

            tr.appendTo(table2);

        }

        $(table).appendTo("#tableDiv")

        $(table2).appendTo("#tableDiv")

        let game

        function start() {

            game = new Game();

        }

  


        //主控制函数

        //下落速度

        window.constTimer = 1000;

        function Game() {

  


            //设置行和列

            this.row = 20;

            this.col = 12;

            //实例化单元格

            this.cells = new Cells();

            //实例化下一个block

            this.nextBlock = new Cells();

            //实例化地图

            this.map = new TableMap();

            //启动定时器

            this.start(window.constTimer);

            //事件监听

            this.bindEvent();

            //分数

            this.score = 0;

        }

        //清屏功能

        Game.prototype.clear = function () {

            for (let i = 0; i < this.row; i++) {

                for (let j = 0; j < this.col; j++) {

                    $(".tab1").find("tr").eq(i).children("td").eq(j).removeClass();

                }

            }

            for (let i = 0; i < 3; i++) {

                for (let j = 0; j < 3; j++) {

                    $(".tab2").find("tr").eq(i).children("td").eq(j).removeClass();

                }

            }

        }

        Game.prototype.setColor = function (row, col, num) {

            // debugger;

            //给对应单元格上色

            $(".tab1").find("tr").eq(row).children("td").eq(col).addClass("c" + num)

        }

        //渲染下一个单元格的颜色

        Game.prototype.setNextColor = function (row, col, num) {

            // debugger;

            //给对应单元格上色

            for (let i = 0; i < 3; i++) {

                for (let j = 0; j < 3; j++) {

                    if (this.nextBlock.code[i][j] != 0) {

                        $(".tab2").find("tr").eq(i).children("td").eq(j).addClass("c" + this.nextBlock.code[i][j])

                    }

                }

            }

        }

        Game.prototype.bindEvent = function () {

            //备份

            // debugger

            let self = this;

            $(document).keydown(function (event) {

                // console.log(event.keyCode);

                if (event.keyCode == 65) {

                    //判断是否可以向左移动

                    debugger

                    self.cells.checkLeft()

                }

                else if (event.keyCode == 68) {

                    //判断是否可以向右移动

                    self.cells.checkRight()

                }

                else if (event.keyCode == 83) {

                    // debugger

                    //加快下落速度

                    window.constTimer = 250;

                    // window.boolResive = false;

                    clearInterval(self.timer);

                    self.start(window.constTimer);

                }

                else if (event.keyCode == 87) {

                    self.cells.rotate();

                }

            })

        }

        Game.prototype.start = function (constTimer) {

            let self = this;

            this.timer = setInterval(function () {

                //渲染分数

                $("#score").html(`积分:${self.score}`);

                //清屏

                self.clear();

                //渲染单元格

                self.cells.render();

                //渲染预览单元格

                self.setNextColor();

                //渲染地图

                self.map.render();

                //下落

                self.cells.checkDown();

            }, constTimer)

        }

  


        //单元格控制

        //矩阵行

        const constRow = 3;

        //矩阵列

        const constCol = 3;

        function Cells() {

            // this.cells = [

            //     [0,1,0],

            //     [0,1,0],

            //     [0,1,0]

            // ]

            //罗列所有的类型

            let allType = ["L", "C", "O"]

            //随机出一种类型,得到一个随机小数,乘以长度取整后得到随机的状态

            this.type = allType[parseInt(Math.random() * allType.length)];

            // console.log(this.type);

            //获取当前类型的形状的数量(PS:不同的的类型形状数量不同)

            this.allDir = cellsAll[this.type].length;

            this.dir = parseInt(Math.random() * this.allDir);

            this.code = cellsAll[this.type][this.dir]

            //初始的行

            this.row = 0;

            //初始的列

            this.col = 5;

        }

        Cells.prototype.render = function () {

            // debugger;

            //渲染单元格

            for (let i = 0; i < constRow; i++) {

                for (let j = 0; j < constCol; j++) {

                    //如果矩阵中不为零的单元格需要有颜色

                    if (this.code[i][j] != 0) {

                        game.setColor(i + this.row, j + this.col, this.code[i][j]);

                    }

                }

            }

        }

        Cells.prototype.check = function (row, col) {

            //判断单元格是否与地图重叠

            // debugger

            for (let i = 0; i < constRow; i++) {

                for (let j = 0; j < constCol; j++) {

                    //如果矩阵中不为零的单元格需要有颜色

                    // if(i+row>19){

                    //     return false;

                    // }

                    if (this.code[i][j] != 0 && game.map.mapCode[i + row][j + col] != 0) {

                        return false;

                    }

                }

            }

            return true;

        };

        //判断当前单元格是否能过够下落

        Cells.prototype.checkDown = function () {

            //判断地图和单元格是否重叠,this.row+1指的是预判断

            if (this.check(this.row + 1, this.col)) {

                this.row++;

            } else {

                //此时单元格停止

                //将下一个单元格渲染到本次

                game.cells = game.nextBlock;

                //重新渲染预览框的单元格

                game.nextBlock = new Cells();

                // window.boolResive = true;

                //将单元格渲染到地图上

                this.renderMap();

                //重置刷新时间(新单元格回到原来的下落速度)

                window.constTimer = 1000;

                clearInterval(game.timer);

                game.start(window.constTimer);

                //判断消行

                game.map.checkRemove()

                //判断游戏是否结束

                this.gameOver()

            }

        }

        //判断单元格是否可以向左移动

        Cells.prototype.checkLeft = function () {

            //判断是否可以向左

            // debugger

            if (this.check(this.row, this.col - 1)) {

                this.col--;

            }

        }

        //判断单元格是否可以向右移动

        Cells.prototype.checkRight = function () {

            //判断是否可以向右

            if (this.check(this.row, this.col + 1)) {

                this.col++;

            }

        }

        //旋转方法

        Cells.prototype.rotate = function () {

            //保存旧形状的方向

            let oldDir = this.dir;

            //改变新的形状

            this.dir++;

            //判断如果索引值越位,重新初始化形状数值

            if (this.dir > this.allDir - 1) {

                this.dir = 0;

            }

            //渲染新的形状

            this.code = cellsAll[this.type][this.dir];

            //判断单元格是否可以旋转

            if (!this.check(this.row, this.col)) {

                //与地图重合,回到旧的形状

                this.dir = oldDir;

                //再次渲染单元格

                this.code = cellsAll[this.type][this.dir];

            }

        }

        //降落落地的单元格渲染到地图中

        Cells.prototype.renderMap = function () {

            for (let i = 0; i < constRow; i++) {

                for (let j = 0; j < constCol; j++) {

                    if (this.code[i][j] != 0) {

                        //改变地图数据

                        game.map.mapCode[this.row + i][this.col + j] = this.code[i][j];

                    }

  


                }

            }

        }

        //检查游戏是否结束

        Cells.prototype.gameOver = function () {

            for (let i = 0; i < game.col; i++) {

                //检查地图数组的第一行,若有不为零的项则游戏终止

                if (game.map.mapCode[0][i] != 0) {

                    clearInterval(game.timer);

                    alert("游戏结束," + $("#score").text());

                }

            }

        }

        //表格地图控制

        function TableMap() {

            this.mapCode = [

                [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, 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],

                [9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9]

            ]

            //地图的行列数

            this.maprow = 20;

            this.mapcol = 12;

        }

        //持久化地图

        TableMap.prototype.render = function () {

            // debugger;

            //渲染单元格

            for (let i = 0; i < this.maprow; i++) {

                for (let j = 0; j < this.mapcol; j++) {

                    //如果矩阵中不为零的单元格需要有颜色

                    if (this.mapCode[i][j] != 0) {

                        game.setColor(i, j, this.mapCode[i][j])

                    }

                }

            }

        }

        //地图消行

        TableMap.prototype.checkRemove = function () {

            //判断map行,全是0的话消除

            for (let i = 0; i < this.maprow; i++) {

                if (this.mapCode[i].indexOf(0) == -1) {

                    //删除一行

                    this.mapCode.splice(i, 1);

                    //头部添加一行

                    this.mapCode.unshift([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);

                    //分数增加

                    game.score++;

                }

            }

        }

// setInterval(function(){

//     if(window.boolResive){

//         game.start(window.constTimer);

//     }

// },1)

    </script>

</body>

  


</html>

cellThreeList.js

let cellsAll = {

    "L":[

        [

            [0,1,0],

            [0,1,0],

            [0,1,0]

        ],

        [

            [1,1,1],

            [0,0,0],

            [0,0,0]

        ]

    ],

    "C":[

        [

            [1,1,0],

            [1,0,0],

            [0,0,0]

        ],

        [

            [1,0,0],

            [1,1,0],

            [0,0,0]

        ],

        [

            [0,1,0],

            [1,1,0],

            [0,0,0]

        ],

        [

            [1,1,0],

            [0,1,0],

            [0,0,0]

        ]

    ],

    "O":[

        [

            [1,1,0],

            [1,1,0],

            [0,0,0]

        ]

    ]

}