过程化开发2048智力游戏WebApp

时间荏苒,唯编程与青春不可辜负,感觉自己一直没有专心去提升编程的技能,甚是惭愧!!!

周五,无意间看到一个开发2048的视频,有点兴趣就动起手来了,虽然不擅长前端开发,在此献丑,分享一下自己使用过程化开发2048的编码思考与过程。

既然要开发2048,大部分人应该都玩过,如果你有更好的建议可以给我留言O(∩_∩)O~

目录结构

  • 1.什么是2048?
  • 2.玩2048技巧?
  • 3.移动端开发注意事项?
  • 4.游戏设计图?
  • 5.HTML编写?
  • 6.CSS编写
  • 7.JavaScript游戏模型编写?
  • 8.JavaScript游戏逻辑编写?
  • 9.JavaScript游戏特效编写?
  • 10.打包APP?

什么是2048?

2048有16个格子,初始时会有两个格子上安放了两个数字2,每次可以选择上下左右其中一个方向去滑动,每滑动一次,所有的数字方块都会往滑动的方向靠拢外,系统也会在空白的地方随即出现一个数字方块,相同数字的方块在靠拢、相撞时会相加。

玩2048技巧?

1、最大数尽可能放在角落。

2、数字按顺序紧邻排列。

3、首先满足最大数和次大数在的那一列/行是满的。

4、时刻注意活动较大数(32以上)旁边要有相近的数。

5、以大数所在的一行为主要移动方向

6、不要急于“清理桌面”。

移动端开发注意事项?

屏幕宽度:

开发移动端页面时,必须设置适应移动端显示代码:

1 <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width">

触屏事件:

基于移动端开发一定要支持触屏touch事件。

因为我开发选用JQ支持,所以引入了JQuery.touch.js

JQuery.min.js下载:http://www.netcu.de/templates/netcu/js/jquery-1.4.2.min.js

JQuery.touch.js 下载:http://www.netcu.de/templates/netcu/js/jquery.touchwipe.js

JQuery.touch.js 实现大概原理:

 1 (function($) {
 2    $.fn.touchwipe = function(settings) {
 3      var config = {
 4             min_move_x: 20,
 5              wipeLeft: function() { alert("left"); },
 6              wipeRight: function() { alert("right"); },
 7             preventDefaultEvents: true
 8      };
 9
10      if (settings) $.extend(config, settings);
11
12      this.each(function() {
13          var startX;
14          var isMoving = false;
15
16          function cancelTouch() {
17              this.removeEventListener(‘touchmove‘, onTouchMove);
18              startX = null;
19              isMoving = false;
20          }
21
22          function onTouchMove(e) {
23              if(config.preventDefaultEvents) {
24                  e.preventDefault();
25              }
26              if(isMoving) {
27                  var x = e.touches[0].pageX;
28                  var dx = startX - x;
29                  if(Math.abs(dx) >= config.min_move_x) {
30                     cancelTouch();
31                     if(dx > 0) {
32                         config.wipeLeft();
33                     }
34                     else {
35                         config.wipeRight();
36                     }
37                  }
38              }
39          }
40
41          function onTouchStart(e)
42          {
43              if (e.touches.length == 1) {
44                  startX = e.touches[0].pageX;
45                  isMoving = true;
46                  this.addEventListener(‘touchmove‘, onTouchMove, false);
47              }
48          }
49
50          this.addEventListener(‘touchstart‘, onTouchStart, false);
51      });
52
53      return this;
54    };
55
56  })(jQuery);

这样子,我们就可以支持wipeLeft、wipeRight、wipeDown、wipeUp事件了。

注意:在移动端click事件会延迟300ms

游戏设计图?

看看我们2048设计图:

HTML编写?

页面编写过程:

最外层我使用一个div,里面的4*4一共使用16个div。

只要外层的div使用relative相对定位,然后内部的单元格div使用absolute绝对定位。然后使用js代码计算对应单元格的Left与Top值。

HTML代码如下:

 1 <!DOCTYPE html>
 2 <html>
 3 <head>
 4     <title>2048</title>
 5     <link type="text/css" rel="stylesheet" href="./lib/style.css" />
 6     <meta charset="utf-8">
 7     <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width">
 8
 9     <script src="./lib/jquery.min.js"></script>
