小5聊前端开发经典游戏俄罗斯方块(前端开发领域)

Posted 小5聊

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了小5聊前端开发经典游戏俄罗斯方块(前端开发领域)相关的知识,希望对你有一定的参考价值。

一年一度的博客之星来了,在此通过前端开发方式实现经典游戏俄罗斯方块

俄罗斯方块游戏,大家都玩过,今天就用自己熟悉的jQuery来实现TA

可提供完整源码,如果小伙伴们需要的话(步骤里其实也是完整的源码了)

一、功能分析

1、设置一个高宽度范围

长=20格,宽=10格(标准设置)

2、方块类型

  • 七种类型

O形、I形、S形、Z形、L形、J形、T形 

不管是什么形状,都是由4个小格子拼接而成

  • O形

一种旋转形态

  • I形、S形、Z形

两种形态,就是两种旋转类型

  • L形、J形、T形

四种形态,就是四个旋转方向,上右下左

3、控制方块方向

可以使用键盘的左右下来控制方块的移动方向

4、定时器

通过定时器控制方块向下移动,可以先设置每一秒种向下移动一个单位,比如设置好的30px一个移动单位

5、边界判断

主要有三个边界判断

1)到达底部边界判断

2)到达左右两边边界判断

3)到达某一方块上方边界判断

6、方块旋转

通过left和top移动标志,保持left和top值不变,根据每个形态的每个小方块进行公式计算即可

7、方块消除分析

每个格子都是独立,移动到一定位置后,如果10个小方块都是同在一行,那么就直接对当前行的小方块进行移除即可

二、实现流程

1、页面范围设计

长宽2:1,div高宽设计为600px:300px

  • 代码
<div style="background:#099dff;position:absolute;top:150px;left:50%;height:600px;width:300px;box-shadow:0 0 13px #ccc;margin-left:-150px;">
    <!--游戏面板-->
    <div class="playDiv" style="background: #099dff; position: relative; height: 600px; width: 300px;">

    </div>

    <!--开始按钮-->
    <div class="btnStartDiv" style="position:absolute;top:-45px;left:0px;width:60px;height:35px;line-height:35px;text-align:center;background:#099dff;color:#fff;cursor:pointer;">
        <span>开始</span>
    </div>

    <!--测试-->
    <div class="testDiv" style="position:absolute;top:0px;right:-150px;">
        <div class="one" style="height:35px;line-height:35px;"></div>
        <div class="two" style="height:35px;line-height:35px;"></div>
        <div class="three" style="height:35px;line-height:35px;"></div>
    </div>
</div>

<script type="text/template" id="shapeTemplate">
    <div class="shapeDiv shapeMoveDiv" style="width: 30px;height: 30px;background: #3e3cd0;position:absolute;top:0px;left:0px;">
        <div style="width:100%;height:100%;box-sizing:border-box;border:2px solid #000;"></div>
    </div>
    <div class="shapeDiv shapeMoveDiv" style="width: 30px;height: 30px;background: #3e3cd0;position:absolute;top:0px;left:0px;">
        <div style="width:100%;height:100%;box-sizing:border-box;border:2px solid #000;"></div>
    </div>
    <div class="shapeDiv shapeMoveDiv" style="width: 30px;height: 30px;background: #3e3cd0;position:absolute;top:0px;left:0px;">
        <div style="width:100%;height:100%;box-sizing:border-box;border:2px solid #000;"></div>
    </div>
    <div class="shapeDiv shapeMoveDiv" style="width: 30px;height: 30px;background: #3e3cd0;position:absolute;top:0px;left:0px;">
        <div style="width:100%;height:100%;box-sizing:border-box;border:2px solid #000;"></div>
    </div>
</script>

 2、方块形状设计

上一步骤设计了宽度为300px,那么一个小格子就是30px,并且每个形状都有四个方向的

1)O形

 2)I形

 3)S形

4)Z形

5)L形

 6)J形

7)T形

 

3、全局参数设置

1)方块模板

模板里有4个小方块,然后根据随机以及公式对4个方块进行absolute相对定位,组成一个方块形状以及方块方向

