2048小游戏的核心是:通过控制键盘上的“上”、“下”、“左”、“右”键来实现数字的移动、相加、以及生成新的数字。
上图为运行后的结果,我随便操作了几下,可以看到图片上有数字2,数字4,数字8,数字16,数字32,其中只有2和4是可以随机生成的,其他的都是根据上下左右操作获得的,下面提供2048的js代码:
var game={
score :0, //分数
status :1, //游戏处于的状态
gameover :0, //游戏结束
gamerunning :1, //游戏进行中
data : [],
start :function(){ //开始
this.status=this.gamerunning;
this.score=0;
this.data=[]; //生成一个数组用来存放格子里的数字
for(var r=0;r<4;r++){
this.data[r]=[];
for(var c=0;c<4;c++){
this.data[r][c]=0; //初始化每个格子,使其值为0
}
}
this.randomNum(); //在一个随机的格子上随机生成2或4
this.randomNum();
this.dataView();
console.log(this.data);
},
randomNum:function(){ //随机数
var r=Math.floor(Math.random()*4);
var c=Math.floor(Math.random()*4);
if(this.data[r][c]==0){
var num=Math.random() >0.2 ? 2 : 4;//三元表达式随机生成2或4
this.data[r][c]=num;
}else{
//这边我用的是else重新调用函数,也可以通过while死循环和break来实现在没有数值的格子上随机生成2或4.
this.randomNum();
}
},
dataView : function(){ //数据可视化
for(var r=0;r<4;r++){
for(var c=0;c<4;c++){
var div=document.getElementById("c"+ r + c);//通过不同的id名获取对应的div元素节点
if(this.data[r][c]!=0){ //判断数字不为0(初始值),就将该数字显示在页面上
div.innerHTML=this.data[r][c];
div.className="cell n"+this.data[r][c];//通过修改class名来实现不同数字会有不同的样式
}else{
div.innerHTML=""; //没有数值就不显示内容
div.className="cell";//class名为初始值
}
}
}
document.getElementById("score01").innerHTML=this.score;//把分数显示在页面上
if(this.status==this.gameover){
document.getElementById("score02").innerHTML=this.score;
document.getElementById("gameover").style.display="block";
}
else{
document.getElementById("gameover").style.display="none";
}
},//游戏结束时修改元素样式使其显现在页面上
isGameover :function(){ //游戏结束
for(var r=0 ;r<4;r++){
for(var c=0;c<4;c++){
if(this.data[r][c]==0){ //如果还有格子的数值是0,证明游戏还没结束
return false;
}
if(c<3){
if(this.data[r][c]==this.data[r][c+1]){
return false;
}
}
if(r<3){
if(this.data[r][c]==this.data[r+1][c]){
return false;
}
} //如果有上下或左右相邻的数是一样的,那么游戏还没有结束
}
}
return true;//如果以上情况都没有,返回true,游戏结束.
},
moveLeft:function(){ //点击左键
var before=String(this.data); //一个不为0的数
for(var r=0; r<4;r++){
this.moveLeftRow(r);
}
var after =String(this.data) //同一行相邻的另一个数(可能为0(就是格子上没有数))
if(before!=after){
this.randomNum(); //如果两数不相等,在随机位置生成2或4;
if(this.isGameover()){
this.status=this.gameover; //判断游戏是否结束
}
this.dataView(); //渲染页面
}
},
moveLeftRow:function(r){ //单独抽出一行进行写逻辑
for(var c=0;c<3;c++){ //最左边的不需要移动,所以遍历3次
var nextc=this.getNextinRow(r,c);
// 找出r行c列后面不为0的数据的位置保存至nextc中
if(nextc !=-1){ //这一行有需要移动的
if(this.data[r][c]==0){//一定是把所有需要移动的数据移动到靠左的位置
this.data[r][c]=this.data[r][nextc];
this.data[r][nextc]=0;
c--;//c留在原地继续左移
}else if(this.data[r][c]==this.data[r][nextc]){
this.data[r][c]=this.data[r][c]*2;
this.score +=this.data[r][c]; //分数
this.data[r][nextc]=0;
}
}
else{
// 这一行中没有需要移动的数据
break;
}
}
},
getNextinRow: function(r,c){
for(var i=c+1;i<4;i++){
// 如果数据不为0,表示找到了,返回i,i对应的是当前数据的列下标
if(this.data[r][i]!=0){
return i;
}
}
return -1;
},
moveUp: function(){ //向上
var before=String(this.data);
for(var c=0;c<4;c++){
this.moveUpCell(c);
}
var after =String(this.data)
if(before!=after){
this.randomNum();
if(this.isGameover()){
this.status=this.gameover;
}
this.dataView();
}
},
moveUpCell:function(c){
for(var r=0;r<3;r++){
var nextr=this.getUpCell(r,c);
if(nextr!=-1){
if(this.data[r][c]==0){
this.data[r][c]=this.data[nextr][c];
this.data[nextr][c]=0;
r--;
}else if(this.data[r][c]==this.data[nextr][c]){
this.data[r][c]=this.data[nextr][c]*2;
this.score +=this.data[r][c];
this.data[nextr][c]=0;
}
}
else{
break;
}
}
},
getUpCell :function(r,c){ //向上
for(var i=r+1;i<4;i++){
if(this.data[i][c]!=0){
return i;
}
}
return -1;
},
getRightRow :function(r,c){ //向右
for(var i=c-1;i>=0;i--){
if(this.data[r][i]!=0){
return i;
}
}
return -1;
},
moveRightRow: function(r){
for(var c=3;c>=0;c--){
//c需要=3,不然移动时会移动不到最右边(别问我怎么知道的!!!)
var nextc=this.getRightRow(r,c);
if(nextc !=-1){
if(this.data[r][c]==0){
this.data[r][c]=this.data[r][nextc];
this.data[r][nextc]=0;
c++;
}else if(this.data[r][c]==this.data[r][nextc]){
this.data[r][c]=this.data[r][c]*2;
this.score +=this.data[r][c];
this.data[r][nextc]=0;
}
}
else{
break;
}
}
},
moveRight: function(){ //向右
var before=String(this.data);
for(var r=3;r>=0;r--){
this.moveRightRow(r);
}
var after =String(this.data)
if(before!=after){
this.randomNum();
if(this.isGameover()){
this.status=this.gameover;
}
this.dataView();
}
},
getPreCell :function(r,c){ //向下
for(var i=r-1;i>=0;i--){
if(this.data[i][c]!=0){
return i;
}
}
return -1;
},
moveDownCell: function(c){
for(var r=3;r>=0;r--){
var nextr=this.getPreCell(r,c);
if(nextr !=-1){
if(this.data[r][c]==0){
this.data[r][c]=this.data[nextr][c];
this.data[nextr][c]=0;
r++;
}else if(this.data[r][c]==this.data[nextr][c]){
this.data[r][c]=this.data[r][c]*2;
this.score +=this.data[r][c]; //分数
this.data[nextr][c]=0;
}
}
else{
break;
}
}
},
moveDown: function(){ //向下移动
var before=String(this.data);
for(var c=3;c>=0;c--){
this.moveDownCell(c);
}
var after =String(this.data)
if(before!=after){
this.randomNum();
if(this.isGameover()){
this.status=this.gameover;
}
this.dataView();
}
},
}
game.start(); //调用函数,游戏开始
document.onkeydown=function(event){
if(event.keyCode==37){
game.moveLeft();
}
else if(event.keyCode==38){
game.moveUp();
}
else if(event.keyCode==39){
game.moveRight();
}
else if(event.keyCode==40){
game.moveDown();
}
}
上面把向左移动介绍的比较详细,向右,向上,向下的函数方法和向左方法差不多类似,只需要修改少量数据就行。
移动逻辑:根据需要移动的方向,从左往右,从上往下…循环来找第一个非零的数据在数组中的下标,循环查找完一行(列)中的所有数据,然后通过下标赋值来实现移动,之后判断相邻数是否相同,相同就相加,再循环操作每一行(列)的数据,判断游戏是否结束,没有就继续随机生成2或4;通过键盘按键点击事件触发对应的函数,实现2048小游戏。
快来自己写一个,看看可以玩到多少分。