10     <script src="./lib/jquery.touchSwipe.min.js"></script>
11
12     <script src="./lib/data.js"></script>
13     <script src="./lib/function.js"></script>
14     <script src="./lib/animation.js"></script>
15     <script src="./lib/main.js"></script>
16 </head>
17 <body>
18     <div class="main">
19         <div class="header">
20                 <h4>2048</h4>
21                 <div class="score">Score&nbsp;:&nbsp;<span id="score">0</span></div>
22                 <div class="new_game" id="new_game">New Game</div>
23         </div>
24         <div class="msg"><span id="msg">GameOver.</span></div>
25         <div class="game-panel">
26             <div class="wall">
27                 <div class="cell" id="box-cell-0-0"></div>
28                 <div class="cell" id="box-cell-0-1"></div>
29                 <div class="cell" id="box-cell-0-2"></div>
30                 <div class="cell" id="box-cell-0-3"></div>
31                 <div class="cell" id="box-cell-1-0"></div>
32                 <div class="cell" id="box-cell-1-1"></div>
33                 <div class="cell" id="box-cell-1-2"></div>
34                 <div class="cell" id="box-cell-1-3"></div>
35                 <div class="cell" id="box-cell-2-0"></div>
36                 <div class="cell" id="box-cell-2-1"></div>
37                 <div class="cell" id="box-cell-2-2"></div>
38                 <div class="cell" id="box-cell-2-3"></div>
39                 <div class="cell" id="box-cell-3-0"></div>
40                 <div class="cell" id="box-cell-3-1"></div>
41                 <div class="cell" id="box-cell-3-2"></div>
42                 <div class="cell" id="box-cell-3-3"></div>
43             </div>
44         </div>
45     </div>
46     <div class="footer">Hatcher make.2016</div>
47 </body>
48 </html>

header这个div显示标题,然后得分,以及一个开始游戏的button。

wall这个div就是游戏的主体部分。

CSS编写?

对应的CSS如下:

 1 *{
 2     margin: 0px 0px;
 3     padding: 0px 0px;
 4 }
 5 .main{
 6     font-family: "微软雅黑";
 7     text-align: center;
 8 }
 9 .header{
10     border: 5px solid #fff;
11     height: 120px;
12     border-radius: 2px;
13     position: relative;
14 }
15 .header h4{
16     width: 100px;
17     height: 100px;
18     color:#fff;
19     font-size: 32px;
20     line-height: 100px;
21     margin: 10px;
22     border-radius: 6px;
23     background-color: #ffad2d;
24 }
25 .header .score{
26     color: #ffad2d;
27     font-size: 20px;
28     font-weight: bold;
29     position: absolute;
30     top: 20px;
31     left: 150px;
32 }
33 .header .new_game{
34     color: #ffffff;
35     background-color: #19B8C8;
36     padding: 8px 10px;
37     font-size: 22px;
38     font-weight: bold;
39     position: absolute;
40     border-radius: 2px;
41
42     top: 60px;
43     left: 150px;
44 }
45 .header .new_game:active{
46     background-color: #e15661;
47 }
48 .msg{
49     font-size: 22px;
50     font-weight: bold;
51     line-height: 100px;
52     color: #ff3d44;
53 }
54 .game-panel{
55     height: 300px;
56     width: 250px;
57     margin: 20px auto;
58 }
59 .game-panel .wall{
60     padding: 10px;
61     width: 230px;
62     height: 230px;
63     background-color: #bbada0;
64     border-radius: 6px;
65     position: relative;
66 }
67
68 .game-panel .wall .cell{
69     width: 50px;
70     height: 50px;
71     background-color: #ccc0b3;
72     border-radius: 4px;
73     position: absolute;
74 }
75
76 .game-panel .wall .number-cell{
77     font-size: 25px;
78     font-weight: bold;
79     color: #fff;
80     border-radius: 4px;
81     line-height: 50px;
82     width: 0px;
83     height: 0px;
84     position: absolute;
85 }
86 .footer {
87     font-family: "微软雅黑";
88     font-weight: bold;
89     font-size: 15px;
90     bottom: 0px;
91     line-height: 30px;
92     text-align: center;
93     position: static;
94 }

嘿嘿,我觉得这个css写得有些牵强了。

好,我们先看看这个时候的效果:

JavaScript编写?

很明显,中间的格子都没有摆放整齐。

没事,我们接下来,就使用js将格子摆放整齐。

从设计图中,我们很容易看出。

单元格(0,0)对应的left与top值应该是:10px , 10px

单元格(0,1)对应的left与top值应该是:10+60px , 10px

单元格(0,2)对应的left与top值应该是:10+60px+60px , 10px

..............依次类推

可以得到两个函数:

1 function getLeftPos(i,j){
2     return 10+60*j;
3 }
4
5 function getTopPos(i,j){
6     return 10+60*i;
7 }

那个,初始化内部16个单元的function怎么写呢?

1 function init_grid() {
2     for (var i = 0; i <= 3; i++) {
3         for (var j = 0; j <= 3; j++) {
4             $cell = $("#box-cell-" + i + "-" + j);
5             $cell.css("left", getLeftPos(i, j));
6             $cell.css("top", getTopPos(i, j));
7         }
8     }
9 }

ok,真的挺有意思的。

看看效果图

好像还挺简单的。

游戏数据模型?

页面的编写已经差不多了。

接下来,我们该考虑数据模型层了。

 1 var lock = false;
 2 var cell_grid = [
 3     [0,0,0,0],
 4     [0,0,0,0],
 5     [0,0,0,0],
 6     [0,0,0,0]
 7 ];
 8
 9 var game_score = 0;
10
11 var color_cell = new Array();
12 color_cell[2]       = "#eee4da";
13 color_cell[4]       = "#ede0c8";
14 color_cell[8]       = "#f2b179";
15 color_cell[16]      = "#f59563";
16 color_cell[32]      = "#f67c5f";
17 color_cell[64]      = "#f65e3b";
18 color_cell[128]     = "#edcf72";
19 color_cell[256]     = "#edcc61";
20 color_cell[512]     = "#9c0";
21 color_cell[1024]    = "#33b5e5";
22 color_cell[2048]    = "#09c";
23 color_cell[4096]    = "#a6c";
24 color_cell[8192]    = "#93c";
25
26 var font_cell = new Array();
27 font_cell[2]       = "25px";
28 font_cell[4]       = "25px";
29 font_cell[8]       = "23px";
30 font_cell[16]      = "21px";
31 font_cell[32]      = "21px";
32 font_cell[64]      = "21px";
33 font_cell[128]     = "18px";
34 font_cell[256]     = "18px";
35 font_cell[512]     = "18px";
36 font_cell[1024]    = "15px";
37 font_cell[2048]    = "15px";
38 font_cell[4096]    = "15px";
39 font_cell[8192]    = "15px";

声明定义了,4*4单元格对应的数值二维数组,0就代表空。还有对应的数值的颜色和字体大小范围。

注意,我们需要动态生成一个数字放在每个单元格之上,所以,我们需要在每个单元格内使用一个div进行盛放我们的数字,若非零即显示数值。

 1 function init_view() {
 2     for (var i = 0; i <= 3; i++) {
 3         for (var j = 0; j <= 3; j++) {
 4             $number_cell = $("<div class=‘number-cell‘ id=‘number-cell-" + i + "-" + j + "‘></div>");
 5             $number_cell.css("left", getLeftPos(i, j) + 25);
 6             $number_cell.css("top", getTopPos(i, j) + 25);
 7             $(".wall").append($number_cell);
 8         }
 9     }
10 }

这样,我们每个单元格就有了显示数值的一个容器div。

当对应单元格数值为0,这个div的width,height都为0px。(也就是什么看不到,呵呵)

当对应单元格数值大于0,这个div的width和height等于单元格的宽和高。这样这个数值就覆盖了单元格。

看看要实现的效果图:

对应的数值容器:0,2,0,4

再说一下游戏的规则,每次游戏开始时候,就自动随机生成两个2/4的数值。

所以,我们需要随机在单元格中,寻找为0的位置并设置其数值为2/4。

 1 function create_two_number() {
 2
 3     {
 4         var i = Math.floor(Math.random() * 4);
 5         var j = Math.floor(Math.random() * 4);
 6         var n = Math.floor(Math.random() * 4);
 7         var m = Math.floor(Math.random() * 4);
 8
 9     }
10     while (cell_grid[i][j] != 0 || cell_grid[n][m] != 0);
11     var number1 = Math.random() > 0.5 ? 4 : 2;
12     var number2 = Math.random() > 0.5 ? 4 : 2;
13
14     cell_grid[i][j] = number1;
15     cell_grid[n][m] = number2;
16 }

游戏控制逻辑?

因为整个程序都是JS编写的,所以我们的游戏采用事件驱动编写:

绑定touch滑动事件如下:

 1 $(".game-panel").swipe({
 2         swipe: function (event, direction, distance, duration, fingerCount) {
 3             var can_handler = false;
 4             switch (direction) {
 5                 case ‘left‘: //left
 6                     if (can_left()) {
 7                         handle_left();
 8                     }
 9                     break;
10                 case ‘up‘: //up
11                     break;
12                 case ‘right‘: //right
13                     break;
14                 case ‘down‘: //down
15                     break;
16                 default :
17
18             }
19         }
20     });