<script type="text/template" id="shapeTemplate">
    <div class="shapeDiv shapeMoveDiv" style="width: 30px;height: 30px;background: #3e3cd0;position:absolute;top:0px;left:0px;">
        <div style="width:100%;height:100%;box-sizing:border-box;border:2px solid #000;"></div>
    </div>
    <div class="shapeDiv shapeMoveDiv" style="width: 30px;height: 30px;background: #3e3cd0;position:absolute;top:0px;left:0px;">
        <div style="width:100%;height:100%;box-sizing:border-box;border:2px solid #000;"></div>
    </div>
    <div class="shapeDiv shapeMoveDiv" style="width: 30px;height: 30px;background: #3e3cd0;position:absolute;top:0px;left:0px;">
        <div style="width:100%;height:100%;box-sizing:border-box;border:2px solid #000;"></div>
    </div>
    <div class="shapeDiv shapeMoveDiv" style="width: 30px;height: 30px;background: #3e3cd0;position:absolute;top:0px;left:0px;">
        <div style="width:100%;height:100%;box-sizing:border-box;border:2px solid #000;"></div>
    </div>
</script>

2)全局变量如下

var shapeUnitPx = 30; //格子单元像素
var leftMaxValue = 30 * 10; //300px,小方块最大的移动宽度
var topMaxValue = 30 * 20; //600px,小方块最大的移动高度

var leftArr = [0, 0, 0, 0]; //单元格的left值(每个方块都有4个小方块)
var topArr = [0, 0, 0, 0]; //单元格的top值(每个方块都有4个小方块)
var nextIndex = 0; //下一个切换方向下标
var currentIndex = 0; //当前小方块下标

var moveLeft = 0; //方块移动的left倍数
var moveTop = 0; //方块移动的top倍数

var htmlTemplate = $("#shapeTemplate").html(); //单元格模板


moveLeft = 5; //每个小方块的left值乘以5
moveTop = -2; //每个小方块的top值乘以-2

4、开始游戏按钮

1)点击开始游戏,默认方块的初始位置为left值的5倍,top的-2倍

2)随机从19种方块里获得1个方块

3)将随机得到的方块下标保存到全局当前方块下标里

4)调用创建方块方法或者移动方块方法

5)同时开启定时器,设置初始状态每隔1秒向下移动一个单元

//===开始===
$(".btnStartDiv").click(function () 

    moveLeft = 5;
    moveTop = -2;

    var shapeIndex = Math.ceil(Math.random() * 19); //1~19随机出现数字
    currentIndex = shapeIndex;

    createShapeOrChangeHtml(shapeIndex);

    moveTime = setInterval(autoMoveShape, 1 * 1000); //开启定时器
);

5、创建方块或移动方块

1)根据方块下标,定位到不同的小方块的left和top值计算公式里

2)设置好方块的4个小方块的left和top值后,即可追加方块到游戏面板里

3)或者修改方块在面板的移动位置

