web--2048小游戏复现(慕课网)

这周断断续续完成了2048小游戏的网页版,这里主要讲这款游戏的逻辑和代码实现。
参考:慕课网2048私人订制 https://www.imooc.com/learn/76
对着视频把源码敲了一遍,这里作一个思路整理。

一、整体思路

1、游戏页面结构及样式
2、2048游戏逻辑
3、手机端优化
思路可以划分为上三步,在第一步中,首先规划好整体的排版。

页面内容包括2048header、游戏开始button、得分字段

、整个4*4方格grid-container。在container中每一个cell后期都要绑定一个number。

二、游戏页面结构及样式

2048,开始、得分
设置text-align:center;margin左右auto居中,字体背景颜色等;

1
<header>
2
	<h1>2048</h1>
3
	<a href="javascrpit:newgame();">开始</a>
4
	<p>得分</p>
5
</header>

4*4方格,盒子模型

1
<div id="grid-container">
2
	<div id="grid-cell-0-0>
3
	</div>
4
</div>
5
//grid-cell-0-0到3-3

container设置width、height、background,bord-radius边框,padding,margin、position(relative相对定位,相当于浮动)
grid-cell设置width,height、background-color、position(absolute绝对定位,可以被覆盖)
number-cell覆盖每个grid-cell,,其中的数字为border-number,初使为0

三、2048游戏逻辑

1、newgame包括:init初始化游戏,生成gridcell4*4,number-cell清零,随机两个位置,generateOneNumber两次。
(0)生成页面结构后,加载DOM(文档对象模型)。通过$(document).ready()完成,ready事件在生成html标签、元素,显示CSS样式后实现。在ready()事件中执行newgame函数,该函数链接到《开始》按钮。
(1)init:通过类选择器number-cell $(.number-cell).remove()清零,对grid-container中添加number-cell,number-cell中的数字都存在board【】【】二维数组中。
(2)generateOneNumber中随机生成两个位置,和随机2或4,
board[randx][randy]=randNumber;

