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


Posted in Javascript onAugust 03, 2018

简单的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;
  }
}

总结

以上所述是小编给大家介绍的使用JS代码实现俄罗斯方块游戏,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
Javascript动态创建div的方法
Feb 09 Javascript
jQuery仿gmail实现fixed布局的方法
May 27 Javascript
jQuery实现判断滚动条到底部
Jun 23 Javascript
Windows下用PyCharm和Visual Studio开始Python编程
Oct 26 Javascript
利用JS实现数字增长
Jul 28 Javascript
EasyUI 中combotree 默认不能选择父节点的实现方法
Nov 07 Javascript
详解Angularjs 如何自定义Img的ng-load 事件
Feb 15 Javascript
详解vue.js的事件处理器v-on:click
Jun 27 Javascript
web前端vue实现插值文本和输出原始html
Jan 19 Javascript
详解Angular路由之路由守卫
May 10 Javascript
vue项目上传Github预览的实现示例
Nov 06 Javascript
解决VUE项目localhost端口服务器拒绝连接,只能用127.0.0.1的问题
Aug 14 Javascript
小程序tab页无法传递参数的方法
Aug 03 #Javascript
详解Webpack多环境代码打包的方法
Aug 03 #Javascript
浅析vue-router jquery和params传参(接收参数)$router $route的区别
Aug 03 #jQuery
浅析Vue 和微信小程序的区别、比较
Aug 03 #Javascript
Vue 项目分环境打包的方法示例
Aug 03 #Javascript
如何在vue里添加好看的lottie动画
Aug 02 #Javascript
原生js实现form表单序列化的方法
Aug 02 #Javascript
You might like
文件上传的实现
2006/10/09 PHP
ThinkPHP缓存方法S()概述
2014/06/13 PHP
php中Snoopy类用法实例
2015/06/19 PHP
PHP实现的简单网络硬盘
2015/07/29 PHP
在WordPress中使用wp-cron插件来设置定时任务
2015/12/10 PHP
基于Codeigniter框架实现的student信息系统站点动态发布功能详解
2017/03/23 PHP
PHP排序算法之堆排序(Heap Sort)实例详解
2018/04/21 PHP
php实现微信公众号创建自定义菜单功能的实例代码
2019/06/11 PHP
flash javascript之间的通讯方法小结
2008/12/20 Javascript
JavaScript 类的定义和引用 JavaScript高级培训 自定义对象
2010/04/27 Javascript
Javascript实现的鼠标经过时播放声音
2010/05/18 Javascript
使用Jquery搭建最佳用户体验的登录页面之记住密码自动登录功能(含后台代码)
2011/07/10 Javascript
javascript权威指南 学习笔记之变量作用域分享
2011/09/28 Javascript
from表单多个按钮提交用onclick跳转不同action
2014/04/24 Javascript
基于javascript、ajax、memcache和PHP实现的简易在线聊天室
2015/02/03 Javascript
js实现Select下拉框具有输入功能的方法
2015/02/06 Javascript
jQuery实现鼠标跟随提示层效果代码(可显示文本,Div,Table,Html等)
2016/04/18 Javascript
jQuery Easyui datagrid editor为combobox时指定数据源实例
2016/12/19 Javascript
js实现功能比较全面的全选和多选
2017/03/02 Javascript
javascript定时器取消定时器及优化方法
2017/07/08 Javascript
iview给radio按钮组件加点击事件的实例
2017/09/30 Javascript
Vue.js如何使用Socket.IO的示例代码
2019/09/05 Javascript
js正则表达式简单校验方法
2021/01/03 Javascript
[56:35]DOTA2上海特级锦标赛C组小组赛#1 OG VS Archon第二局
2016/02/27 DOTA
使用pyshp包进行shapefile文件修改的例子
2019/12/06 Python
Tensorflow 实现将图像与标签数据转化为tfRecord文件
2020/02/17 Python
python使用numpy中的size()函数实例用法详解
2021/01/29 Python
python 使用OpenCV进行简单的人像分割与合成
2021/02/02 Python
2013年学期结束动员演讲稿
2014/01/07 职场文书
交通事故协议书范文
2014/04/16 职场文书
领导干部遵守党的政治纪律情况思想汇报
2014/09/14 职场文书
习近平在党的群众路线教育实践活动总结大会上的讲话全文
2014/10/25 职场文书
员工表扬信怎么写
2015/05/05 职场文书
2015年机关党建工作总结
2015/05/22 职场文书
python爬虫请求库httpx和parsel解析库的使用测评
2021/05/10 Python
Python破解极验滑动验证码详细步骤
2021/05/21 Python