用原生js写2048小游戏

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用原生js写2048小游戏相关的知识,希望对你有一定的参考价值。

 

<!DOCTYPE html>

<html>

 

<head>

  <title> 2048-game </title>

  <meta charset="utf-8" />

  <style media="screen">

    #game {

      display: none;

      position: absolute;

      left: 0px;

      top: 0px;

      right: 0px;

      bottom: 0px;

      

      opacity: 0.5;

      z-index: 1;

    }

 

    .clear:after {

      content: "";

      display: table;

      clear: both;

    }

 

    .left {

      float: left;

    }

 

    .right {

      float: right;

    }

 

    .scoreShow {

      height: 50px;

      text-align: center;

      line-height: 50px;

    }

 

    .model {

      text-decoration: none;

      color: white;

      background-color: #bbada0;

      font-size: 36px;

      border-radius: 10px;

    }

 

    .head {

      width: 480px;

      height: 50px;

      margin: 0 auto;

      font-size: 25px;

    }

 

    #gridPanel {

      width: 480px;

      height: 480px;

      margin: 0 auto;

      background-color: #bbada0;

      border-radius: 10px;

      position: relative;

      z-index: 1;

    }

 

    .grid,

    .cell {

      width: 100px;

      height: 100px;

      border-radius: 6px;

    }

 

    .grid {

      background-color: #ccc0b3;

      float: left;

      margin: 16px 0 0 16px;

    }

 

    .cell {

      position: absolute;

      font-size: 60px;

      text-align: center;

      line-height: 100px;

      color: #fff;

    }

 

    .n2 {

      background-color: #eee3da

    }

 

    .n4 {

      background-color: #ede0c8

    }

 

    .n8 {

      background-color: #f2b179

    }

 

    .n16 {

      background-color: #f59563

    }

 

    .n32 {

      background-color: #f67c5f

    }

 

    .n64 {

      background-color: #f65e3b

    }

 

    .n128 {

      background-color: #edcf72

    }

 

    .n256 {

      background-color: #edcc61

    }

 

    .n512 {

      background-color: #9c0

    }

 

    .n1024 {

      background-color: #33b5e5

    }

 

    .n2048 {

      background-color: #09c

    }

 

    .n4096 {

      background-color: #a6c

    }

 

    .n8192 {

      background-color: #93c

    }

 

    .n2,

    .n4 {

      color: #776e65

    }

 

    #gameover {

      width: 100%;

      display: none;

      position: fixed;

      left: 50%;

      right: 50%;

      top: 148px;

      width: 220px;

      height: 200px;

      border-radius: 10px;

      background-color: white;

      margin-left: -110px;

      text-align: center;

      z-index: 5;

    }

 

    #gameover>a {

      display: inline-block;

      width: 170px;

      height: 50px;

      border-radius: 10px;

      text-decoration: none;

      background-color: #9F8D77;

      color: white;

      font-size: 36px;

    }

  </style>

</head>

 

