回归前端学习第23天-实现俄罗斯方块小游戏6(实现单机版2——键盘控制方块移动)

调整代码结构

首先调整代码结构,建立JS文件,如图
在这里插入图片描述
在这里插入图片描述

实现键盘控制方块移动

game.js中代码

var Game = function () {
    //dom元素
    var gameDiv;
    var nextDiv;
    // 游戏矩阵
    var gameData = [
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 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 cur;
    // 下一个方块
    var next;
    // divs
    var nextDivs = [];
    var gameDivs = [];
    // 初始化div
    var initDiv = function (container, data, divs) {
        for (var i = 0; i < data.length; i++) {
            var div = [];
            for (var j = 0; j < data[0].length; j++) {
                var newNode = document.createElement('div');
                newNode.className = 'none';
                newNode.style.top = (i * 20) + 'px';
                newNode.style.left = (j * 20) + 'px';
                // 建立一维数组
                container.appendChild(newNode);
                div.push(newNode);
            }
            // 把一维数组放到多维数组中
            divs.push(div);
        }
    }

    // 刷新div
    var refreshDiv = function (data, divs) {
        for (var i = 0; i < data.length; i++) {
            for (var j = 0; j < data[0].length; j++) {
                if (data[i][j] == 0) {
                    divs[i][j].className = 'none';
                } else if (data[i][j] == 1) {
                    divs[i][j].className = 'done';
                } else if (data[i][j] == 2) {
                    divs[i][j].className = 'current';
                }
            }
        }
    }
    // 检测点是否合法,即是否降落到最底部——pos为方块原点位置,x=cur.origin.x,y=cur.origin.y,
    var check = function (pos, x, y) {
        if (pos.x + x < 0) {
            // 超出上面
            return false;
        } else if (pos.x + x >= gameData.length) {
            // 超出下面
            return false;
        } else if (pos.y + y < 0) {
            // 到最左边
            return false;
        } else if (gameData[pos.x + x][pos.y + y] == 1) {
            // 已经有落下来的方块了
            return false;
        } else {
            return true;
        }

    }
    // 检测数据是否合法,pos为原点,data为每次下降的方块的数据,为有方块存在的数据下降操作时做准备
    var isValid = function (pos, data) {
        for (var i = 0; i < data.length; i++) {
            for (j = 0; j < data[0].length; j++) {
                if (data[i][j] != 0) {
                    if (!check(pos, i, j)) {
                        // 不等于0且非法
                        return false;
                    }
                }
            }
        }
        return true;
    }
    // 清除数据
    var clearData = function () {
        for (var i = 0; i < cur.data.length; i++) {
            if (check(cur.origin, i, j)) {
                for (var j = 0; j < cur.data[0].length; j++) {
                    gameData[cur.origin.x + i][cur.origin.y + j] = 0;
                }
            }
        }
    }
    // 设置数据
    var setData = function () {
        for (var i = 0; i < cur.data.length; i++) {
            for (var j = 0; j < cur.data[0].length; j++) {
                // 先判断是否合法
                if (check(cur.origin, i, j)) {
                    // 将cur.data[i][j]中的数据拷贝到gameData数组中
                    gameData[cur.origin.x + i][cur.origin.y + j] = cur.data[i][j];
                }
            }
        }
    }
    // 下移设置
    var down = function () {
        // 判断是否可以下降,方法写在square中
        if (cur.canDown(isValid)) {
            clearData();
            cur.down();
            setData();
            refreshDiv(gameData, gameDivs);
            return true;
        } else {
            // 不能再向下
            return false;
        }
    }
    // 旋转设置
    var rotate = function () {
        // 判断是否可以下降,方法写在square中
        if (cur.canRotate(isValid)) {
            clearData();
            cur.rotate();
            setData();
            refreshDiv(gameData, gameDivs);
        }
    }

    // 左移设置
    var left = function () {
        // 判断是否可以下降,方法写在square中
        if (cur.canLeft(isValid)) {
            clearData();
            cur.left();
            setData();
            refreshDiv(gameData, gameDivs);
        }
    }
    // 右移设置
    var right = function () {
        // 判断是否可以下降,方法写在square中
        if (cur.canRight(isValid)) {
            clearData();
            cur.right();
            setData();
            refreshDiv(gameData, gameDivs);
        }
    }
    // 初始化 doms对象包含两个内容gameDiv、nextDiv
    var init = function (doms) {
        gameDiv = doms.gameDiv;
        nextDiv = doms.nextDiv;
         let square = new SquareFactory();
        cur = square.make(2, 2);
        next = square.make(3, 3);
        setData();
        initDiv(gameDiv, gameData, gameDivs);
        initDiv(nextDiv, next.data, nextDivs);

        // 调用封装函数,将cur.data[i][j]中的数据拷贝到gameData数组中
        setData();
        refreshDiv(gameData, gameDivs);
        refreshDiv(next.data, nextDivs);
    }
    // 导出API,在外部local里就可以调用这个init函数了
    this.init = init;
    this.down = down;
    this.left = left;
    this.right = right;
    this.rotate = rotate;
    this.fall = function () {
        // 返回false就不能再下降
        while (down());
    }
}

注意这里在SquareFactory中又写了个make函数,所以在game.js调用的时候,需要先new一个实例,否则会出现未定义的情况

在这里插入图片描述

square.js中代码

var Square = function () {
    // 方块数据
    this.data = [
        [0, 0, 0, 0],
        [0, 0, 0, 0],
        [0, 0, 0, 0],
        [0, 0, 0, 0]
    ];
    // 原点对象
    this.origin = {
        x: 0,
        y: 0
    }
    // 方向,即旋转中的索引
    this.dir = 0;
}
// 判断是否可以旋转
Square.prototype.canRotate = function (isValid) {
    var d = (this.dir + 1) % 4;
    var test = [
        [0, 0, 0, 0],
        [0, 0, 0, 0],
        [0, 0, 0, 0],
        [0, 0, 0, 0]
    ];
    for (var i = 0; i < this.data.length; i++) {
        for (var j = 0; j < this.data[0].length; j++) {
            test[i][j] = this.rotates[d][i][j];
        }
    }
    return isValid(this.origin, test);
}
Square.prototype.rotate = function (num) {
    if (!num) num = 1;
    this.dir = (this.dir + num) % 4;
    for (var i = 0; i < this.data.length; i++) {
        for (var j = 0; j < this.data[0].length; j++) {
            this.data[i][j] = this.rotates[this.dir][i][j];
        }
    }
}
// 判断是否可以下降
Square.prototype.canDown = function (isValid) {
    var test = {};
    test.x = this.origin.x + 1;
    test.y = this.origin.y;
    return isValid(test, this.data);
}
Square.prototype.down = function () {
    this.origin.x = this.origin.x + 1;
}
// 判断是否可以左移
Square.prototype.canLeft = function (isValid) {
    var test = {};
    test.x = this.origin.x;
    test.y = this.origin.y - 1;
    return isValid(test, this.data);
}
Square.prototype.left = function () {
    this.origin.y = this.origin.y - 1;
}
// 判断是否可以右移
Square.prototype.canRight = function (isValid) {
    var test = {};
    test.x = this.origin.x;
    test.y = this.origin.y + 1;
    return isValid(test, this.data);
}
Square.prototype.right = function () {
    this.origin.y = this.origin.y + 1;
}

squareFactory.js中代码

var Square1 = function () {
    // 调用Square方法
    Square.call(this);
    // 旋转数组,枚举可能的情况 其中每个元素都是二维数组
    this.rotates = [
        [
            [0, 2, 0, 0],
            [2, 2, 2, 0],
            [0, 0, 0, 0],
            [0, 0, 0, 0]
        ],
        [
            [2, 0, 0, 0],
            [2, 2, 0, 0],
            [2, 0, 0, 0],
            [0, 0, 0, 0]
        ],
        [
            [2, 2, 2, 0],
            [0, 2, 0, 0],
            [0, 0, 0, 0],
            [0, 0, 0, 0]
        ],
        [
            [0, 2, 0, 0],
            [2, 2, 0, 0],
            [0, 2, 0, 0],
            [0, 0, 0, 0]
        ],
    ]
}
// 省去代码
Square1.prototype = Square.prototype;

var Square2 = function () {
    // 调用Square方法
    Square.call(this);
    // 旋转数组,枚举可能的情况 其中每个元素都是二维数组
    this.rotates = [
        [
            [0, 2, 0, 0],
            [0, 2, 0, 0],
            [0, 2, 0, 0],
            [0, 2, 0, 0]
        ],
        [
            [0, 0, 0, 0],
            [2, 2, 2, 2],
            [0, 0, 0, 0],
            [0, 0, 0, 0]
        ],
        [
            [0, 2, 0, 0],
            [0, 2, 0, 0],
            [0, 2, 0, 0],
            [0, 2, 0, 0]
        ],
        [
            [0, 0, 0, 0],
            [2, 2, 2, 2],
            [0, 0, 0, 0],
            [0, 0, 0, 0]
        ],
    ]
}
// 判断是否可以旋转
Square2.prototype = Square.prototype;

var Square3 = function () {
    // 调用Square方法
    Square.call(this);
    // 旋转数组,枚举可能的情况 其中每个元素都是二维数组
    this.rotates = [
        [
            [2, 2, 2, 0],
            [0, 0, 2, 0],
            [0, 0, 0, 0],
            [0, 0, 0, 0]
        ],
        [
            [0, 2, 0, 0],
            [0, 2, 0, 0],
            [2, 2, 0, 0],
            [0, 0, 0, 0]
        ],
        [
            [2, 0, 0, 0],
            [2, 2, 2, 0],
            [0, 0, 0, 0],
            [0, 0, 0, 0]
        ],
        [
            [2, 2, 0, 0],
            [2, 0, 0, 0],
            [2, 0, 0, 0],
            [0, 0, 0, 0]
        ],
    ]
}
// 判断是否可以旋转
Square3.prototype = Square.prototype;


var Square4 = function () {
    // 调用Square方法
    Square.call(this);
    // 旋转数组,枚举可能的情况 其中每个元素都是二维数组
    this.rotates = [
        [
            [2, 2, 2, 0],
            [2, 0, 0, 0],
            [0, 0, 0, 0],
            [0, 0, 0, 0]
        ],
        [
            [2, 2, 0, 0],
            [0, 2, 0, 0],
            [0, 2, 0, 0],
            [0, 0, 0, 0]
        ],
        [
            [0, 0, 2, 0],
            [2, 2, 2, 0],
            [0, 0, 0, 0],
            [0, 0, 0, 0]
        ],
        [
            [2, 0, 0, 0],
            [2, 0, 0, 0],
            [2, 2, 0, 0],
            [0, 0, 0, 0]
        ],
    ]
}
// 判断是否可以旋转
Square4.prototype = Square.prototype;

var Square5 = function () {
    // 调用Square方法
    Square.call(this);
    // 旋转数组,枚举可能的情况 其中每个元素都是二维数组
    this.rotates = [
        [
            [2, 2, 0, 0],
            [2, 2, 0, 0],
            [0, 0, 0, 0],
            [0, 0, 0, 0]
        ],
        [
            [2, 2, 0, 0],
            [2, 2, 0, 0],
            [0, 0, 0, 0],
            [0, 0, 0, 0]
        ],
        [
            [2, 2, 0, 0],
            [2, 2, 0, 0],
            [0, 0, 0, 0],
            [0, 0, 0, 0]
        ],
        [
            [2, 2, 0, 0],
            [2, 2, 0, 0],
            [0, 0, 0, 0],
            [0, 0, 0, 0]
        ],
    ]
}
// 判断是否可以旋转
Square5.prototype = Square.prototype;

var Square6 = function () {
    // 调用Square方法
    Square.call(this);
    // 旋转数组,枚举可能的情况 其中每个元素都是二维数组
    this.rotates = [
        [
            [0, 2, 2, 0],
            [2, 2, 0, 0],
            [0, 0, 0, 0],
            [0, 0, 0, 0]
        ],
        [
            [2, 0, 0, 0],
            [2, 2, 0, 0],
            [0, 2, 0, 0],
            [0, 0, 0, 0]
        ],
        [
            [0, 2, 2, 0],
            [2, 2, 0, 0],
            [0, 0, 0, 0],
            [0, 0, 0, 0]
        ],
        [
            [2, 0, 0, 0],
            [2, 2, 0, 0],
            [0, 2, 0, 0],
            [0, 0, 0, 0]
        ],
    ]
}
// 判断是否可以旋转
Square6.prototype = Square.prototype;

var Square7 = function () {
    // 调用Square方法
    Square.call(this);
    // 旋转数组,枚举可能的情况 其中每个元素都是二维数组
    this.rotates = [
        [
            [2, 2, 2, 0],
            [2, 2, 2, 0],
            [0, 0, 0, 0],
            [0, 0, 0, 0]
        ],
        [
            [2, 2, 0, 0],
            [2, 2, 0, 0],
            [2, 2, 0, 0],
            [0, 0, 0, 0]
        ],
        [
            [2, 2, 2, 0],
            [2, 2, 2, 0],
            [0, 0, 0, 0],
            [0, 0, 0, 0]
        ],
        [
            [2, 2, 0, 0],
            [2, 2, 0, 0],
            [2, 2, 0, 0],
            [0, 0, 0, 0]
        ],
    ]
}
// 判断是否可以旋转
Square7.prototype = Square.prototype;

var SquareFactory = function () {
    SquareFactory.prototype.make = function (index, dir) {
        var s;
        index = index + 1;
        switch (index) {
            case 1:
                s = new Square1();
                break;
            case 2:
                s = new Square2();
                break;
            case 3:
                s = new Square3();
                break;
            case 4:
                s = new Square4();
                break;
            case 5:
                s = new Square5();
                break;
            case 6:
                s = new Square6();
                break;
            case 7:
                s = new Square7();
                break;
            default:
                break;
        }
        // 定义原点
        s.origin.x = 0;
        s.origin.y = 3;
        s.rotate(dir);
        return s;
    }
}

local.js代码

var Local = function () {
    // 游戏对象
    var game;
    // 绑定键盘事件
    var bindKeyEvent = function () {
        document.onkeydown = function (e) {
            if (e.keyCode == 38) {
                // 向上
                game.rotate();
            } else if (e.keyCode == 39) {
                // 向右
                game.right();
            } else if (e.keyCode == 40) {
                // 向下
                game.down();
            } else if (e.keyCode == 37) {
                // 向左
                game.left();
            } else if (e.keyCode == 32) {
                // 空格键
                game.fall();
            }
        }
    }
    // 开始
    var start = function () {
        var doms = {
            gameDiv: document.getElementById('game'),
            nextDiv: document.getElementById('next')
        }
        game = new Game();
        game.init(doms);
        bindKeyEvent();
    }
    // 导出API
    this.start = start;
}

script.js代码

 // 创建local对象并调用
    var local = new Local();
    local.start();

实现效果

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值