用原生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; background-color: #9DA5C3; 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>

Score:
3X3 4X4 5X5 6X6 <!-- <input type="text" id="model"> --> <!-- <button type="button" name="button" id="set">设置游戏</button> -->
<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才随机生成2或4
        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才随机生成2或4
    //   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>

收藏 0分享浏览 1066
3年前
跟帖

朋友们可以加我的Q 1098271199 每天分享一些好玩的技术

沙发

京东京豆项目分享、京东福卡项目分享、超市会员管理系统、汽车租赁系统(上)、汽车租赁系统(下)、动物乐园 +裙498854752 加群分享以上视频项目

板凳

请关注这个~~http://www.toutiao.com/i6402760703672844801/

地板
好小灰灰
1年前

谢谢楼主分享! 我也收集了三款html5版2048游戏 http://www.sucaihuo.com/search?keyword=2048&mtype=2

4 楼
说几句
广告位 点击查看投放指南

我的收藏