2、moveLeft、moveRight、moveUp、moveDown键盘操作。moveLeft发生,所有数字左移,相同数字求和。
(0)按下键盘的↑↓←→由$(document).keydown()监听,通过switch–case决定运行moveLeft还是moveRight。
(1)!!!!!重点来了!moveLeft发生,所有数字左移。
两重for循环让每一个board[i][j]都左移(最左侧一列不能移动)
移动的前提是board[i][j]!=0,board[i][k]!=0&&在左移的这段(k~j)距离,不能有阻挡(canMoveLeft)。
(2)if 新位置为0,替换,elseif 新位置与board[i][j]相等,即相加。
(3)向右,上、下思路一样,判断移动的这段距离无阻挡,然后相加或替换。
3、绑定分数,定义score变量,当board[i][k] +=board[i][j]时,score+=board[i][k];
“得分”的id标签为score,通过选择器$(‘#score’).text(score)使得在得分:0处显示分数。
4、game over,判断所有border-number不为零(没有空格),且canMoveLeft等四个函数return false(不能移动)。

四、手机端优化

(0)在手机上与pc端的主要区别:页面大小、控制方式(按键盘和触控)
(1)为了适应手机和pc,加一个获取屏幕大小的函数documentWidth=window.screen.availWidth,if 屏幕宽度大于500像素,认为是PC,grid-container按500像素显示,小于500,按手机来自适应。width和height按%百分比显示。
(2)触控用document.addEventListener监听,包括touchstart、touchmove和touchend。
(3)touchstart获取手指初始位置;touchmove是优化,使得手指点击无效;touchend获取手指离开屏幕的位置,通过xy坐标和滑动产生的位移来判断,执行moveLeft等上下左右四个函数。

注:bug修改
在一排四个格子出现2248这样的情况下,左移结果应该是4480,但是在三、2、(2)中,结果是16000,应该添加hasConflicted二维数组,判断是否加过,保证只加一次。
最后,附上慕课中给的源代码,仅作少量修改,侵删
整体结构:
在这里插入图片描述
index.html

1
<!DOCTYPE html>
2
<html lang="en">
3
<head>
4
    <meta charset="UTF-8">
5
    <meta name="viewport"
6
          content="
7
            width=device_value,
8
            height=device_value,
9
            initial-scale=1.0,
10
            minimum-scale=0.9,
11
            maxmum-scale=1.0,
12
<!--            //用户可以缩小或放大屏幕尺寸的最小最大值-->
13
            user-scalable = yes"
14
          />
15
16
    <title>Title</title>
17
    <link rel="stylesheet" type="text/css" href="2048.css">
18
<!--    <script type="text/javascript" src="https://code.jquery.com/jquery-3.3.1.min.js"></script>-->
19
<!--    <script type="text/javascript" src="http://libs.baidu.com/jquery/1.9.0/jquery.min.js"></script>-->
20
    <script type="text/javascript" src="jquery.min.js"></script>
21
    <script type="text/javascript" src="main2048.js"></script>
22
    <script type="text/javascript" src="showanimation.js"></script>
23
    <script type="text/javascript" src="support2048.js"></script>
24
</head>
25
<body>
26
    <header>
27
        <h1>2048</h1>
28
        <a href="javascript:newgame();" id="newgamebutton">开始</a>
29
        <p>得分: <span id="score">0</span>  </p>
30
    </header>
31
32
    <div id="grid-container">
33
        <div class="grid-cell" id="grid-cell-0-0"></div>
34
        <div class="grid-cell" id="grid-cell-0-1"></div>
35
        <div class="grid-cell" id="grid-cell-0-2"></div>
36
        <div class="grid-cell" id="grid-cell-0-3"></div>
37
38
        <div class="grid-cell" id="grid-cell-1-0"></div>
39
        <div class="grid-cell" id="grid-cell-1-1"></div>
40
        <div class="grid-cell" id="grid-cell-1-2"></div>
41
        <div class="grid-cell" id="grid-cell-1-3"></div>
42
43
        <div class="grid-cell" id="grid-cell-2-0"></div>
44
        <div class="grid-cell" id="grid-cell-2-1"></div>
45
        <div class="grid-cell" id="grid-cell-2-2"></div>
46
        <div class="grid-cell" id="grid-cell-2-3"></div>
47
48
        <div class="grid-cell" id="grid-cell-3-0"></div>
49
        <div class="grid-cell" id="grid-cell-3-1"></div>
50
        <div class="grid-cell" id="grid-cell-3-2"></div>
51
        <div class="grid-cell" id="grid-cell-3-3"></div>
52
53
54
    </div>
55
</body>
56
</html>
57
<!--MVC结构:Model模型、visual界面UIControl逻辑控制-->
58
59
<!--待优化:-->
60
<!--1game over-->
61
<!--2、最高得分-->
62
<!--3、加分动画-->
63
<!--可以通过phoneGapweb APP转换为native app-->
64
<!--网站发布:dropBox&dropPages-->
65
<!--或者发布方式:nginx+花生壳,存在nginx中即可。-->

2048.css

1
header{
2
    display: block;
3
    margin: 0 auto;
4
    width:100%;
5
    text-align: center;
6
}
7
header h1{
8
    font-family: Arial;
9
    font-size: 40px;
10
    font-weight:bold ;
11
}
12
header #newgamebutton{
13
    display: block;
14
    margin: 20px auto;
15
    width: 100px;
16
    padding:10px 10px;
17
    /*background-color: #9efff4;*/
18
    background-color: chocolate;
19
    font-family: Arial;
20
    color: white;
21
    border-radius: 10px;
22
    text-decoration: none;
23
}
24
header #newgamebutton:hover{
25
    background-color: cyan;
26
}
27
28
header p{
29
    font-family:Arial;
30
    font-size: 25px;
31
    margin: 20px auto;
32
}
33
34
#grid-container{
35
    width:460px;
36
    height: 460px;
37
    padding:20px;
38
    /*上下左右各自向外20px,盒子为500*500*/
39
40
    margin: 50px auto;
41
    /*background-color: #bbada0;*/
42
    background-color: #9efff4;
43
    background-color: rgba(22,27,255,0.9);
44
    border-radius: 10px;
45
    position: relative;
46
47
}
48
.grid-cell{
49
    width: 100px;
50
    height: 100px;
51
    border-radius: 6px;
52
    /*background-color: #ccc0b3;*/
53
    background-color: yellowgreen;
54
    position: absolute;
55
}
56
.number-cell{
57
    border-radius:6px;
58
    font-family: Arial;
59
    font-size: 60px;
60
    font-weight: bold;
61
    font-height:100px;
62
    text-align:center;
63
64
    position:absolute;
65
}