//===生成方块形状===
function createShapeOrChangeHtml(shapeIndex) 

    //方块形状格子叠加原则:从下到上,从左到右
    //这个规则的目的:为消除方块作为基础条件

    //公式创建
    if (shapeIndex == 1)  //O
        nextIndex = 1;

        leftArr[3] = (moveLeft - 1) * shapeUnitPx + shapeUnitPx;
        leftArr[2] = (moveLeft - 1) * shapeUnitPx;
        leftArr[1] = (moveLeft - 1) * shapeUnitPx + shapeUnitPx;
        leftArr[0] = (moveLeft - 1) * shapeUnitPx;

        topArr[3] = (moveTop - 1) * shapeUnitPx;
        topArr[2] = (moveTop - 1) * shapeUnitPx;
        topArr[1] = (moveTop - 1) * shapeUnitPx + shapeUnitPx;
        topArr[0] = (moveTop - 1) * shapeUnitPx + shapeUnitPx;
    
    else if (shapeIndex == 2)  //I - 竖线
        nextIndex = 3;

        leftArr[3] = (moveLeft - 1) * shapeUnitPx;
        leftArr[2] = (moveLeft - 1) * shapeUnitPx;
        leftArr[1] = (moveLeft - 1) * shapeUnitPx;
        leftArr[0] = (moveLeft - 1) * shapeUnitPx;

        topArr[3] = (moveTop - 1) * shapeUnitPx;
        topArr[2] = (moveTop - 1) * shapeUnitPx + shapeUnitPx;
        topArr[1] = (moveTop - 1) * shapeUnitPx + shapeUnitPx * 2;
        topArr[0] = (moveTop - 1) * shapeUnitPx + shapeUnitPx * 3;
    
    else if (shapeIndex == 3)  //I - 横线
        nextIndex = 2;

        leftArr[3] = (moveLeft - 1) * shapeUnitPx;
        leftArr[2] = (moveLeft - 1) * shapeUnitPx + shapeUnitPx;
        leftArr[1] = (moveLeft - 1) * shapeUnitPx + shapeUnitPx * 2;
        leftArr[0] = (moveLeft - 1) * shapeUnitPx + shapeUnitPx * 3;

        topArr[3] = (moveTop - 1) * shapeUnitPx;
        topArr[2] = (moveTop - 1) * shapeUnitPx;
        topArr[1] = (moveTop - 1) * shapeUnitPx;
        topArr[0] = (moveTop - 1) * shapeUnitPx;
    
    else if (shapeIndex == 4)  //S形 - 向右

        /*
            0 30 60
            0   3 4
        30 1 2
        60
            */

        leftArr[3] = (moveLeft - 1) * shapeUnitPx + shapeUnitPx * 2;
        leftArr[2] = (moveLeft - 1) * shapeUnitPx + shapeUnitPx;
        leftArr[1] = (moveLeft - 1) * shapeUnitPx + shapeUnitPx;
        leftArr[0] = (moveLeft - 1) * shapeUnitPx;

        topArr[3] = (moveTop - 1) * shapeUnitPx;
        topArr[2] = (moveTop - 1) * shapeUnitPx;
        topArr[1] = (moveTop - 1) * shapeUnitPx + shapeUnitPx;
        topArr[0] = (moveTop - 1) * shapeUnitPx + shapeUnitPx;

        nextIndex = 5;
    
    else if (shapeIndex == 5)  //S形 - 向下

        /*
            0 30 60
            0 4
        30 2 3
        60   1
            */

        leftArr[3] = (moveLeft - 1) * shapeUnitPx;
        leftArr[2] = (moveLeft - 1) * shapeUnitPx + shapeUnitPx;
        leftArr[1] = (moveLeft - 1) * shapeUnitPx;
        leftArr[0] = (moveLeft - 1) * shapeUnitPx + shapeUnitPx;

        topArr[3] = (moveTop - 1) * shapeUnitPx;
        topArr[2] = (moveTop - 1) * shapeUnitPx + shapeUnitPx;
        topArr[1] = (moveTop - 1) * shapeUnitPx + shapeUnitPx;
        topArr[0] = (moveTop - 1) * shapeUnitPx + shapeUnitPx * 2;

        nextIndex = 4;
    
    else if (shapeIndex == 6)  //Z形 - 向左

        /*
            34
            12
            */

        leftArr[3] = (moveLeft - 1) * shapeUnitPx + shapeUnitPx;
        leftArr[2] = (moveLeft - 1) * shapeUnitPx;
        leftArr[1] = (moveLeft - 1) * shapeUnitPx + shapeUnitPx * 2;
        leftArr[0] = (moveLeft - 1) * shapeUnitPx + shapeUnitPx;

        topArr[3] = (moveTop - 1) * shapeUnitPx;
        topArr[2] = (moveTop - 1) * shapeUnitPx;
        topArr[1] = (moveTop - 1) * shapeUnitPx + shapeUnitPx;
        topArr[0] = (moveTop - 1) * shapeUnitPx + shapeUnitPx;

        nextIndex = 7;
    
    else if (shapeIndex == 7)  //Z形 - 向上

        /*
            4
            23
            1
            */

        leftArr[3] = (moveLeft - 1) * shapeUnitPx + shapeUnitPx;
        leftArr[2] = (moveLeft - 1) * shapeUnitPx + shapeUnitPx;
        leftArr[1] = (moveLeft - 1) * shapeUnitPx;
        leftArr[0] = (moveLeft - 1) * shapeUnitPx;

        topArr[3] = (moveTop - 1) * shapeUnitPx;
        topArr[2] = (moveTop - 1) * shapeUnitPx + shapeUnitPx;
        topArr[1] = (moveTop - 1) * shapeUnitPx + shapeUnitPx;
        topArr[0] = (moveTop - 1) * shapeUnitPx + shapeUnitPx * 2;

        nextIndex = 6;
    
    else if (shapeIndex == 8)  //L形 - 向上

        /*
            0 30 60
            0 4
        30 3
        60 1 2
            */

        leftArr[3] = (moveLeft - 1) * shapeUnitPx;
        leftArr[2] = (moveLeft - 1) * shapeUnitPx;
        leftArr[1] = (moveLeft - 1) * shapeUnitPx + shapeUnitPx;
        leftArr[0] = (moveLeft - 1) * shapeUnitPx;

        topArr[3] = (moveTop - 1) * shapeUnitPx;
        topArr[2] = (moveTop - 1) * shapeUnitPx + shapeUnitPx;
        topArr[1] = (moveTop - 1) * shapeUnitPx + shapeUnitPx * 2;
        topArr[0] = (moveTop - 1) * shapeUnitPx + shapeUnitPx * 2;

        nextIndex = 9;
    
    else if (shapeIndex == 9)  //L形 - 向右

        /*
            0 30 60
            0 1 2 3
        30 4
        60
            */

        leftArr[3] = (moveLeft - 1) * shapeUnitPx;
        leftArr[2] = (moveLeft - 1) * shapeUnitPx + shapeUnitPx * 2;
        leftArr[1] = (moveLeft - 1) * shapeUnitPx + shapeUnitPx;
        leftArr[0] = (moveLeft - 1) * shapeUnitPx;

        topArr[3] = (moveTop - 1) * shapeUnitPx + shapeUnitPx;
        topArr[2] = (moveTop - 1) * shapeUnitPx;
        topArr[1] = (moveTop - 1) * shapeUnitPx;
        topArr[0] = (moveTop - 1) * shapeUnitPx;

        nextIndex = 10;
    
    else if (shapeIndex == 10)  //L形 - 向下

        /*
            0 30 60
            0 3 4
        30   2
        60   1
            */

        leftArr[3] = (moveLeft - 1) * shapeUnitPx + shapeUnitPx;
        leftArr[2] = (moveLeft - 1) * shapeUnitPx;
        leftArr[1] = (moveLeft - 1) * shapeUnitPx + shapeUnitPx;
        leftArr[0] = (moveLeft - 1) * shapeUnitPx + shapeUnitPx;

        topArr[3] = (moveTop - 1) * shapeUnitPx;
        topArr[2] = (moveTop - 1) * shapeUnitPx;
        topArr[1] = (moveTop - 1) * shapeUnitPx + shapeUnitPx;
        topArr[0] = (moveTop - 1) * shapeUnitPx + shapeUnitPx * 2;

        nextIndex = 11;
    
    else if (shapeIndex == 11)  //L形 - 向左

        /*
            0 30 60
            0     4
        30 1 2 3
        60
            */

        leftArr[3] = (moveLeft - 1) * shapeUnitPx + shapeUnitPx * 2;
        leftArr[2] = (moveLeft - 1) * shapeUnitPx + shapeUnitPx * 2;
        leftArr[1] = (moveLeft - 1) * shapeUnitPx + shapeUnitPx;
        leftArr[0] = (moveLeft - 1) * shapeUnitPx;

        topArr[3] = (moveTop - 1) * shapeUnitPx;
        topArr[2] = (moveTop - 1) * shapeUnitPx + shapeUnitPx;
        topArr[1] = (moveTop - 1) * shapeUnitPx + shapeUnitPx;
        topArr[0] = (moveTop - 1) * shapeUnitPx + shapeUnitPx;

        nextIndex = 8;
    
    else if (shapeIndex == 12)  //J形 - 向上

        /*
            4
            3
            12
            */

        leftArr[3] = (moveLeft - 1) * shapeUnitPx + shapeUnitPx;
        leftArr[2] = (moveLeft - 1) * shapeUnitPx + shapeUnitPx;
        leftArr[1] = (moveLeft - 1) * shapeUnitPx + shapeUnitPx;
        leftArr[0] = (moveLeft - 1) * shapeUnitPx;

        topArr[3] = (moveTop - 1) * shapeUnitPx;
        topArr[2] = (moveTop - 1) * shapeUnitPx + shapeUnitPx;
        topArr[1] = (moveTop - 1) * shapeUnitPx + shapeUnitPx * 2;
        topArr[0] = (moveTop - 1) * shapeUnitPx + shapeUnitPx * 2;

        nextIndex = 13;
    
    else if (shapeIndex == 13)  //J形 - 向右

        /*
            0 30 60
            0 4
        30 1 2 3
        60
            */

        leftArr[3] = (moveLeft - 1) * shapeUnitPx;
        leftArr[2] = (moveLeft - 1) * shapeUnitPx + shapeUnitPx * 2;
        leftArr[1] = (moveLeft - 1) * shapeUnitPx + shapeUnitPx;
        leftArr[0] = (moveLeft - 1) * shapeUnitPx;

        topArr[3] = (moveTop - 1) * shapeUnitPx;
        topArr[2] = (moveTop - 1) * shapeUnitPx + shapeUnitPx;
        topArr[1] = (moveTop - 1) * shapeUnitPx + shapeUnitPx;
        topArr[0] = (moveTop - 1) * shapeUnitPx + shapeUnitPx;

        nextIndex = 14;
    
    else if (shapeIndex == 14)  //J形 - 向下

        /*
            0 30 60
            0 3 4
        30 2
        60 1
            */

        leftArr[3] = (moveLeft - 1) * shapeUnitPx + shapeUnitPx;
        leftArr[2] = (moveLeft - 1) * shapeUnitPx;
        leftArr[1] = (moveLeft - 1) * shapeUnitPx;
        leftArr[0] = (moveLeft - 1) * shapeUnitPx;

        topArr[3] = (moveTop - 1) * shapeUnitPx;
        topArr[2] = (moveTop - 1) * shapeUnitPx;
        topArr[1] = (moveTop - 1) * shapeUnitPx + shapeUnitPx;
        topArr[0] = (moveTop - 1) * shapeUnitPx + shapeUnitPx * 2;

        nextIndex = 15;
    
    else if (shapeIndex == 15)  //J形 - 向左

        /*
            0 30 60
            0 2 3 4
        30     1
        60
            */

        leftArr[3] = (moveLeft - 1) * shapeUnitPx + shapeUnitPx * 2;
        leftArr[2] = (moveLeft - 1) * shapeUnitPx + shapeUnitPx;
        leftArr[1] = (moveLeft - 1) * shapeUnitPx;
        leftArr[0] = (moveLeft - 1) * shapeUnitPx + shapeUnitPx * 2;

        topArr[3] = (moveTop - 1) * shapeUnitPx;
        topArr[2] = (moveTop - 1) * shapeUnitPx;
        topArr[1] = (moveTop - 1) * shapeUnitPx;
        topArr[0] = (moveTop - 1) * shapeUnitPx + shapeUnitPx;

        nextIndex = 12;
    
    else if (shapeIndex == 16)  //T形 - 向下

        /*
            0 30 60
            0 2 3 4
        30   1
        60
            */

        leftArr[3] = (moveLeft - 1) * shapeUnitPx + shapeUnitPx * 2;
        leftArr[2] = (moveLeft - 1) * shapeUnitPx + shapeUnitPx;
        leftArr[1] = (moveLeft - 1) * shapeUnitPx;
        leftArr[0] = (moveLeft - 1) * shapeUnitPx + shapeUnitPx;

        topArr[3] = (moveTop - 1) * shapeUnitPx;
        topArr[2] = (moveTop - 1) * shapeUnitPx;
        topArr[1] = (moveTop - 1) * shapeUnitPx;
        topArr[0] = (moveTop - 1) * shapeUnitPx + shapeUnitPx;

        nextIndex = 17;
    
    else if (shapeIndex == 17)  //T形 - 向左

        /*
            0 30 60
            0   4
        30 2 3
        60   1
            */

        leftArr[3] = (moveLeft - 1) * shapeUnitPx + shapeUnitPx;
        leftArr[2] = (moveLeft - 1) * shapeUnitPx + shapeUnitPx;
        leftArr[1] = (moveLeft - 1) * shapeUnitPx;
        leftArr[0] = (moveLeft - 1) * shapeUnitPx + shapeUnitPx;

        topArr[3] = (moveTop - 1) * shapeUnitPx;
        topArr[2] = (moveTop - 1) * shapeUnitPx + shapeUnitPx;
        topArr[1] = (moveTop - 1) * shapeUnitPx + shapeUnitPx;
        topArr[0] = (moveTop - 1) * shapeUnitPx + shapeUnitPx * 2;

        nextIndex = 18;
    
    else if (shapeIndex == 18)  //T形 - 向上

        /*
            0 30 60
            0   4
        30 1 2 3
        60
            */

        leftArr[3] = (moveLeft - 1) * shapeUnitPx + shapeUnitPx;
        leftArr[2] = (moveLeft - 1) * shapeUnitPx + shapeUnitPx * 2;
        leftArr[1] = (moveLeft - 1) * shapeUnitPx + shapeUnitPx;
        leftArr[0] = (moveLeft - 1) * shapeUnitPx;

        topArr[3] = (moveTop - 1) * shapeUnitPx;
        topArr[2] = (moveTop - 1) * shapeUnitPx + shapeUnitPx;
        topArr[1] = (moveTop - 1) * shapeUnitPx + shapeUnitPx;
        topArr[0] = (moveTop - 1) * shapeUnitPx + shapeUnitPx;

        nextIndex = 19;
    
    else if (shapeIndex == 19)  //T形 - 向右

        /*
            0 30
            0 4
        30 2 3
        60 1
            */

        leftArr[3] = (moveLeft - 1) * shapeUnitPx;
        leftArr[2] = (moveLeft - 1) * shapeUnitPx + shapeUnitPx;
        leftArr[1] = (moveLeft - 1) * shapeUnitPx;
        leftArr[0] = (moveLeft - 1) * shapeUnitPx;

        topArr[3] = (moveTop - 1) * shapeUnitPx;
        topArr[2] = (moveTop - 1) * shapeUnitPx + shapeUnitPx;
        topArr[1] = (moveTop - 1) * shapeUnitPx + shapeUnitPx;
        topArr[0] = (moveTop - 1) * shapeUnitPx + shapeUnitPx * 2;

        nextIndex = 16;
    

    //===方块是否可移动判断===
    IsMove(function () 
        if ($(".shapeMoveDiv").html() == undefined)  //下一个方法(新增方块到游戏面板)

            var html = '';

            for (var i = 0; i < leftArr.length; i++) 
                var html1 = htmlTemplate;
                html += $(html1).css( "left": leftArr[i] + "px", "top": topArr[i] + "px" ).prop('outerHTML');
            

            $(".playDiv").append(html);
        
        else  //移动当前方块

            for (var i = 0; i < leftArr.length; i++) 

                $(".shapeMoveDiv").eq(i).css( "left": leftArr[i] + "px", "top": topArr[i] + "px" );
            
        

        tempDisplay();
    );
    //===/方块是否可移动判断===

