• 使用JS实现俄罗斯方块游戏


     简单的JS俄罗斯方块游戏源码

      效果图:

     

     代码如下,复制即可使用:

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <title>使用JS实现俄罗斯方块游戏</title>
    
    <style type="text/css">
        
        .MainFrame
        {
            border: 1px solid burlywood;
            margin: 10px auto;
            position: relative;
            background-color: silver;
        }
        
        .MainFramediv
        {
            float: left;
            margin: 1px;
            position: absolute;
            /*z-index: -1;*/
        }
        
        .smallDiv
        {
            margin: 1px;
            position: absolute;
        }
        
        .smallDivblack
        {
            /*float: left;*/
            margin: 1px;
            /*margin: 1px;*/
            position: absolute;
            /*z-index: 2;*/
        }
        
        #tetris{
            width: 50%;
            margin: 0 auto;
            padding: 0;
            /*border: 1px solid silver;*/
        }
        #tetris:after{
            content:  "";
            Display:  block;
            Clear:  both;
        }
        
        #control{
            float: left;
            border: 1px solid silver;
            width: 150px;
            height: 578px;
            margin-top: 10px;
            margin-left: 20px;
            padding-top: 30px;
            font-size: 24px;
            font-weight: 400;
            color: blue;
            text-align: center;
        }
        #level,#regame{
            width: 100px;
            height: 30px;
            border: 1px solid blue;
            font-size: 16px;
            color: red;
            font-weight: 300;
        }
        #control p{
            margin-top: 200px;
        }
        #regame{
            margin-top: 100px;
            font-weight: 600;
            background-color: azure;
        }
        
        
        #TFrime{
            float: left;
        }
        
        
        #info{
            float: left;
            border: 1px solid silver;
            width: 150px;
            height: 578px;
            margin: 10px auto;
            padding-top: 30px;
            text-align: center;
            color: blue;
            font-size: 24px;
            font-weight: 400;
        }
        #nextfigure{
            width: 100px;
            height: 100px;
            background-color: silver;
            margin: 0 auto;
            margin-bottom: 100px;
            position: relative;
        }
        
        .drawdiv{
            background-color: red;
            margin: 1px;
            border: 1px solid silver;
            position: absolute;
        }
        
    </style>
    <!-- 此处需要自己修改JS路径 -->
    <script src="js/GameFrame.js" type="text/javascript" charset="utf-8"></script>
    <script src="js/graph.js" type="text/javascript" charset="utf-8"></script>
    <script src="js/index.js" type="text/javascript" charset="utf-8"></script>
    
    </head>
    <body onload="initGame()">
    <div id="tetris">
        <div id="control">
            难度:
            <div><select id="level" onchange="changespeed()">
                <option value="1000">简单
                <option value="500">一般
                <option value="200">困难
            </select></div>
            <input type="button" id="regame" value="重 新 开 始" onclick="regame()">
            <p>
                ↑:变换<br>
                ←:左移<br>
                →:右移<br>
                ↓:加速<br>
            </p>
        </div>
        <div id="TFrime"></div>
        <div id="info">
            下一个图形:
            <div id="nextfigure">
                
            </div>
            <div>分数:<span id="score">0</span></div>
        </div>
    </div>
    <div style="text-align:center;margin:10px 0; font:normal 14px/24px 'MicroSoft YaHei';">
    <p>适用浏览器:360、FireFox、Chrome、Safari、Opera、傲游、搜狗、世界之窗. 不支持IE8及以下浏览器。</p>
    </div>
    </body>
    </html>

     GameFrame.js

    function GameFrame(unit,row,col)
    {
        //单位的像素
        this.unit = unit;
        //横向单位个数(列),,(一行的个数)
        this.row = row;
        //纵向单位个数(行),,(一列的个数)
        this.col =col;
        //保存页面创建div容器的属性
        this.Content;
        //小图形
        this.samlldiv;
        //定时器id
        this.intervalid;
        //速度
        this.speed =document.getElementById("level").value;
        //速度是否改变
        this.ChangeSped=0;
        //记录每个位置是否有div
        this.datas=[];
        //记录消除行数相应的分数
        this.score=[0,100,300,600,1000]
        //记录当前的图形的下标
        this.now;
        //记录下一个图形的下标
        this.next;
        //记录当前的图形的颜色
        this.nowcolor;
        //记录下一个图形的颜色
        this.nextcolor;
        //保存7种图形相对坐标的数组
        this.arr = "0,1,0,2,1,2,2,2;0,1,1,1,1,2,2,2;0,1,0,2,1,1,2,1;0,2,1,1,1,2,2,1;1,0,1,1,1,2,1,3;1,1,1,2,2,1,2,2;1,1,2,0,2,1,2,2".split(";");
        //保存小方块的颜色
        this.color=["red","blue","green","yellow","#00FFFF","#930093","#F80000","#984B4B"];
        
        //初始化容器div
        this.init = function()
        {
            //创建div
            var div = document.createElement("div");
            //设置div的宽度
            div.style.width = (this.unit*this.row)+"px";
            //设置div的高度
            div.style.height=(this.unit*this.col)+"px";
            //设置div的样式
            div.className="MainFrame";
            div.id="MainFrame";
            //加入到body中
            document.getElementById("TFrime").appendChild(div);
            this.Content =div; //保存div的引用
            //初始化数组
            for(var i=0;i<this.col;i++)    //i为行
            {
                for(var j=0;j<this.row;j++){                //j为列
                var sdiv = document.createElement("div");
                sdiv.className="MainFramediv";
                sdiv.style.width = (this.unit - 2) + "px";
                sdiv.style.height = (this.unit - 2) + "px";
                sdiv.style.left=(j*this.unit)+"px";
                sdiv.style.top=(i*this.unit)+"px";
                this.Content.appendChild(sdiv);
                this.datas.push(0);
                }
            }
            this.next=Math.floor(Math.random() * this.arr.length);
            this.nextcolor=this.color[Math.floor(Math.random() * this.color.length)];
            Start();
        }
        
        this.MoveLeft = function()
        {
            this.samlldiv.moveleft();
        }
        
        this.MoveRight = function(){
            this.samlldiv.moveright();
        }
        
        this.Change = function(){
            this.samlldiv.change();
            
        }
        
        this.MoveDown = function(){
            if(this.samlldiv.movedown())
            {
    //            for(var i=0;i<this.samlldiv.divs.length;i++)
    //            {
    //                this.Content.removeChild(this.samlldiv.divs[i]);
    //            }
                this.samlldiv.rescore();
                Start();
            }
            
        }
        
        function Start()
        {
            //将next值传给now
            this.frame.now=this.frame.next;
            this.frame.nowcolor=this.frame.nextcolor;
            //创建小div
            this.frame.samlldiv=new Graph(this.frame);
            this.frame.samlldiv.init(this.frame.now,this.frame.nowcolor);
            //绘出下一个图形
            this.frame.next=Math.floor(Math.random() * this.frame.arr.length);
            this.frame.nextcolor=this.frame.color[Math.floor(Math.random() * this.frame.color.length)];
            draw();
            
            //调用定时器下落
            this.frame.intervalid = setInterval(autoMoveDown,this.frame.speed);
            //判断游戏是否结束
            if (this.frame.samlldiv.movedown()){
                    clearInterval(this.frame.intervalid);
                    alert("游戏结束!");
                }
        }
        
        function autoMoveDown()
        {
            if(this.frame.samlldiv.movedown())
            {
                this.frame.samlldiv.rescore();
                Start();
            }
            
            //改变速度
            if(this.frame.ChangeSped){
                clearInterval(this.frame.intervalid);
                this.frame.intervalid = setInterval(autoMoveDown,this.frame.speed);
                this.frame.ChangeSped=0;
            }
        }
        
        //速度改变,令ChangeSped值为1
        this.changespeed=function(){
            this.speed=document.getElementById("level").value;
            this.ChangeSped=1;
    //        alert(this.ChangeSped);
        }
        
        //绘制下一个图形
        function draw(){
            //清楚原有的图形
            var cleardiv=document.getElementsByClassName("drawdiv");
            for(;;){
                if(cleardiv.length){
                    document.getElementById("nextfigure").removeChild(cleardiv[0]);
                }else{
                    break;
                }
            }
            //绘制图形
            var smallarr = this.frame.arr[this.frame.next].split(",");
            for (var i = 0; i < 8; i += 2) {
            var drawdiv = document.createElement("div");
            drawdiv.className = "drawdiv";
            drawdiv.style.backgroundColor=this.frame.nextcolor;
            drawdiv.style.width = (this.frame.unit - 2) + "px";
            drawdiv.style.height = (this.frame.unit - 2) + "px";
            drawdiv.style.top = (((smallarr[i] - 0) * this.frame.unit)+18) + "px";
            drawdiv.style.left = (((smallarr[i + 1] - 0) * this.frame.unit)+18) + "px";
            document.getElementById("nextfigure").appendChild(drawdiv);
            }
        }
        
        
    }

     graph.js

    function Graph(frame) {
        //保存7种图形相对坐标的数组
    //    var arr = "0,1,0,2,1,2,2,2;0,1,1,1,1,2,2,2;0,1,0,2,1,1,2,1;0,2,1,1,1,2,2,1;1,0,1,1,1,2,1,3;1,1,1,2,2,1,2,2;1,1,2,0,2,1,2,2".split(";");
        //保存4个小图形的数组
        this.divs = [];
        //外部容器div的数组
        this.parentFrame = frame;
        //图形横纵偏移
        this.x = 0;
        this.y = 0;
        //记录图形的坐标数组
        this.zb = [];
        //记录消除的行数
        this.line=0;
        
        
    
        //初始化小图形的方法
        this.init = function(rand,color) {
                //计算图形其实坐标的单位
                var startleft = (this.parentFrame.row - 4) / 2;
                this.x = startleft;
                //随机生成图形数组下标
    //            var rand = Math.floor(Math.random() * arr.length);
                //分解图形的坐标
                var smallarr = this.parentFrame.arr[rand].split(",");
                this.zb = smallarr;
                //循环设置小div的 left和top
                for (var i = 0; i < 8; i += 2) {
                    //创建小div
                    var smalldiv = document.createElement("div");
                    //设置样式
                    smalldiv.className = "smallDiv";
                    //设置颜色
                    smalldiv.style.backgroundColor=color;
                    //定义高宽
                    smalldiv.style.width = (this.parentFrame.unit - 2) + "px";
                    smalldiv.style.height = (this.parentFrame.unit - 2) + "px";
                    //设置小div的top
                    smalldiv.style.top = ((smallarr[i] - 0) * this.parentFrame.unit) + "px";
                    //设置小div的left
                    smalldiv.style.left = (((smallarr[i + 1] - 0) + startleft) * this.parentFrame.unit) + "px";
                    //保存小div的引用
                    this.divs.push(smalldiv);                
                    //加入到外部容器
                    document.getElementById("MainFrame").appendChild(smalldiv);
                }
                //执行自动向下移动
                //this.parentFrame.intervalid = setInterval(autoMoveDown, this.parentFrame.speed);
            }
            //左移动
        this.moveleft = function() {
                //        var canmove = true;
                //        //判断能否左移动
                //        
                //        for(var i=0;i<this.divs.length;i++)
                //        {
                //                var left=parseInt(this.divs[i].style.left); //div目前的left
                //                if(left - this.parentFrame.unit <0) //减去一个单位的像素是否小于0
                //                {
                //                    canmove = false; //不能向左移动了
                //                    break;
                //                }
                //        }
    
                if (canMove(this.zb, this.x, this.y, this.parentFrame, 2)) //可以移动
                {
                    this.x -= 1;
                    for (var i = 0; i < this.divs.length; i++) //循环小div,把每个div的left减去一个单位的像素
                    {
                        var left = parseInt(this.divs[i].style.left);
                        this.divs[i].style.left = (left - this.parentFrame.unit) + "px";
                    }
                }
    
            }
            //右移动
        this.moveright = function() {
            //        var canmove = true;
            //            //判断能否右移动
            //        for(var i=0;i<this.divs.length;i++)
            //        {
            //            var left=parseInt(this.divs[i].style.left);
            //            if(left + this.parentFrame.unit >=parseInt(this.parentFrame.Content.style.width))
            //            {
            //                canmove = false;
            //                break;
            //            }
            //        }
            var temp = canMove(this.zb, this.x, this.y, this.parentFrame, 1);
    //        alert(temp);
            console.log(temp);
            if (canMove(this.zb, this.x, this.y, this.parentFrame, 1)) {
                this.x += 1;
                for (var i = 0; i < this.divs.length; i++) {
                    var left = parseInt(this.divs[i].style.left);
                    this.divs[i].style.left = (left + this.parentFrame.unit) + "px";
                }
            }
        }
    
        //变形
        this.change = function() {
            //变形的公式
            //小div的2个相对坐标点改变    x = y ;  y= 3-x; 比如  (0,1) 变化之后 就是   x=1,y=3-0 -> (1,3)
            //循环4个小div
            if (!canMove(this.zb, this.x, this.y, this.parentFrame, 4)) {
                if (this.x < 0) {
                    this.x += 1;
                } else {
                    this.x -= 1;
                }
            }
            for (var i = 0; i < this.divs.length; i++) {
                //根据公式改变每个div的相对偏移量,2个一改
                var temp = this.zb[i * 2]
                this.zb[i * 2] = this.zb[i * 2 + 1];
                this.zb[i * 2 + 1] = 3 - temp;
                //根据改变后的偏移量计算图形的当前left和top
                this.divs[i].style.top = ((this.y + parseInt(this.zb[i * 2])) * this.parentFrame.unit) + "px";
                this.divs[i].style.left = ((this.x + parseInt(this.zb[i * 2 + 1])) * this.parentFrame.unit) + "px";
            }
    
        }
    
        this.movedown = function() {
            
            var $this = this =="window" ? this.frame.samlldiv : this;
            
    
            if (canMove($this.zb, $this.x, $this.y, $this.parentFrame, 3)) {
                $this.y += 1;
                for (var i = 0; i < $this.divs.length; i++) {
                    var top = parseInt($this.divs[i].style.top);
                    $this.divs[i].style.top = (top + $this.parentFrame.unit) + "px";
                }
                return false;
            } else {
                clearInterval($this.parentFrame.intervalid);
    //            var temp = $this.parentFrame.Content.getElementsByTagName("div");
                for (var i=0;i<$this.divs.length;i++) {
                    //div变灰
                    //$this.divs[i].className ="smallDivblack";
                    var $y =  $this.y + parseInt($this.zb[i*2]);
                    var $x =  $this.x+parseInt($this.zb[i*2+1]);
    //                debugger;
                    $this.parentFrame.datas[$y*$this.parentFrame.row+ $x] =1;
                    $this.divs[i].dataset.row=$y;    //记录div所在的行
                    $this.divs[i].dataset.col=$x;    //记录div所在的列
                    $this.divs[i].className="smallDivblack";
                    $this.divs[i].style.backgroundColor="black";
                    //$this.parentFrame.datas[]
                }
                    
                    
                    //消行并计分
                    for (var i= 0;i<$this.parentFrame.col;i++) {        //i为行
                        //判断是否满足消行条件
                        for (var j=0;j<$this.parentFrame.row;j++) {        //j为列
                            if($this.parentFrame.datas[i*$this.parentFrame.row+ j] !=1){
                                break;
                            }
                        }
                        //消行,将该行上面的所有div下移一行
                        if(j==$this.parentFrame.row){
                            var x;        //记录div在哪一列
                            var y;        //记录div在哪一行
                            var getsmalldiv=document.getElementById("TFrime").getElementsByClassName("smallDivblack");//得到小div
                            for (var a=0;a<getsmalldiv.length;a++){
                                y=parseInt(getsmalldiv[a].dataset.row);
                                x=parseInt(getsmalldiv[a].dataset.col);
                                if(y==i){        //消除该行
                                    debugger;
                                    $this.parentFrame.datas[y*$this.parentFrame.row+ x]=0;
                                    getsmalldiv[a].remove();
                                    a--;
                                }
                            }
                            
                            for (var a=i-1;a>0;a--) {
                                for (var b=0;b<getsmalldiv.length;b++) {
                                    y=parseInt(getsmalldiv[b].dataset.row);
                                    x=parseInt(getsmalldiv[b].dataset.col);
                                    if(y==a){        //将上面的div下移一行
    //                                debugger;
                                    var divtop=parseInt(getsmalldiv[b].style.top);
                                    getsmalldiv[b].style.top=(divtop+$this.parentFrame.unit)+"px";
                                    getsmalldiv[b].dataset.row++;
                                    $this.parentFrame.datas[y*$this.parentFrame.row+ x]=0;
                                    $this.parentFrame.datas[(y+1)*$this.parentFrame.row+ x]=1;
                                    }
                                }
                                
                            }
                            $this.line++;
                            
    //                        for (var a=0;a<getsmalldiv.length;a++) {
    //                            y=parseInt(getsmalldiv[a].dataset.row);
    //                            x=parseInt(getsmalldiv[a].dataset.col);
    ////                            alert(getsmalldiv[a].dataset.row);
    //                            if(y<i){        //将上面的div下移一行
    ////                                debugger;
    //                                var divtop=parseInt(getsmalldiv[a].style.top);
    ////                                alert(getsmalldiv[a].style.top);
    //                                getsmalldiv[a].style.top=(divtop+$this.parentFrame.unit)+"px";
    //                                getsmalldiv[a].dataset.row++;
    //                                debugger;
    //                                $this.parentFrame.datas[y*$this.parentFrame.row+ x]=0;
    //                                $this.parentFrame.datas[(y+1)*$this.parentFrame.row+ x]=1;
    //                            }
    ////                            }else if(y==i){        //消除该行
    ////                                debugger;
    ////                                $this.parentFrame.datas[y*$this.parentFrame.row+ x]=0;
    ////                                getsmalldiv[a].className="MainFramediv";
    ////                            }
    //                        }
                        }
                    }
                        
                return true;
            }
        }
    
    //    function autoMoveDown() {
    //        
    //        var small = this.frame.samlldiv;
    //        var f = this.frame;
    //        
    //        if (canMove(small.zb, small.x, small.y, 0, f.col, 3)) {
    //            small.y += 1;
    //            for (var i = 0; i < small.divs.length; i++) {
    //                var top = parseInt(small.divs[i].style.top);
    //                small.divs[i].style.top = (top + f.unit) + "px";
    //            }
    //        } else {
    //            clearInterval(f.intervalid);
    //        }
    //
    //    }
    
        //预判能否移动或变化,action:1.右移,2.左移,3.下移,4.变化
        //zb是4个小图形的相对偏移,x是图形左偏移,y是top偏移,f是外部frame
        function canMove(zb, x, y, f, action) {
            //datas[parseInt(zb[i + 1]) + x + 1)+(this.y-1)*row] !=0
            
            switch (action) {
                case 1:
    //                debugger;
                    for (var i = 0; i < zb.length; i += 2) {
                        if (parseInt(zb[i + 1]) + x + 1 >= f.row)
                        {
                            return false;
                        }else if(f.datas[(parseInt(zb[i + 1]) + x + 1)+(y+parseInt(zb[i]))*f.row] !=0)
                        {
                            return false;
                        }
                    }
                    break;
                case 2:
                    for (var i = 0; i < zb.length; i += 2) {
                        if (parseInt(zb[i + 1]) + x - 1 < 0 ) {
                            return false;
                        }else if(f.datas[(parseInt(zb[i + 1]) + x - 1)+(y+parseInt(zb[i]))*f.row] !=0)
                        {
                            return false;
                        }
                    }
                    break;
                case 3:
                    for (var i = 0; i < zb.length; i += 2) {
                        if (parseInt(zb[i]) + y + 1 >= f.col ||
                        f.datas[(parseInt(zb[i + 1]) + x)+(parseInt(zb[i]) + y+1)*f.row] !=0) {
                            return false;
                        }
                    }
                    break;
                case 4:
                    for (var i = 0; i < zb.length; i += 2) {
                        var temp = 3 - zb[i];
                        if (temp + x < 0 || temp + x >= f.row) {
                            return false;
                        }
                    }
                    break;
            }
            return true;
        }
        
        this.rescore=function(){
            var gamescore=document.getElementById("score");
            gamescore.innerHTML=parseInt(gamescore.innerHTML)+this.parentFrame.score[this.line];
        }
    
    }

     index.js

    var frame;
    
    function initGame()
    {
        frame = new GameFrame(16,20,38);
        frame.init();
    
       document.body.addEventListener("keydown",MoveOrChange)
        
    }
    
    function changespeed(){
        frame.changespeed();
    }
    
    function regame(){
        location.reload();
    }
    
    
    function MoveOrChange()
    {
        
        switch(event.keyCode)
        {
            case 38: //变形(上方向键)
                frame.Change();
                break;
            case 37: //左移动
                frame.MoveLeft();
                break;
            case 39://右移动
                frame.MoveRight();
                break;
            case 40:  //向下
                frame.MoveDown();
                break;
        }
    }

     如果有更好的方法或更多的功能,可以和我们大家一起分享哦,如有错误,欢迎联系我改正,非常感谢!!!

  • 相关阅读:
    [转载]VC补遗之Profile篇
    [原创]百度之星2009初赛第二场第四题解答
    [总结]QT在CODE:BLOCKS中的配置
    [原创]自己写的一个简单的程序日志记录类
    [原创]QT动态加载UI文件注意事项
    window版本信息资源格式
    [原创]滚动条滚动范围的问题总结
    ofstream奇怪问题解决方法
    [转载]最小矩形(rec1)的解题报告
    oracle数据库用户之间授权
  • 原文地址:https://www.cnblogs.com/yidaixiaohui/p/8447594.html
Copyright © 2020-2023  润新知