main2048.js

1
var board = new Array();
2
var score =0;
3
var hasConflicted = new Array();
4
//用于判断每个小格子是否发生了变化
5
//游戏初始化---------------------------------
6
$(document).ready(function(){
7
    prepareForMobile();
8
    newgame();
9
});
10
function prepareForMobile() {
11
    if( documentWidth > 500 ){
12
        gridContainerWidth = 500;
13
        cellSpace = 20;
14
        cellSideLength = 100;
15
    }
16
    $('#grid-container').css('width',gridContainerWidth-2*cellSpace);
17
    $('#grid-container').css('height',gridContainerWidth-2*cellSpace);
18
    $('#grid-container').css('padding',cellSpace);
19
    $('#grid-container').css('border-radius',0.02*gridContainerWidth)
20
21
    $('.grid-cell').css('width',cellSideLength);
22
    $('.grid-cell').css('height',cellSideLength);
23
    $('.grid-cell').css('border-radius',0.02*cellSideLength);
24
25
    
26
}
27
function newgame() {
28
    //初始化棋盘格
29
    init();
30
    //在随机两个格子生成数字
31
    generateOneNumber();
32
    generateOneNumber();
33
34
}
35
function init() {
36
    for (var i=0; i<4;i++)
37
        for (var j=0;j<4;j++){
38
            var gridCell=$('#grid-cell-'+i+"-"+j);
39
            gridCell.css('top', getPosTop(i, j));
40
            gridCell.css('left', getPosLeft(i, j));
41
            //每个方格的位置由这两个函数决定,在support2048中
42
        }
43
44
    for(var i = 0;i<4;i++){
45
        board[i]=new Array();
46
        hasConflicted[i] = new Array();
47
        for(var j=0;j<4;j++){
48
            board[i][j]=0;
49
            hasConflicted[i][j]= false;
50
        }
51
    }
52
    updateBoardView();
53
    score = 0;
54
}
55
function  updateBoardView(){
56
    $(".number-cell").remove();
57
    // 删除当前所有方格中的值
58
    for (var i=0;i<4;i++)
59
        for (var j=0;j<4;j++){
60
            $("#grid-container").append('<div class="number-cell" id="number-cell-'+i+'-'+j+'"></div>');
61
            var theNumberCell = $('#number-cell-'+i+'-'+j);
62
63
            if (board[i][j]==0){
64
                theNumberCell.css('width','0px');
65
                theNumberCell.css('height','0px');
66
                theNumberCell.css('top',getPosTop(i, j)+cellSideLength/2);
67
                theNumberCell.css('left',getPosLeft(i, j)+cellSideLength/2);
68
            }else{
69
                // 不为零时用number-cell代替gridcell
70
                theNumberCell.css('width',cellSideLength);
71
                theNumberCell.css('height',cellSideLength);
72
                theNumberCell.css('top',getPosTop(i, j));
73
                theNumberCell.css('left',getPosLeft(i, j));
74
                theNumberCell.css('background-color',getNumberBackgroudColor(board[i][j]));
75
                theNumberCell.css('color',getNumberColor(board[i][j]));
76
                // 背景色和前景色
77
                theNumberCell.text(board[i][j]);
78
            }
79
80
            hasConflicted[i][j]= false;
81
        }
82
    $('.number-cell').css('line-height',cellSideLength+'px');
83
    $('.number-cell').css('font-size',0.6*cellSideLength+'px');
84
85
}
86
function generateOneNumber(){//先随机找一个位置,再在这个位置上赋值
87
    if (nospace(board))
88
        return false;
89
    //随机一个位置
90
    var randx=parseInt(Math.floor(Math.random()*4));
91
    var randy=parseInt(Math.floor(Math.random()*4));
92
      //产生0-4直接的浮点数,floor向下取整0123,parseInt强制类型转换为int
93
    var time=0;
94
95
    while(time<30){ //===========================================================不懂
96
        if (board[randx][randy]==0)
97
            break;
98
        randx=parseInt(Math.floor(Math.random()*4));
99
        randy=parseInt(Math.floor(Math.random()*4));
100
        time++;
101
    }
102
    if(time>30){
103
        for(var i=0;i<4;i++)
104
            for(var j=0;j<4;j++)
105
                if(board[i][j]==0){
106
                    randx=i;
107
                    randy=j;
108
                }
109
    }
110
    //随机一个数字2,4
111
    var randNumber = Math.random() <0.5? 2:4;//随机数小于0.5为2,大于0.5为4
112
113
    //显示
114
    board[randx][randy]=randNumber;
115
    showNumberWithAnimation(randx, randy, randNumber);
116
    return true;
117
}
118
$(document).keydown(function (event) {
119
    event.preventDefault();//阻挡按键本来会产生的效果,这里防止屏幕滚动条上下移动
120
    switch (event.keyCode) {
121
        case 37: //left,向左移动,生成新的数,判断游戏是否结束
122
            if (moveLeft()){
123
                setTimeout("generateOneNumber()",200);
124
                setTimeout("isgameover();",200);
125
                //设置延时,让alert有出现 的效果
126
            }
127
            break;
128
        case 38://up
129
            if (moveUp()){
130
                setTimeout("generateOneNumber()",200);
131
                setTimeout("isgameover();",200);
132
            }
133
            break;
134
        case 39://right
135
            if (moveRight()){
136
                setTimeout("generateOneNumber()",200);
137
                setTimeout("isgameover();",200);
138
            }
139
            break;
140
        case 40://down
141
            if (moveDown()){
142
                setTimeout("generateOneNumber()",200);
143
                setTimeout("isgameover();",200);
144
            }
145
            break;
146
        default:
147
            break;
148
149
    }
150
})
151
document.addEventListener('touchstart',function (event) {
152
    startx=event.touches[0].pageX;//event.touches获取多个手指触碰屏幕的信息【0】为一个手指
153
    starty=event.touches[0].pageY;
154
});
155
document.addEventListener('touchmove',function (event) {
156
    event.preventDefault();
157
});
158
document.addEventListener('touchend',function (event) {
159
    endx=event.changedTouches[0].pageX;
160
    endy=event.changedTouches[0].pageY;
161
    var deltax=endx-startx;
162
    var deltay=endy-starty;
163
164
    if(Math.abs(deltax)<0.3*documentWidth && Math.abs(deltay)<0.3*documentWidth)
165
        return;
166
    //x
167
    if(Math.abs(deltax)>=Math.abs(deltay)){
168
        if(deltax>0){
169
            //向右
170
            if (moveRight()){
171
                setTimeout("generateOneNumber()",200);
172
                setTimeout("isgameover();",200);
173
            }
174
        }else{
175
            //向左
176
            if (moveLeft()){
177
                setTimeout("generateOneNumber()",200);
178
                setTimeout("isgameover();",200);
179
                //设置延时,让alert有出现 的效果
180
            }
181
        }
182
183
    }
184
    else{
185
        //y
186
        if(deltay>0){
187
            //向下
188
            if (moveDown()){
189
                setTimeout("generateOneNumber()",200);
190
                setTimeout("isgameover();",200);
191
            }
192
        }else{
193
            //向上
194
            if (moveUp()){
195
                setTimeout("generateOneNumber()",200);
196
                setTimeout("isgameover();",200);
197
            }
198
        }
199
    }
200
});
201
function isgameover() {
202
    if (nospace(board)&&nomove(board)){
203
        gameover();
204
    }
205
}
206
function gameover() {
207
    alert('Game Over');
208
}
209
//--------------------------------------------------------Left-------------------------------------
210
function moveLeft() {
211
    if (!canMoveLeft(board)){
212
        return false;
213
    }
214
    //moveLeft
215
    for (var i=0;i<4;i++)
216
        for (var j=1;j<4;j++){
217
            if (board[i][j]!=0){//不为0可以向左移动,移动要判断该行左侧是否空(或相等)且没有障碍物
218
                for (var k=0;k<j;k++){
219
                    if (board[i][k]==0&&noBlockHorizontal(i, k, j, board)){
220
                        //move
221
                        showMoveAnimation(i, j,i, k);
222
                        board[i][k]=board[i][j];
223
                        board[i][j]=0;
224
                        continue;
225
                    }
226
                    else if (board[i][k]==board[i][j] &&noBlockHorizontal(i, k, j, board)&& !hasConflicted[i][k]){
227
                    // else if (board[i][k]==board[i][j] &&noBlockHorizontal(i, k, j, board)){
228
                        //hasConflicted[i][k]没变化过,即没有发生add
229
                        //move
230
                        showMoveAnimation(i, j,i, k);
231
                        //add
232
                        board[i][k] +=board[i][j];
233
                        board[i][j]=0;
234
                        score+=board[i][k];
235
                        updateScore(score);
236
                        hasConflicted[i][k]=true;//只add一次
237
                        continue;
238
                    }
239
                }
240
            }
241
        }
242
    setTimeout("updateBoardView()",200);//设置更新在200ms后发生,move动画就可以显示
243
    return true;
244
}
245
//--------------------------------------------------------Right-------------------------------------
246
247
function moveRight(){
248
    if( !canMoveRight( board ) )
249
        return false;
250
251
    //moveRight
252
    for( var i = 0 ; i < 4 ; i ++ )
253
        for( var j = 2 ; j >= 0 ; j -- ){
254
            if( board[i][j] != 0 ){
255
                for( var k = 3 ; k > j ; k -- ){
256
257
                    if( board[i][k] == 0 && noBlockHorizontal( i , j , k , board ) ){
258
                        showMoveAnimation( i , j , i , k );
259
                        board[i][k] = board[i][j];
260
                        board[i][j] = 0;
261
                        continue;
262
                    }
263
                    else if( board[i][k] == board[i][j] && noBlockHorizontal( i , j , k , board )&& !hasConflicted[i][k] ){
264
                    // else if( board[i][k] == board[i][j] && noBlockHorizontal( i , j , k , board )){
265
                        showMoveAnimation( i , j , i , k);
266
                        board[i][k] *= 2;
267
                        board[i][j] = 0;
268
                        score+=board[i][k];
269
                        updateScore(score);
270
                        hasConflicted[i][k]=true;
271
272
                        continue;
273
                    }
274
                }
275
            }
276
        }
277
278
    setTimeout("updateBoardView()",200);
279
    return true;
280
}
281
function moveUp() {
282
    if (!canMoveUp(board)){
283
        return false;
284
    }
285
    //
286
    for(var j=0;j<4;j++)
287
        for (var i=1;i<4;i++)
288
            if (board[i][j]!=0)
289
                for (var k=0;k<i;k++)
290
                    if (board[k][j]==0 && noBlockupdown(j, k, i, board)) {
291
                        //move
292
                        showMoveAnimation(i, j, k, j);
293
                        board[k][j] = board[i][j];
294
                        board[i][j] = 0;
295
                        continue;
296
                    }
297
                    // else if (board[k][j]==board[i][j]&&noBlockupdown(j, k, i, board)&& !hasConflicted[k][j]) {
298
                    else if (board[k][j]==board[i][j]&&noBlockupdown(j, k, i, board)) {
299
                        //move
300
                        showMoveAnimation(i,j, k, j);
301
302
                        //add
303
                        board[k][j]+=board[i][j];
304
                        board[i][j]=0;
305
                        score+=board[k][j];
306
                        updateScore(score);
307
                        // hasConflicted[k][j]=true;
308
309
                        continue;
310
                    }
311
    setTimeout("updateBoardView()",200);
312
    return true;
313
}
314
function moveDown() {
315
    if (!canMoveDown(board)){
316
        return false;
317
    }
318
    //
319
    for (var j=0;j<4;j++)
320
        for (var i=2;i>=0;i--)
321
            if(board[i][j]!=0){
322
                for (var k=3;k>i;k--)
323
                    if (board[k][j]==0&&noBlockupdown(j, i, k, board)){
324
                        //move
325
                        showMoveAnimation(i, j, k, j);
326
                        board[k][j]=board[i][j];
327
                        board[i][j]=0;
328
                    }
329
                    // else if (board[i][j]==board[k][j]&&noBlockupdown(j, i, k, board) && !hasConflicted[k][j]){
330
                    else if (board[i][j]==board[k][j]&&noBlockupdown(j, i, k, board)){
331
                        //move,add
332
                        showMoveAnimation(i, j, k, j)
333
                        board[k][j]+=board[i][j];
334
                        board[i][j]=0;
335
                        score+=board[k][j];
336
                        updateScore(score);
337
                        // hasConflicted[k][j]=true;
338
339
                    }
340
            }
341
    setTimeout("updateBoardView()",200);
342
    return true;
343
344
}