6、方块是否可移动判断

1)设置一个全局变量,保存已经在游戏面板占据空间的小方块的坐标

2)首先对方块进行右边界的判断,如果方块有一个小方块的left值大于等于了游戏面板的最大宽度,那么就停止向右边移动

3)到达底部判断,如果方块有一个小方块的top值超过了游戏面板的最大宽度,那么就停止向下移动,并移除当前方块移动标志的class值

4)如果游戏面板已经有方块存在,那么根据前面已经保存好的方块坐标来判断,如果存在相同坐标,那么停止方块移动,并将当前方块的坐标保存到全局变量里

5)如果通过上面步骤都不满足,那么就是可以移动,否则就进行下一步操作

6)如果方块触发了停止,那么就停止定时器向下移动方法

7)如果当前停止移动的方块的top值有出现负数,那么就结束游戏

//===判断是否可以移动===
var havePositionArr = [];
function IsMove(call) 

    var flag = 1;

    //判断右边边界
    for (var i = 0; i < leftArr.length; i++) 

        var _v = leftArr[i];
        if (_v >= leftMaxValue) 
            flag = 0;
            moveLeft -= 1;
        
    
    if (!flag) 
        return;
    

    //到达了底部,不可再移动
    for (var i = 0; i < leftArr.length; i++) 

        var _v = topArr[i];
        if (_v >= topMaxValue) 
            flag = 0;
        
    

    //再判断是否存在的单元格
    if (havePositionArr.length > 0) 
        for (var i = 0; i < leftArr.length; i++) 
            var currentPosition = leftArr[i] + "," + topArr[i];
            for (var j = 0; j < havePositionArr.length; j++) 
                var havaPosition = havePositionArr[j];
                if (currentPosition == havaPosition) 
                    flag = 0;
                
            
        
    

    //判断
    if (flag)  //可以移动方块

        call();
    
    else  //停止移动方块

        //===先停止定时器===
        clearInterval(moveTime); 

        //===移除移动标志class===
        var isFinal = 0;
        for (var i = 0; i < $(".shapeMoveDiv").length; i++) 

            havePositionArr.push($(".shapeMoveDiv").eq(i).css("left").replace("px", "") + "," + $(".shapeMoveDiv").eq(i).css("top").replace("px", ""));

            if (parseInt($(".shapeMoveDiv").eq(i).css("top").replace("px", "")) < 0) 
                isFinal = 1;
            
        
        $(".shapeMoveDiv").removeClass("shapeMoveDiv");
        if (isFinal) 

            alert("游戏结束!");
            return;
        
        //===/移除移动标志class===

        //===再检查是否有可移除的方块==
        checkRemoveFun();
    

