前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【 数字游戏 2048 】原生 JavaScript 做小游戏

【 数字游戏 2048 】原生 JavaScript 做小游戏

作者头像
QUXINGDONG.COM
发布2018-04-17 11:55:47
1.1K0
发布2018-04-17 11:55:47
举报
文章被收录于专栏:前端笔记

原生 JavaScript 2048 源码 :

代码语言:javascript
复制
<!doctype html>
<html>

 <head>
 <title>2048</title>
 <meta charset="utf-8">
 <style type="text/css">
 body{
 margin: 0;
 padding: 0;
 }
 #gridPanel {
 width: 480px;
 height: 480px;
 margin: 0 auto;
 position: relative;
 background: #bbada0;
 border-radius: 10px;
 }
 
 .grid,
 .cell {
 width: 100px;
 height: 100px;
 border-radius: 6px;
 }
 
 .grid {
 float: left;
 background: #ccc0b3;
 margin: 16px 0 0 16px;
 }
 
 .cell {
 position: absolute;
 font-size: 60px;
 text-align: center;
 line-height: 100px;
 color: #fff;
 }
 
 [id^="c0"] {
 top: 16px;
 }
 
 [id^="c1"] {
 top: 132px;
 }
 
 [id^="c2"] {
 top: 248px;
 }
 
 [id^="c3"] {
 top: 364px;
 }
 
 [id$="0"] {
 left: 16px;
 }
 
 [id$="1"] {
 left: 132px;
 }
 
 [id$="2"] {
 left: 248px;
 }
 
 [id$="3"] {
 left: 364px;
 }
 
 .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
 }
 
 .n1024,
 .n2048,
 .n4096,
 .n8192 {
 font-size: 40px
 }
 
 p {
 width: 480px;
 margin: 0 auto;
 font-size: 40px;
 font-family: Arial;
 font-weight: bold;
 }
 
 #gameOver {
 display: none;
 position: absolute;
 top: 0;
 left: 0;
 right: 0;
 bottom: 0;
 background: rgba(55, 55, 55, .5);
 }
 
 #gameOver>p {
 width: 300px;
 height: 200px;
 position: absolute;
 top: 50%;
 left: 50%;
 margin-left: -150px;
 margin-top: -100px;
 background: #fff;
 text-align: center;
 line-height: 1.5em;
 border-radius: 10px;
 border: 1px solid #edcf72;
 }
 
 #gameOver .btn {
 padding: 10px;
 color: #fff;
 background: #9f8d77;
 border-radius: 6px;
 text-decoration: none;
 }
 </style>
 </head>

 <body>
 <p>SCORE:<span id="score">0</span></p>
 <div id="gridPanel">
 <div class="grid"></div>
 <div class="grid"></div>
 <div class="grid"></div>
 <div class="grid"></div>
 <div class="grid"></div>
 <div class="grid"></div>
 <div class="grid"></div>
 <div class="grid"></div>
 <div class="grid"></div>
 <div class="grid"></div>
 <div class="grid"></div>
 <div class="grid"></div>
 <div class="grid"></div>
 <div class="grid"></div>
 <div class="grid"></div>
 <div class="grid"></div>
 <div id="c00" class="cell"></div>
 <div id="c01" class="cell"></div>
 <div id="c02" class="cell"></div>
 <div id="c03" class="cell"></div>
 <div id="c10" class="cell"></div>
 <div id="c11" class="cell"></div>
 <div id="c12" class="cell"></div>
 <div id="c13" class="cell"></div>
 <div id="c20" class="cell"></div>
 <div id="c21" class="cell"></div>
 <div id="c22" class="cell"></div>
 <div id="c23" class="cell"></div>
 <div id="c30" class="cell"></div>
 <div id="c31" class="cell"></div>
 <div id="c32" class="cell"></div>
 <div id="c33" class="cell"></div>
 </div>
 <div id="gameOver">
 <p>
 GAME OVER!<br> SCORE: <span id="final">0</span><br>
 <a class="btn" href="javascript:game.start();">TRY AGAIN</a>
 </p>
 </div>
 <script type="text/javascript">
 //Module: 专门操作一类数据的方法和属性的集合
 var game = {
 data: null, //保存游戏的数据:二维数组
 RN: 4,
 CN: 4, //总行数和总列数
 score: 0, //保存游戏得分
 state: 1, //保存游戏状态
 RUNNING: 1, //运行中
 GAMEOVER: 0, //结束
 start: function() { //启动游戏
 this.state = this.RUNNING; //重置游戏状态为启动
 this.score = 0; //得分归零
 //创建空数组保存在data属性中
 this.data = [];
 //r从0开始到<RN结束
 for(var r = 0; r < this.RN; r++) {
 //向data中压入一个空数组
 this.data.push([]);
 //c从0开始到<CN结束
 for(var c = 0; c < this.CN; c++) {
 //将data中r行c列位置赋值为0
 this.data[r][c] = 0;
 }
 }
 this.randomNum();
 this.randomNum();
 //debugger;//必须开着F12
 //console.dir(this.data);//打桩
 //console.log(this.data.join("\n"));
 this.updateView();
 //为页面绑定键盘按下事件
 //当键盘按下时,自动执行之后的function
 //event事件对象: 当事件发生时自动保存所有事件相关信息的对象
 document.onkeydown = function(e) { //event
 if(this.state == this.RUNNING)
 switch(e.keyCode) { //判断e.keyCode
 //是37: 就左移
 case 37:
 this.moveLeft();
 break;
 //是38: 就上移
 case 38:
 this.moveUp();
 break;
 //是39: 就右移
 case 39:
 this.moveRight();
 break;
 //是40: 就下移
 case 40:
 this.moveDown();
 break;
 }
 }.bind(this);
 //document.onkeydown();
 },
 move: function(callback) { //所有移动中相同的代码
 //为data拍照,保存在before中
 var before = String(this.data);
 callback.call(this);
 //为data拍照,保存在after中
 var after = String(this.data);
 if(before != after) { //如果发生了移动
 this.randomNum(); //随机生成数
 //如果游戏结束
 //修改游戏状态为GAMEOVER
 this.updateView(); //更新页面
 }
 },
 isGameOver: function() {
 //遍历data
 //如果当前元素是0,就返回false
 //如果c<CN-1且当前元素等于右侧元素时,就返回false
 //如果r<RN-1且当前元素等于下方元素时,就返回false
 //(遍历结束)
 //返回true
 },
 moveRight: function() { //右移所有行
 this.move(function() {
 //遍历data中每一行
 for(var r = 0; r < this.RN; r++)
 this.moveRightInRow(r); //右移第r行
 });
 },
 moveLeft: function() { //左移所有行
 this.move(function() {
 //遍历data中每一行 r
 for(var r = 0; r < this.RN; r++)
 this.moveLeftInRow(r); //左移第r行
 });
 },
 moveUp: function() {
 this.move(function() {
 //遍历data中每一列
 for(var c = 0; c < this.CN; c++)
 //调用moveUpInCol上移第c列
 this.moveUpInCol(c);
 });
 },
 moveDown: function() {
 this.move(function() {
 //遍历data中每一列
 for(var c = 0; c < this.CN; c++)
 //调用moveDownInCol下移第c列
 this.moveDownInCol(c);
 });
 },
 moveLeftInRow: function(r) { //左移第r行
 //c从0开始,到<CN-1结束,遍历r行中每个格
 for(var c = 0; c < this.CN - 1; c++) {
 //找r行c列右侧下一个不为0的位置nextc
 var nextc = this.getNextInRow(r, c);
 //如果nextc为-1,就退出循环
 if(nextc == -1) {
 break;
 } else { //否则 
 //如果c列的值是0
 if(this.data[r][c] == 0) {
 //将nextc列的值赋值给c列
 this.data[r][c] = this.data[r][nextc];
 //将nextc列的值置为0
 this.data[r][nextc] = 0;
 c--; //c留在原地
 } else if(this.data[r][c] ==
 this.data[r][nextc]) {
 //否则 如果c列的值等于nextc列的值
 this.data[r][c] *= 2; //将c列的值*2
 this.score += this.data[r][c];
 this.data[r][nextc] = 0; //将nextc列置为0 
 }
 }
 }
 },
 moveRightInRow: function(r) { //右移第r行
 //c从CN-1开始,到>0结束,反向遍历r行中每个格
 for(var c = this.CN - 1; c > 0; c--) {
 //找r行c列左侧前一个不为0的位置prevc
 var prevc = this.getPrevInRow(r, c);
 //如果prevc为-1,就退出循环
 if(prevc == -1) {
 break;
 } else { //否则
 if(this.data[r][c] == 0) { //如果c列的值是0
 //将prevc列的值赋值给c列
 this.data[r][c] = this.data[r][prevc];
 //将prevc列的值置为0
 this.data[r][prevc] = 0;
 c++; //c留在原地
 } else if(this.data[r][c] ==
 this.data[r][prevc]) {
 //否则 如果c列的值等于prevc列的值
 this.data[r][c] *= 2; //将c列的值*2
 this.score += this.data[r][c];
 this.data[r][prevc] = 0; //将prevc列置为0
 }
 }
 }
 },
 moveUpInCol: function(c) {
 //r从0开始,到r<RN-1结束,r每次递增1
 for(var r = 0; r < this.RN - 1; r++) {
 //查找r行c列下方下一个不为0的位置nextr
 var nextr = this.getNextInCol(r, c);
 //如果没找到,就退出循环
 if(nextr == -1) {
 break;
 } else { //否则
 //如果r位置c列的值为0
 if(this.data[r][c] == 0) {
 //将nextr位置c列的值赋值给r位置
 this.data[r][c] = this.data[nextr][c];
 //将nextr位置c列置为0
 this.data[nextr][c] = 0;
 r--; //r留在原地
 } else if(this.data[r][c] ==
 this.data[nextr][c]) {
 //否则,如果r位置c列的值等于nextr位置的值
 //将r位置c列的值*2
 this.data[r][c] *= 2;
 this.score += this.data[r][c];
 //将nextr位置c列的值置为0
 this.data[nextr][c] = 0;
 }
 }
 }
 },
 moveDownInCol: function(c) {
 //r从RN-1开始,到r>0结束,r每次递减1
 for(var r = this.RN - 1; r > 0; r--) {
 //查找r位置c列上方前一个不为0的位置prevr
 var prevr = this.getPrevInCol(r, c);
 //如果没找到,就退出循环
 if(prevr == -1) {
 break;
 } else { //否则 
 //如果r位置c列的值为0
 if(this.data[r][c] == 0) {
 //将prevr位置c列的值赋值给r位置
 this.data[r][c] = this.data[prevr][c];
 //将prevr位置c列置为0
 this.data[prevr][c] = 0;
 r++; //r留在原地
 } else if(this.data[r][c] ==
 this.data[prevr][c]) {
 //否则,如果r位置c列的值等于prevr位置的值
 this.data[r][c] *= 2; //将r位置c列的值*2
 this.score += this.data[r][c];
 //将prevr位置c列置为0
 this.data[prevr][c] = 0;
 }
 }
 }
 },
 getPrevInCol: function(r, c) {
 r--; //r-1
 //循环,r到>=0结束,每次递减1
 for(; r >= 0; r--) {
 //如果r位置c列不等于0, 就返回r
 if(this.data[r][c] != 0) return r;
 } //(遍历结束)
 return -1; //返回-1
 },
 getNextInCol: function(r, c) {
 r++; //r+1
 //循环,到<RN结束,r每次递增1
 for(; r < this.RN; r++) {
 //如果r位置c列不等于0, 就返回r
 if(this.data[r][c] != 0) return r;
 } //(遍历结束)
 return -1; //返回-1
 },
 //找r行c列左侧前一个不为0的位置
 getPrevInRow: function(r, c) {
 c--; //c-1
 //从c开始,到>=0结束,反向遍历
 for(; c >= 0; c--) {
 //如果r行c位置不是0,就返回c
 if(this.data[r][c] != 0) return c;
 } //(遍历结束)
 return -1; //返回-1
 },
 //找r行c列右侧下一个不为0的位置
 getNextInRow: function(r, c) {
 c++; //c+1
 //从c开始,到<CN结束
 for(; c < this.CN; c++) {
 //如果r行c位置不是0,就返回c
 if(this.data[r][c] != 0) {
 return c;
 }
 } //(遍历结束)
 return -1; //返回-1
 },
 //将data中的元素更新到页面对应div中
 updateView: function() {
 //遍历data r c
 for(var r = 0; r < this.RN; r++)
 for(var c = 0; c < this.CN; c++) {
 //找到页面中id为cXX的div
 var div = document.getElementById("c" + r + c);
 //如果当前元素不是0
 if(this.data[r][c] != 0) {
 //将data中当前元素放入div的内容中
 div.innerHTML = this.data[r][c];
 //修改div的className属性为"cell n"+当前元素值
 div.className = "cell n" + this.data[r][c];
 } else { //否则
 div.innerHTML = ""; //清空div的内容
 //将div的className重置为cell
 div.className = "cell";
 }
 }
 //找到id为score的span,设置其内容为score属性
 document.getElementById("score") //span
 .innerHTML = this.score;
 //找到id为gameOver的div,设置其style的display属性为: 如果游戏状态为GAMEOVER?"block":"none"
 document.getElementById("gameOver")
 .style.display =
 this.state == this.GAMEOVER ?
 "block" : "none";
 //如果游戏结束,将score写入final
 this.state == this.GAMEOVER && (
 document.getElementById("final")
 .innerHTML = this.score
 );
 },
 //在data的一个随机位置随机生成一个数字
 randomNum: function() {
 while(true) { //反复:
 //在0~RN-1之间生成一个随机数r
 var r = Math.floor(Math.random() * this.RN);
 //在0~CN-1之间生成一个随机数c
 var c = Math.floor(Math.random() * this.CN);
 //如果data中r行c列为0
 if(this.data[r][c] == 0) {
 //将data中r行c列的值设置为: 
 //随机生成一个0~1之间的小数,如果<0.5,就取2,否则取4
 this.data[r][c] = Math.random() < 0.6 ? 2 : 4;
 break; //退出循环
 }
 }
 },
 }
 game.start(); //页面加载后自动启动游戏
 </script>
 </body>

</html

—— 本页面采用“iframe”标签引用文档,请您滑动文档内容进行浏览 [文章最后编辑于:2017/01/16]

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017年1月10日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 原生 JavaScript 2048 源码 :
    • —— 本页面采用“iframe”标签引用文档,请您滑动文档内容进行浏览 [文章最后编辑于:2017/01/16]
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档