support2048.js

1
documentWidth=window.screen.availWidth;
2
gridContainerWidth=0.92*documentWidth;
3
cellSideLength=0.18*documentWidth;
4
cellSpace=0.04*documentWidth;
5
6
function getPosTop(i,j) {
7
    return cellSpace + (cellSpace+cellSideLength)*i;
8
}
9
function getPosLeft(i,j) {
10
    return cellSpace + (cellSpace+cellSideLength)*j;
11
12
}
13
14
function getNumberBackgroudColor(number) {
15
    switch( number ){
16
        case 2:return "#eee4da";break;
17
        case 4:return "#ede0c8";break;
18
        case 8:return "#f2b179";break;
19
        case 16:return "#f59563";break;
20
        case 32:return "#f67c5f";break;
21
        case 64:return "#f65e3b";break;
22
        case 128:return "#edcf72";break;
23
        case 256:return "#edcc61";break;
24
        case 512:return "#9c0";break;
25
        case 1024:return "#33b5e5";break;
26
        case 2048:return "#09c";break;
27
        case 4096:return "#a6c";break;
28
        case 8192:return "#93c";break;
29
    }
30
31
    return "black";
32
}
33
function getNumberColor(number) {
34
    if (number<= 4)
35
        return "#776e65";
36
    return "white";
37
}
38
39
function nospace(board) {
40
    for (var i=0;i<4;i++)
41
        for (var j=0;j<4;j++)
42
            if (board[i][j]==0)//默认初始值为0,为0说明还有空格
43
                return false;
44
    return true;
45
}
46
47
function noBlockHorizontal(row, col1,col2,board) {
48
    for (var i=col1+1;i<col2;i++)
49
        if (board[row][i]!=0)
50
            return false;
51
    return true;
52
}
53
function noBlockupdown(col, row1,row2,board) {
54
    for (var i=row1+1;i<row2;i++)
55
        if (board[i][col]!=0)
56
            return false;
57
    return true;
58
}
59
function canMoveLeft(board) {
60
    for (var i=0;i<4;i++)
61
        for (var j=1;j<4;j++){
62
            if (board[i][j]!=0)//这个点不为0判断要向左移动
63
                if (board[i][j-1]==0 || board[i][j-1]==board[i][j])//左侧是空的或者左右相等
64
                    return true;
65
        }
66
    return false;
67
}
68
function canMoveRight(board){
69
    for (var i=0;i<4;i++)
70
        for (var j=2;j>=0;j--)
71
            if (board[i][j]!=0)
72
                if (board[i][j+1]==board[i][j] || board[i][j+1]==0)
73
                    return true;
74
    return false;
75
}
76
77
function canMoveUp(board){
78
    for (var j=0;j<4;j++)
79
        for (var i=1;i<4;i++)
80
            if (board[i][j]!=0){
81
                if (board[i-1][j]==0 || board[i][j]==board[i-1][j]){
82
                    return true;
83
                }
84
            }
85
    return false;
86
}
87
function canMoveDown(board) {
88
    for (var j=0;j<4;j++)
89
        for (var i=2;i>=0;i--)
90
            if(board[i][j]!=0){
91
                if (board[i+1][j]==board[i][j] || board[i+1][j]==0){
92
                    return true;
93
                }
94
            }
95
    return false;
96
}
97
98
function nomove(board) {
99
    if (canMoveLeft(board) || canMoveRight(board) || canMoveUp(board) || canMoveDown(board)){
100
        return false;
101
    }
102
    return true;
103
}

showanimation.js 移动的动画效果

1
function showNumberWithAnimation(i, j, randNumber) {
2
    var numberCell=$('#number-cell-'+i+"-"+j);
3
4
    numberCell.css('background-color', getNumberBackgroudColor(randNumber));
5
    numberCell.css('color', getNumberColor(randNumber));
6
    numberCell.text(randNumber);
7
8
    numberCell.animate({
9
        // animate函数是jQUERY中的动画函数,动画渐变50ms
10
        width:cellSideLength,
11
        height:cellSideLength,
12
        top:getPosTop(i, j),
13
        left:getPosLeft(i, j)
14
    },50);
15
}
16
function showMoveAnimation(fromx, fromy,tox, toy){
17
    var numberCell = $('#number-cell-'+fromx+'-'+fromy);
18
    numberCell.animate({
19
        top:getPosTop(tox, toy),
20
        left:getPosLeft(tox, toy)
21
22
    },200);
23
}
24
function updateScore(score) {
25
    $('#score').text(score);
26
27
}