关键两个游戏逻辑控制函数

can_left 是否可以左移动:

规则,遍历靠右侧的三列单元格,如果存在当前单元格的前一个单元格为空,或者等于当前单元格。

 1 function can_left(){
 2     for(var i=0 ; i<=3 ;i++){
 3         for(var j=1 ; j<=3 ;j++){
 4             if(cell_grid[i][j] != 0){
 5                 if(cell_grid[i][j-1] == 0 || cell_grid[i][j-1] == cell_grid[i][j]){
 6                     return true;
 7                 }
 8             }
 9         }
10     }
11     return false;
12 }

handle_left 进行左移动操作:

规则,遍历右侧三列单元格:

然后对每个单元格进行检查,如果存在单元格为0并且,该0单元格到检查中单元格可以走通,则可以进行操作移动。或者存在单元格等于检查中单元格,并也可以走通,则可以进行操作移动。

 1 function handle_left(){
 2     for(var i=0 ; i<=3 ;i++){
 3         for(var j=1 ; j<=3 ;j++){
 4             if(cell_grid[i][j] != 0){
 5                 for(var k=0 ; k<j ; k++){
 6                     if(cell_grid[i][k] == 0 && has_road(i,k,i,j)){
 7                         cell_grid[i][k] = cell_grid[i][j];
 8                         cell_grid[i][j] = 0;
 9                         player_run_view(i,j,i,k);
10                         break;
11                     }else if(cell_grid[i][k] == cell_grid[i][j] && has_road(i,k,i,j)){
12                         game_score += cell_grid[i][j];
13                         $("#score").text(game_score);
14                         cell_grid[i][k] += cell_grid[i][j];
15                         cell_grid[i][j] = 0;
16                         player_run_view(i,j,i,k);
17                         break;
18                     }
19                 }
20             }
21         }
22     }
23 }

其他right、down、up都是同理。

滑动特效编写?

 1 function player_set_number_view(i,j,number){
 2     var cell = $("#number-cell-"+i+"-"+j);
 3     cell.text(number);
 4     cell.css("background-color",color_cell[number]);
 5     cell.css("font-size",font_cell[number]);
 6     cell.animate({left:getLeftPos(i,j),top:getTopPos(i,j),width:50,height:50},150);
 7 }
 8
 9 function player_run_view(i,j,i,k){
10     var cell = $("#number-cell-"+i+"-"+j);
11     cell.animate({left:getLeftPos(i,k),top:getTopPos(i,k)},180);
12 }
13
14 function player_run_vertical_view(i,j,k,j){
15     var cell = $("#number-cell-"+i+"-"+j);
16     cell.animate({left:getLeftPos(k,j),top:getTopPos(k,j)},180);
17 }

最终效果图:

打包APP?

使用phoneGap进行打包,将代码拷贝到asset目录www下:

完成:

最后形成APK就可以到手机安装了:

最后安装好:

谢谢!!!

时间: 2024-10-12 08:32:57

过程化开发2048智力游戏WebApp的相关文章

C# 开发2048小游戏

这应该是几个月前,闲的手痒,敲了一上午代码搞出来的,随之就把它丢弃了,当时让别人玩过,提过几条更改建议,但是时至今日,我也没有进行过优化和更改(本人只会作案,不会收场,嘎嘎),下面的建议要给代码爱好的童鞋完成了. 更改建议: a.当数字超过四位数时,显示的时候有部分被它的容器TextBox遮挡了,能不能把显示的数值变小点?答案是可以的.代码里有一段通过矩阵数据填充TextBox值的操作,可以在填充时,判断下数值长度,然后修改TextBox的文字大小. b.玩游戏的时候,使用方向键移动时,焦点可能

【VC++游戏开发】智力游戏——鸡蛋里挑骨头(仿扫雷)