7、检查是否有方块可消除

判断的原则

1)通过每个小方块的top值为分组,如果top值相同,且达到10个方块,那么说明是同一行,即可移除方块

2)移除方块后,再根据移除后的方块的top值来判断,小于这个top的上面的所有小方块就需要增加top值往下叠加

3)最后就是触发点击开始按钮,即可下一个方块

//===分段判断===
function checkRemoveFun() 

    //检查是否可以消除了
    var length = $(".shapeDiv").length;
    var tempArr = [];
    var flag = '';
    var currentTop = '';
    for (var n = 0; n < length; n++) 
        currentTop = $(".shapeDiv").eq(n).css("top");

        if (tempArr.length <= 0) 

            flag += currentTop + "|";
            tempArr.push( key: currentTop, value: 1 );
        
        else 

            if (flag.indexOf(currentTop) < 0) 

                flag += currentTop + "|";
                tempArr.push( key: currentTop, value: 1 );
            
            else 

                for (var i = 0; i < tempArr.length; i++) 

                    if (tempArr[i]['key'] == currentTop) 

                        var _vvv = parseInt(tempArr[i]['value']) + 1;
                        tempArr[i]['value'] = _vvv;
                    
                
            
        
    

    //循环移除10个单元格
    var removeTop = '';
    var removeRow = 0;
    for (var i = 0; i < tempArr.length; i++) 
        if (parseInt(tempArr[i]['value']) >= 10) 

            removeTop = tempArr[i]['key'];

            //先消除完再移动
            for (var c = 0; c < 10; c++) 
                for (var n = 0; n < length; n++) 
                    currentTop = $(".shapeDiv").eq(n).css("top");
                    if (currentTop == removeTop) 
                        $(".shapeDiv").eq(n).remove();
                    
                
            
                    
            removeRow += 1;
        
    

    //上一层的top值向下
    for (var n = 0; n < $(".shapeDiv").length; n++) 
        currentTop = $(".shapeDiv").eq(n).css("top");
        if (parseInt(currentTop.replace("px", "")) < parseInt(removeTop.replace("px", ""))) 
            $(".shapeDiv").eq(n).css("top", (parseInt(currentTop.replace("px", "")) + shapeUnitPx * removeRow) + "px");
        
    

    //再循环保存现有的单元格
    if (removeTop != '') 
        havePositionArr = [];
        for (var i = 0; i < $(".shapeDiv").length; i++) 

            havePositionArr.push($(".shapeDiv").eq(i).css("left").replace("px", "") + "," + $(".shapeDiv").eq(i).css("top").replace("px", ""));
        
    

    $(".btnStartDiv").trigger('click'); //触发开始,下一个方块

8、到此游戏基础逻辑完成

1)方块随机出现

2)定时器自动将方块往下移动

3)边界判断

4)方块停止判断

5)方块消除判断

9、后续可在基础逻辑上发挥了

1)消除后,增加分数

2)方块动态变化颜色

3)加上消除方块的音效

4)加上背景音乐

5)更换背景皮肤等等可任意发挥的功能

总结

这里提供的是一个开发思路和方向,方法和算法不一定是最佳的,我相信大家通过自己的方式也能快速开发出来

以上是关于小5聊前端开发经典游戏俄罗斯方块(前端开发领域)的主要内容,如果未能解决你的问题,请参考以下文章

俄罗斯方块游戏开发系列教程5:形状碰撞检测(下)

俄罗斯方块游戏开发系列教程8:下落处理

俄罗斯方块游戏开发系列教程2:随机生成形状

团队作业

俄罗斯方块游戏开发系列教程1:整体流程

安卓开发: Jetpack compose + kotlin 实现 俄罗斯方块游戏