<body>

  <div id="game">

  </div>

  <div class="head clear">

    <div class="scoreShow left">

      <span>Score:</span>

      <span id="score"></span>

    </div>

    <div class="selction right" onclick="getModel(event)">

      <a href="#" class="model" value="3">3X3</a>

      <a href="#" class="model" value="4">4X4</a>

      <a href="#" class="model" type="button">5X5</a>

      <a href="#" class="model" type="button">6X6</a>

      <!-- <input type="text" id="model"> -->

      <!-- <button type="button" name="button" id="set">设置游戏</button> -->

    </div>

  </div>

  <div id="gridPanel">

  </div>

  <div id="gameover">

    <h1 id="Score"></h1>

    <a href="#" id="again" onclick="obj.gameStart()">Try again</a>

  </div>

  <script type="text/javascript">

    var arr = [];

 

    function $(id) {

      return document.getElementById(id);

    }

 

    function C(cls) {

      return document.getElementsByClassName(cls);

    }

    var obj = {

      ROW: 4,

      CELL: 4,

      r: 0,

      c: 0,

      f: 0, //r行  c列  f查找的下一位置

      keyCd: 0,

      score: 0,

      createEle: 0, //是否需要创建元素

      eleFragment: "", //文档片段变量

      //游戏开始

      gameStart: function() {

        obj.init();

        document.onkeydown = function(e) { //自动获得事件对象

          switch (e.keyCode) { //判断按键号

            case 37:

              obj.keyCd = 1;

              obj.moveLeft();

              break;

            case 38:

              obj.keyCd = 2;

              obj.moveUp();

              break;

            case 39:

              obj.keyCd = 1;

              obj.moveRight();

              break;

            case 40:

              obj.keyCd = 2;

              obj.moveDown();

              break;

          }

          $("score").innerHTML = obj.score; //更新分数

        }

 

      },

 

      //初始化

      init: function() {

        obj.eleFragment = document.createDocumentFragment();

        for (r = 0; r < obj.ROW; r++) {

          arr.push([]);

          for (c = 0; c < obj.CELL; c++) {

            arr[r][c] = 0;

            if (obj.createEle == 1) {

              obj.create(r, c);

            }

          }

        }

        if (obj.createEle == 1) {

          obj.createEle = 0;

          $("gridPanel").innerHTML = ""; //清空原有的元素

          $("gridPanel").appendChild(obj.eleFragment); //添加元素

        }

        obj.score = 0;

        $("score").innerHTML = obj.score;

        $("game").style.display = "none";

        $("gameover").style.display = "none";

        obj.random(); //开始游戏随机生成两个数

        obj.random();

        obj.updateView();

      },

      //创建div元素,添加到gridPanel

      create: function(r, c) {

        var grid, cell;

        var increment = 14,

          grWidth, grHeight, grMarginTop, grMarginLeft, ceWidth, ceHight;

        grid = document.createElement("div");

        cell = document.createElement("div");

        grid.id = "g" + r + c;

        grid.className = "grid";

        cell.id = "c" + r + c;

        cell.className = "cell";

 

        if (obj.ROW == 3) {

          increment = 24;

        } else if (obj.ROW == 4) {

          increment = 18;

        }

        grWidth = grHeight = ceWidth = ceHight = 66 + (6 - obj.ROW) * increment; //优化后

        grMarginTop = grMarginLeft = (480 - grWidth * obj.ROW) / (obj.ROW + 1);

        grid.style.width = grWidth + "px";

        grid.style.height = grHeight + "px";

        grid.style.marginTop = grMarginTop + "px";

        grid.style.marginLeft = grMarginLeft + "px";

        cell.style.width = ceWidth + "px";

        cell.style.height = ceHight + "px";

        cell.style.top = grMarginTop + r * (grMarginTop + ceWidth) + "px";

        cell.style.left = grMarginLeft + c * (grMarginLeft + ceHight) + "px";

        cell.style.lineHeight = ceHight + "px";

        cell.style.fontSize = 30 + (6 - obj.ROW) * 10 + "px";

        //优化前

        /*if (obj.ROW == 3) {

          grid.style.width = "140px";

          grid.style.height = "140px";

          grid.style.margin = "15px 0 0 15px";

          cell.style.width = "140px";

          cell.style.height = "140px";

          cell.style.top = 15 + r * 155 + "px"; //设置距离上一位置的高度

          cell.style.left = 15 + c * 155 + "px"; //设置离左一位置的距离

          cell.style.lineHeight = "140px";

        } else if (obj.ROW == 4) {

          grid.style.width = "100px";

          grid.style.height = "100px";

          grid.style.margin = "16px 0 0 16px";

          cell.style.width = "100px";

          cell.style.height = "100px";

          cell.style.top = 16 + r * 116 + "px";

          cell.style.left = 16 + c * 116 + "px";

          cell.style.lineHeight = "100px";

        } else if (obj.ROW == 5) {

          grid.style.width = "75px";

          grid.style.height = "75px";

          grid.style.margin = "17.5px 0 0 17.5px";

          cell.style.width = "75px";

          cell.style.height = "75px";

          cell.style.top = 17.5 + r * 92.5 + "px";

          cell.style.left = 17.5 + c * 92.5 + "px";

          cell.style.fontSize = "40px";

          cell.style.lineHeight = "75px";

        } else if (obj.ROW == 6) {

          grid.style.width = "66px";

          grid.style.height = "66px";

          grid.style.margin = "12px 0 0 12px";

          cell.style.width = "66px";

          cell.style.height = "66px";

          cell.style.top = 12 + r * 78 + "px";

          cell.style.left = 12 + c * 78 + "px";

          cell.style.fontSize = "30px";

          cell.style.lineHeight = "66px";

        }*/

        obj.eleFragment.appendChild(grid);

        obj.eleFragment.appendChild(cell);

      },

      //随机产生一个新的数

      random: function() {

        while (1) {

          var row = Math.floor(Math.random() * obj.ROW);

          var cell = Math.floor(Math.random() * obj.CELL);

          if (arr[row][cell] == 0) { //判断生成的随机数位置为0才随机生成24

            arr[row][cell] = (Math.random() > 0.5) ? 4 : 2;

            break;

          }

        }

        // var row = Math.floor(Math.random() * 4);

        // var cell = Math.floor(Math.random() * 4);

        // if (arr[row][cell] == 0) { //判断生成的随机数位置为0才随机生成24

        //   arr[row][cell] = (Math.random() > 0.5) ? 4 : 2;

        //   return;

        // }

        // obj.random();//递归影响执行效率

      },

      //更新页面

      updateView: function() {

        var win = 0;

        for (r = 0; r < obj.ROW; r++) {

          for (c = 0; c < obj.CELL; c++) {

            if (arr[r][c] == 0) { //值为0的不显示

              $("c" + r + c).innerHTML = ""; //0不显示

              $("c" + r + c).className = "cell" //清除样式

            } else {

              $("c" + r + c).innerHTML = arr[r][c];

              $("c" + r + c).className = "cell n" + arr[r][c]; //添加不同数字的颜色

              if (obj.ROW == 3 && arr[r][c] == 1024) {

                win = 1;

              } else if (obj.ROW == 4 && arr[r][c] == 2048) {

                win = 1;

              } else if (obj.ROW == 5 && arr[r][c] == 4096) {

                win = 1;

              } else if (obj.ROW == 6 && arr[r][c] == 8192) {

                win = 1;

              }

            }

          }

        }

        if (win == 1) { //通关

          $("game").style.display = "block";

          $("gameover").style.display = "block";

          $("Score").innerHTML = "You win!<br>Score:" + obj.score;

        }

        if (obj.isGameOver()) { //游戏失败

          $("game").style.display = "block";

          $("gameover").style.display = "block";

          $("Score").innerHTML = "GAME OVER!<br>Score:" + obj.score;

          console.log("gameover");

        }

      },

      //游戏失败

      isGameOver: function() {

        for (r = 0; r < obj.ROW; r++) {

          for (c = 0; c < obj.CELL; c++) {

            if (arr[r][c] == 0) { //0还不是gameover

              return false;

            } else if (c != obj.CELL - 1 && arr[r][c] == arr[r][c + 1]) { //左往右  前一个和下一个不相等

              return false;

            } else if (r != obj.ROW - 1 && arr[r][c] == arr[r + 1][c]) { //上往下 上一个和下一个不相等

              return false;

            }

          }

        }

        return true;

      },

      //查找下一个不为0的数值的位置

      find: function(r, c, start, condition, direction) {

        if (obj.keyCd == 2) { //上下按键

          if (direction == 1) { //向上按键  f++

            for (var f = start; f < condition; f += direction) {

              if (arr[f][c] != 0) {

                return f;

              }

            }

          } else { //向下按键 f--

            for (var f = start; f >= condition; f += direction) {

              if (arr[f][c] != 0) {

                return f;

              }

            }

          }

 

        } else { //左右按键

          if (direction == 1) { //左按键   f++

            for (var f = start; f < condition; f += direction) {

              if (arr[r][f] != 0) {

                return f;

              }

            }

          } else { //右按键  f--

            for (var f = start; f >= condition; f += direction) {

              if (arr[r][f] != 0) {

                return f;

              }

            }

          }

        }

        return null; //循环结束仍然没有找到!=0的数值,返回null

      },

      //左按键的处理

      dealToLeft: function(r) {

        var next;

        for (c = 0; c < obj.ROW; c++) {

          next = obj.find(r, c, c + 1, obj.CELL, 1); //找出第一个不为0的位置

          if (next == null) break; //没有找到就返回

          //如果当前位置为0

          if (arr[r][c] == 0) {

            arr[r][c] = arr[r][next]; //把找到的不为0的数值替换为当前位置的值

            arr[r][next] = 0; //找到的位置清0

            c--; //再次循环多一次,查看后面否有值与替换后的值相同,

          } else if (arr[r][c] == arr[r][next]) { //如果当前位置与找到的位置数值相等,则相加

            arr[r][c] *= 2;

            arr[r][next] = 0;

            obj.score += arr[r][c];

          }

        }

      },

      move: function(itertor) {

        var before, //没处理前

          after; //after处理后

        before = arr.toString();

        itertor(); //执行for函数

        after = arr.toString();

        if (before != after) { //前后对比,如果不同就update

          obj.random();

          obj.updateView();

        }

      },

      moveLeft: function() {

        obj.move(function() {

          for (r = 0; r < obj.ROW; r++) {

            obj.dealToLeft(r);

          }

        })

        // if 当前位置 不为零

        // 从当前位置,下一个成员开始,遍历,

        // 如果找到,与当前位置相等的数,

        // 两者相加,并把不为零的成员,设置为零

        // 如果 当前位置是 零

        // 从当前位置下一个成员开始遍历

        // 如果找到 第一个不为零的成员

        // 当前位置数值设置为这个不为零的成员的值 ,并且把那个不为零的成员设置为 0

      },

      //右按键处理

      dealToRight: function(r) {

        var next;

        for (c = obj.CELL - 1; c >= 0; c--) {

          next = obj.find(r, c, c - 1, 0, -1); //找出第一个不为0的位置

          if (next == null) break; //没有找到就返回

          //如果当前位置为0

          if (arr[r][c] == 0) {

            arr[r][c] = arr[r][next]; //把找到的不为0的数值替换为当前位置的值

            arr[r][next] = 0; //找到的位置清0

            c++; //再次循环多一次,查看后面否有值与替换后的值相同,

          } else if (arr[r][c] == arr[r][next]) { //如果当前位置与找到的位置数值相等,则相加

            arr[r][c] *= 2;

            arr[r][next] = 0;

            obj.score += arr[r][c];

          }

        }

      },

      moveRight: function() {

        obj.move(function() {

          for (r = 0; r < obj.ROW; r++) {

            obj.dealToRight(r);

          }

        })

      },

      //上按键处理

      dealToUp: function(c) {

        var next;

        for (r = 0; r < obj.ROW; r++) {

          next = obj.find(r, c, r + 1, obj.ROW, 1); //找出第一个不为0的位置

          if (next == null) break;

          //如果当前位置为0

          if (arr[r][c] == 0) {

            arr[r][c] = arr[next][c]; //把找到的不为0的数值替换为当前位置的值

            arr[next][c] = 0; //找到的位置清0

            r--; //再次循环多一次,查看后面否有值与替换后的值相同

          } else if (arr[r][c] == arr[next][c]) { //如果当前位置与找到的位置数值相等,则相加

            arr[r][c] *= 2;

            arr[next][c] = 0;

            obj.score += arr[r][c];

          }

        }

      },

      moveUp: function() {

        obj.move(function() {

          for (c = 0; c < obj.CELL; c++) {

            obj.dealToUp(c);

          }

        })

      },

      //下按键处理

      dealToDown: function(c) {

        var next;

        for (r = obj.ROW - 1; r >= 0; r--) {

          next = obj.find(r, c, r - 1, 0, -1); //找出第一个不为0的位置

          if (next == null) {

            break;

          }

          //如果当前位置为0

          if (arr[r][c] == 0) {

            arr[r][c] = arr[next][c]; //把找到的不为0的数值替换为当前位置的值

            arr[next][c] = 0; //找到的位置清0

            r++; //再次循环多一次,查看后面否有值与替换后的值相同

          } else if (arr[r][c] == arr[next][c]) { //如果当前位置与找到的位置数值相等,则相加

            arr[r][c] *= 2;

            arr[next][c] = 0;

            obj.score += arr[r][c];

          }

        }

      },

      moveDown: function() {

        obj.move(function() {

          for (c = 0; c < obj.CELL; c++) {

            obj.dealToDown(c);

          }

        })

      }

    }

    window.onload = function() {

      obj.createEle = 1;

      obj.gameStart();

    }

    //切换模式

    function getModel(e) { //事件冒泡获取a元素

      var a = e.target,

        modelValue = 4;

      if (a.nodeName == "A") {

        if (a.innerHTML == "3X3") {

          modelValue = 3;

        } else if (a.innerHTML == "4X4") {

          modelValue = 4;

        } else if (a.innerHTML == "5X5") {

          modelValue = 5;

        } else if (a.innerHTML == "6X6") {

          modelValue = 6;

        }

        obj.ROW = obj.CELL = modelValue;

        obj.createEle = 1; //需要创建格子div元素的标志

        obj.gameStart();

      }

    }

 

    //   var modelValue = parseInt($("model").value);

    //   if (isNaN(modelValue)) {

    //     modelValue = 4; //默认是4*4

    //   }

    //   if (modelValue <= 2 || modelValue > 6) return; //2格或者大于6格无效

    //   obj.ROW = modelValue;

    //   obj.CELL = modelValue;

    //   obj.createEle = 1;

    //   obj.gameStart();

    //   console.log(modelValue);

    // }

  </script>

 

</body>

 

</html>

想要学习前端的同学,可以加群:543#6273#93 学习哦!

以上是关于用原生js写2048小游戏的主要内容,如果未能解决你的问题,请参考以下文章

用原生js写2048小游戏

原生js写一个2048游戏

2048小游戏——CSS/原生js爬坑之纯CSS模态对话框&游戏结束

纯JS写的2048游戏,分享之

用原生js写小游戏--Flappy Bird

用js实现2048小游戏