2048是2014年出现的一款游戏,虽然距今已有两年时间,但是依然是让人爱的根本听不下来。我也玩过很长时间,如今网上也有各种版本(不同的语言实现)的2048。但是,我依然想自己实现一次。于是就有了今天的分享。源码地址在这里
分析
2048这个游戏在开始时,界面会出现两个为2的方块,然后玩家可以向上下左右四个方向任意方向操作来移动方块,并向界面再新增一个为2的方块,含有相同数值的方块会合并为一个方块,该方块值为二者相加,由此不断直到方块填满界面且没有可合并方块时,游戏结束。
纵观整个过程,涉及的操作有
- 初始化
- 移动方块
- 合并方块
- 插入方块
- 游戏是否结束? 未结束那么重复第2到第4步,否则结束游戏
现在就按照上面5个步骤开始代码实现。
定义游戏类
function game(){
//为了不每次检查是否要合并方块都从DOM去取,所以给类定义一个map一一对应每个方格。
this.map = [
[
[],[],[],[]
],
[
[],[],[],[]
],
[
[],[],[],[]
],
[
[],[],[],[]
]
];
//方块的颜色值,以标识不同的值
this.color = [
'#99CCCC','#FFCC99','#FFCCCC',
'#FFFF99','#CCCCFF','#CC9966',
'#666666','#CC9999','#993333',
'#CCCC00','#663366','#CC0033',
'#333333','#CCCC00','#FF0033',
'#333399','#999933','#333300'
];
//玩家操作方向
this.direction = {
37: 'left',
38: 'up',
39: 'right',
40: 'down'
};
//获取所有行
this.tr = (function(){
var tbody = document.querySelector('tbody');
return tbody.children;
}());
//分数
this.score = 0;
}
初始化
初始化是向界面随意两个位置插入两个方块,位置怎么选是后面每一次操作都会遇到的问题,所以得先有一个方法来指定位置。
获取位置
game.prototype = {
selectPosition: function(){
}
}
最开始我是随机选择一行i,然后判断这行是否有空余位置(即this.map[i]中是否存在空数组),但是这样会出现问题就是肯能随机10次得到的i都是满员了,所以改作一下这种方式(也不知道这样好不好),先遍历map找出至少还有一个还有位置的行,然后在这些行里随机出一行:
getLine: function(){
var line = [];
for(var i=0; i<4; ++i){
for(var j=0; j<4; ++j){
if(!this.map[i][j].length){
line.push(i);
break;
}
}
}
return line;
},
得到行之后再从得到当前行存在几个空位,从空位中找出一个位置返回。位置得到了,现在就是将方块显示在界面中,所以需要一个插入方块的方法。但是这个方块哪里来呢?所以还需要一个制造方块的工厂。
生产方块
game.prototype.create = function(){
}
颜色选择
由于不同的值,方块颜色不同,怎么来确定选用哪个颜色呢?因为出现的值都是2的n次方,所以我打算由n来选择颜色,代码如下:
game.prototype.color = function(val){
return Math.log(val)/Math.log(2);
}
插入方块
现在,插入方块所需的条件都已经具备了。so,去吧,皮卡丘!
game.prototype.insert = function(){
}
在界面中新增方块过后,需要及时更新map。接下来就是玩家操作了,我们可以在document上注册键盘事件以判断玩家操作。
game.prototype.move = function(){
var direc = this.direction;
document.addEventListener('keyup', function(e){
var keycode = e.keyCode || e.which;
keycode in direc ? self[direc[keycode]]() : '';
},false);
}
操作
来到最后一步了,那就是上下左右的四个操作:
game.prototype.up = function(){}
game.prototype.right = function(){}
game.prototype.down = function(){}
game.prototype.left = function(){}
在做完这里之后,我觉得这四个方法可以优化合并成一个,但是没有想到怎么处理。
试玩地址:点击这里