样式:
从CSS样式可以看出,我们并没有对每个格子的位置进行设置,因为如果用CSS给每个格子设置样式代码量太大,而且他们的位置有一定的规律,所以我们可以用js循环来完成每个格子样式的设置
代码:
获取位置
function getPos(num){
return 20 + num*120;
}
这样我们的第一层就好了
效果:
现在构造第二层,即构建一个4x4的值全部为0的数组,由于在构造第二层时,有两层循环,所以我们可以在构造第一层时也能构造第二层
第三层是用js生成16个格子,它和第一层的16个格子一一对应
代码:
')
// 设置数字格的位置,样式
var everyNumber = $('#number-'+ i +'-'+ j);
if(checkerboard[i][j] == 0){
everyNumber.css({
width:'0px',height:'opx',top:getPos(i) + 50,left:getPos(j) + 50
})
}else{
everyNumber.css({
width:'100px',height:'100px',top:getPos(i),left:getPos(j),backgroundColor:getBackgroundColor(checkerboard[i][j]),color:getColor(checkerboard[i][j])
});
everyNumber.text(checkerboard[i][j]);
}
}
}
}
获取相应数字的背景颜色
function getBackgroundColor(number){
switch (number) {
case 2:return "#eee4da";break;
case 4:return "#ede0c8";break;
case 8:return "#f2b179";break;
case 16:return "#f59563";break;
case 32:return "#f67c5f";break;
case 64:return "#f65e3b";break;
case 128:return "#edcf72";break;
case 256:return "#edcc61";break;
case 512:return "#9c0";break;
case 1024:return "#33b5e5";break;
case 2048:return "#09c";break;
case 4096:return "#a6c";break;
case 8192:return "#93c";break;
}
}
文字颜色
function getColor(number){
if (number <= 4) {
return "#776e65"
}
return "white";
}
初始化
在每次游戏重新开始时,都会在随机的位置出现两个随机的数字,我们写一个在随机位置出现一个随机数的函数,只要调用两次就可以实现了
代码:
0.5 ? 2 : 4;
// 在数字格不为0的地方
生成一个
随机数字
while(true){
if(checkerboard[randomX][randomY] == 0){
break;
}else{
var randomX = Math.floor(Math.random() * 4);
var randomY = Math.floor(Math.random() * 4);
}
}
// 将
随机产生的数字
显示在
随机的位置上
checkerboard[randomX][randomY] = randomValue;
// 动画
randomNumAnimate(randomX,randomY,randomValue);
}
随机产生数字的动画
function randomNumAnimate(randomX,randomValue){
var randomnum = $('#number-'+ randomX +'-'+ randomY);
randomnum.css({
backgroundColor:getBackgroundColor(randomValue),color:getColor(randomValue),})
.text(randomValue)
.animate({
width:'100px',top:getPos(randomX),left:getPos(randomY)
},50);
}
基本操作
我们通过switch循环,来根据用户不同的输入进行不同的操作
代码:
获取
键盘事件,检测不同的按键进行不同的操作
$(document).keydown(function(event){
switch(event.keyCode){
case 37://左
if(canMoveLeft(checkerboard)){
// 如果可以向左移动
MoveLeft();
// 向左移动
setTimeout(function(){
randomNum();
},200);
//
随机产生一个数字
}
break;
case 38://上
if(canMoveUp(checkerboard)){
// 如果可以向上移动
MoveUp();
// 向上移动
setTimeout(function(){
randomNum();
},200);
//
随机产生一个数字
}
break;
case 39://右
if(canMoveRight(checkerboard)){
// 如果可以向右移动
MoveRight();
// 向右移动
setTimeout(function(){
randomNum();
},200);
//
随机产生一个数字
}
break;
case 40://下
if(canMoveDown(checkerboard)){
// 如果可以向下移动
MoveDown();
// 向下移动
setTimeout(function(){
randomNum();
},200);
//
随机产生一个数字
}
break;
default:
break;
}
});
由于数字格的移动只有左、上、右、下四种方式,并且他们都是大同小异的,所以就拿向左移动为例,
向左移动,我们首先需要判断它是否能向左移动,能向左移动有两种情况
第一种:当前格子的左边的格子是空的即值为0
第二种:当前格子的值和左边格子的值相同
由于向左移动,所以第一列的格子不可能向左移动,所以不需要判断
代码:
判断能否向左移动后,我们就要对可以移动的格子进行移动,这里需要特别注意,
向哪个方向移动就要先从哪个方向开始判断
代码:
将上、右、下四个方向写完以后,游戏基本的操作就已经完成了。
游戏分数和判断游戏结束
游戏的分数是每个相加的数的和,所以我们在每个数相加的时候更新分数就可以了
代码:
score(num){
$('#
score').text(num);
}
判断游戏是否结束很简单,用我们之前定义的方法就可以实现
代码:
显示游戏结束
function showGameOver(){
$('#container').append("
")
}
// 重新开始游戏
function resert(){
$('#gameover').remove();
newgame();
}
最后优化
1、游戏中会出现一次移动,一个数会被累加很多次
在原游戏中,每个数在每次操作中只能累加一次,所以我们在定义一个4x4的值为false的数组,与中间层的数组一一对应,专门用来防止一个数的多次累加,如果是false则可以累加,并将值改为false,否则不可以累加
2、结束死循环
由于在设置随机数的时候用到了一个死循环,但是在游戏结束后,该循环还在,所以我们在死循环中在添加一个条件,如果游戏结束就跳出循环
3、最后的结束游戏提示不执行
随机产生数字后再进行判断,如果不加
// 延时,则最后一次的判断因为canMoveLeft(checkerboard)为false就不会再执行了
setTimeout(function(){
randomNum();
},200);
//
随机产生一个数字
}
break;
从代码中可以看出,判断游戏是否结束是在随机产生一个数字前执行的,所以在判断游戏结束时,总是有一个空的格子,所以代码执行后认为游戏没有结束,但是当这个随机数字产生后,所有的格子不能移动,当我们按键时,if条件不通过,判断游戏是否结束的函数不能执行。所以我们要给判断游戏结束的函数设置定时器,让他在随机产生一个数字后再进行判断
4、在移动端可以执行
由于原作者没有写有关移动端的操作,所以我在网上找的判断移动端触屏手机滑动位置的代码,加入了游戏的事件就可以执行了
atan2(dy,dx) * 180 / Math.PI;
}
//根据起点和终点返回方向 1:向上,2:向下,3:向左,4:向右,0:未滑动
function GetSlideDirection(startX,startY,endX,endY) {
var dy = startY - endY;
var dx = endX - startX;
varresult = 0;
//如果滑动距离太短
if(Math.abs(dx) < 2 && Math.abs(dy) < 2) {
returnresult;
}
var angle = GetSlideAngle(dx,dy);
if(angle >= -45 && angle < 45) {
result = 4;
}else if (angle >= 45 && angle < 135) {
result = 1;
}else if (angle >= -135 && angle < -45) {
result = 2;
}
else if ((angle >= 135 && angle <= 180) || (angle >= -180 && angle < -135)) {
result = 3;
}
return result;
}
//滑动处理
var startX,startY;
document.addEventListener('touchstart',function (ev) {
startX = ev.touches[0].pageX;
startY = ev.touches[0].pageY;
},false);
document.addEventListener('touchend',function (ev) {
var endX,endY;
endX = ev.changedTouches[0].pageX;
endY = ev.changedTouches[0].pageY;
var direction = GetSlideDirection(startX,endY);
switch(direction) {
case 0:
//没滑动
break;
case 1:
if(canMoveUp(checkerboard)){
// 如果可以向上移动
MoveUp();
// 向上移动
setTimeout(function(){
wheGameOver(checkerboard)
},300);
// 判断游戏是否结束
setTimeout(function(){
randomNum();
},200);
//
随机产生一个数字
}
break;
case 2:
if(canMoveDown(checkerboard)){
// 如果可以向下移动
MoveDown();
// 向下移动
setTimeout(function(){
wheGameOver(checkerboard)
},200);
//
随机产生一个数字
}
break;
case 3:
if(canMoveLeft(checkerboard)){
// 如果可以向左移动
MoveLeft();
// 向左移动
setTimeout(function(){
wheGameOver(checkerboard)
},300);
// 判断游戏是否结束,这里设置延时是因为要等到
随机产生数字后再进行判断,如果不加
// 延时,则最后一次的判断因为canMoveLeft(checkerboard)为false就不会再执行了
setTimeout(function(){
randomNum();
},200);
//
随机产生一个数字
}
break;
case 4:
if(canMoveRight(checkerboard)){
// 如果可以向右移动
MoveRight();
// 向右移动
setTimeout(function(){
wheGameOver(checkerboard)
},200);
//
随机产生一个数字
}
break;
default:
}
},false);
总结
总体来说这个游戏实现起来并不是太难,就是许多小的操作集合起来
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持编程之家!