在我学习游戏开发的过程中,遇到的最大的麻烦就是不知道一个游戏的完整实现过程,代码倒是其次. 这里,总结一下我做过的游戏.主要是梳理整每一个步骤. 先看下终于的效果 第1步,准备素材图片 包含鸡蛋.骨头,还有数字以及骨头标识和砸鸡蛋用的小锤. 第2步,声明 Egg类 它仅仅包括2个成员变量 class CEgg { public: int bitmap; //位图 int num; //数目 }; 第2步,初始化界面 1.1 还是要在CMainFrame中设置窗体參数以及图标 1.2 和 五子棋游

【Winform开发2048小游戏】

先来看一下界面: 游戏帮助类 class GameCore { //游戏地图 private int[,] map = new int[4, 4]; //合并时用到的临时数组 private int[] mergeArr = new int[4]; //空位数量 private int emptyCount = 16; //所有空位位置 private Location[] emptyArr = new Location[16]; private Random random = new Rand

终端游戏开发 : 开发2048...

2048这个游戏应该是没几个人不知道吧... 今天去实验楼学了一下这个游戏的终端版本, 大概讲一下我对这个游戏的开发思路的理解. 实现为了实现2048, 我们需要用到3个模块, 分别是curses(用于终端界面交互程序开发的库, 可以解决屏幕打印以及按键处理等方面的问题), random, 以及collections 中的 defaultdict. 第一个库比较复杂, 我之前也没接触过, 不过隐隐感觉是一个功能强大的库, 我之后会专门研究它的官方文档, 目前暂且放在一边, 所幸2048中对这个库

我也来开发2048之终极奥义

本次教程跟之前隔了不少时间哈,有点忘记了的建议先看看前面的熟悉下,今天我准备把这个2048给结束了,拖了这么久. 按照惯例,我们已经把准备工作都做好了,今天这一部分信息量比较大,也是整个游戏的核心所在,所以我准备分功能来讲,最后大家结合源码来看就不会感觉太吃力了. 1.初始化游戏 初始化的时候,我们要干嘛呢,首先要看配置,配置了几行,然后先画好面板,然后要给在面板上随机生成2个数字Item,这涉及到2个方法,一个是初始化面板,一个是添加随机数字 private void initGameView

Asp.Net MVC 插件化开发简化方案

Web 管理系统可以庞大到不可想像的地方,如果想就在一个 Asp.Net MVC 项目中完成开发,这个工程将会变得非常庞大,协作起来也会比较困难.为了解决这个问题,Asp.Net MVC 引入了 Areas 的概念,将模块划分到 Area 中去--然而 Area 仍然是主项目的一部分,多人协作的时候仍然很容易造成 .csproj 项目文件的冲突. 对于这类系统,比较好的解决办法是采用 SOA 的方式,把一个大的 Web 系统划分成若干微服务,通过一个含授权中心的 Web 集散框架组织起来.不过这

大熊君JavaScript插件化开发------(实战篇之DXJ UI ------ ProcessBar)

一,开篇分析 Hi,大家好!大熊君又和大家见面了,还记得前两篇文章吗.主要讲述了以“jQuery的方式如何开发插件”,以及过程化设计与面向对象思想设计相结合的方式是 如何设计一个插件的,两种方式各有利弊取长补短,本系列文章是以学习为导向的,具体场景大家自己定夺使用方式.那么今天从这篇文章开始,我们就以实例 的方式带着大家由浅入深的开发属于自己的插件库.嘿嘿嘿,废话少说,进入正题.直接上实际效果图: 大家看到了吧,这是一个进度条插件,在我们日常开发中,有时我们会有一个装载数据的进度提示,如果无任何

大熊君JavaScript插件化开发------(实战篇之DXJ UI ------ ItemSelector)

一,开篇分析 Hi,大家好!大熊君又和大家见面了,还记得前两篇文章吗.主要讲述了以“jQuery的方式如何开发插件”,以及过程化设计与面向对象思想设计相结合的方式是 如何设计一个插件的,两种方式各有利弊取长补短,本系列文章是以学习为导向的,具体场景大家自己定夺使用方式.那么今天从这篇文章开始,我们就以实例 的方式带着大家由浅入深的开发属于自己的插件库.嘿嘿嘿,废话少说,进入正题.直接上实际效果图: 大家看到了吧,这是一个下拉菜单插件,在我们日常开发中,系统提供的可能有时让我们觉得不是很美观并且功

使用Html5+C#+微信 开发移动端游戏详细教程 :(三)使用html5引擎搭建游戏框架

教程里的案例我们是通过H5游戏引擎开发,目前H5的游戏引擎比较好用的是白鹭,不过对于新手来说白鹭的开发环境和工具使用过于复杂,这里推荐一个国内大神编写的游戏引擎:lufylegend. 直接在页面引入Js文件,就可以开发了,运行效率非常高效,语法是仿AS3语法,懂C#的人上手会很快. Lufylegend引擎具体的API和使用方法可以参考官网和论坛: http://www.lufylegend.com/api/zh_CN/out/classes/FPS.html 之前微信上有一款"怪兽必须死&q