D&G`s BloG V3.0.0

2018,再出发!

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

原生 JavaScript 2048 源码 :

<!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>

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

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

点赞

发表评论

电子邮件地址不会被公开。 必填项已用*标注