js2048小游戏,方格是怎么合并和移动的

index.html
<html>
<head>
<meta charset="utf-8">
<title>2048小游戏</title>
<meta name="renderer" content="webkit"> <!-- 360手机优先使用chrome内核 -->
<meta name="screen-orientation" content="portrait"> <!-- UC强制竖屏 -->
<meta name="x5-orientation" content="portrait"> <!-- QQ强制竖屏 -->
<meta name="browsermode" content="application"> <!-- UC浏览器应用模式 -->
<!-- <meta name="x5-page-mode" content="app"> --> <!-- QQ应用模式 -->
<meta http-equiv="Cache-Control" content="no-siteapp"> <!-- 禁止百度转载页面加载流氓广告 -->
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> <!-- 优先使用最高IE内核和chrome内核 -->
<meta name="viewport" content="width=device-width,maximum-scale=1,initial-scale=1.0,user-scalable=no">
<!-- 禁止用户修改网页大小 -->
<meta name="google" value="notranslate"> <!-- 禁用google翻译网页 -->
<meta name="robots" content="index,follow"> <!-- 网页搜索引擎方式 -->
<meta name="apple-mobile-web-app-capable" content="yes" />
<link href="css/2048.css" rel="stylesheet">
</head>
<body>
<div class="wrap">
<div class="score_box">
<b>score:</b><b id="score"></b>
</div>
<div class="cell_wrap">
<div class="box">
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
</div>
</div>
</div>
<script src="js/jquery-3.2.1.js"></script>
<script src="js/2048.js"></script>
</body>
</html>
<!--
//加排行榜
-->
2048.css
* {
box-sizing: border-box;
font-family: Helvetica;
}
body{
background-color: #444;
}
.wrap{
overflow:hidden;
margin-top: 30px;
}
.score_box{
position: absolute;
left: -40px;
text-align: center;
width: 200px;
height: 50px;
color: #e8ddc7;
background-color: #c26251;
border-radius: 40px;
font-size: 20px;
line-height: 50px;
border: 3px solid #c18479;
}
.cell_wrap{
background-color: rgba(0,0,0,0.2);
width: 35%;
height: 35vw;
padding: 2.5%;
margin: 50px auto 0;
border-radius: 20px;
}
.box{
width: 100%;
height: 30vw;
position: relative;
}
.cell{
float: left;
height: 25%;
width: 25%;
box-sizing:border-box;
border-radius: 15px;
background-color: rgba(230,190,160,0.2);
padding: 1.5px;
background-clip: content-box;
}
.number_cell{
position: absolute;
box-sizing:border-box;
width: 25%;
height: 25%;
padding: 1.5px;
background-clip: content-box;
left: 0;
top: 0;
transition: all 0.2s;
color: #e8ddc7;
}
.number_cell_con{
display: block;
-webkit-border-radius: 15px;
-moz-border-radius: 15px;
border-radius: 15px;
width: 100%;
height:calc(100% - 5px);
height:-moz-calc(100% - 5px);
height:-webkit-calc(100% - 5px);
}
.span_wrap{
position: absolute;
float: left;
top: 26%;
left: 50%;
}
.number_cell_con span{
position: relative;
left: -50%;
font-size: 65px;
-webkit-border-radius: 15px;
-moz-border-radius: 15px;
border-radius: 15px;
}
/*position数组坐标位置*/
.pos00{left:0; top:0;}
.pos01{left:25%; top:0; }
.pos02{left:50%; top:0; }
.pos03{left:75%; top:0; }
.pos10{left:0; top:25%; }
.pos11{left:25%; top:25%; }
.pos12{left:50%; top:25%; }
.pos13{left:75%; top:25%; }
.pos20{left:0; top:50%; }
.pos21{left:25%; top:50%; }
.pos22{left:50%; top:50%; }
.pos23{left:75%; top:50%; }
.pos30{left:0; top:75%; }
.pos31{left:25%; top:75%; }
.pos32{left:50%; top:75%; }
.pos33{left:75%; top:75%; }
/*级别格子样式*/
.n2{
background: #e5cdc4; color: #846767;
box-shadow: 0 4px 0 #b6a7a1, 0 5px 2px rgba(0,0,0,.35);
}
.n4{
background: #d8968a;
box-shadow:0 4px 0 #ad867f,0 5px 2px rgba(0,0,0,.35);
}
.n8{
background:#c26251;
box-shadow:0 4px 0 #924c3f, 0 5px 2px rgba(0,0,0,.35);
}
.n16{
background:#ef7964;
box-shadow:0 4px 0 #c36a5a,0 5px 2px rgba(0,0,0,.35);
}
.n32{
background:#b35c79;
box-shadow:0 4px 0 #98556c,0 5px 2px rgba(0,0,0,.35);
}
.n64{
background:#922b19;
box-shadow:0 4px 0 #662418,0 5px 2px rgba(0,0,0,.35);
}
.n128{
background:#992f44;
box-shadow:0 4px 0 #782b3a,0 5px 2px rgba(0,0,0,.35);
}
.n256{
background:#6a2938;
box-shadow:0 4px 0 #4e2a32,0 5px 2px rgba(0,0,0,.35);
}
.n512{
background:#ae3a71;
box-shadow: 0 4px 0 #7e3356,0 5px 2px rgba(0,0,0,.35);
}
.n1024{
background:#dc1071;
box-shadow:0 4px 0 #9b1e59, 0 5px 2px rgba(0,0,0,.35);
}
.n2048{
background:#e56416;
box-shadow: 0 4px 0 #a54e19 0 5px 2px rgba(0,0,0,.35);
}
.n4096{
background:#e8292c;
box-shadow: 0 4px 0 #b03032,0 5px 2px rgba(0,0,0,.35);
}
.number_cell_con:after{
font-size: 8px;
display: block;
width: 100%;
text-align: center;
position: relative;
top: 70%;
}
.pop_box{
width: 100%;
position: fixed;
top: 0;
left: 0;
height: 100%;
background-color: rgba(35,30,30,0.95);
z-index: 1;
}
.center_wrap{
position: absolute;
float: left;
left: 50%;
top: 20%;
}
.pop_head{
border-radius: 30px 30px 0 0;
height: 40px;
background-color: #c26251;
position: relative;
top: -60px;
line-height: 40px;
color: #e5cdc4;
}
.pop_center{
position: relative;
left: -50%;
z-index: 2;
width: 40vw;
height: 300px;
text-align: center;
background-color: #e5cdc4;
border-radius: 30px;
padding: 60px 0px;
}
.pop_center span{
font-size: 20px;
color: #c26251;
}
.closebtn{
display: block;
width: 100px;
height: 60px;
margin: 40px auto 0;
border-radius: 20px;
background-color: #c26251;
border: 3px solid #c18479;
color: #e5cdc4;
font-size: 18px;
outline: none;
}
.sign{
float: right;
margin-top: -80px;
margin-right: 20px;
border-radius: 50%;
overflow: hidden;
border: 3px solid #c18479;
display:none;
}
.close{
position: absolute;
z-index: 3;
background-color: #e5cdc4;
border-radius: 50%;
border: 2px solid #999;
color: #777;
cursor: pointer;
transform:rotate(45deg);
-ms-transform:rotate(45deg); /* IE 9 */
-moz-transform:rotate(45deg); /* Firefox */
-webkit-transform:rotate(45deg); /* Safari 和 Chrome */
-o-transform:rotate(45deg);
font-size: 45px;
line-height: 45px;
width: 45px;
height: 45px;
top: -10px;
right: -10px;
}
.rank_wrap{
margin-top: -30px;
}
#rank_cell{
height: 55px;
border-bottom: 0.5px dotted #c26251;
line-height: 55px;
}
.ranking{
float: left;
margin-left: 30px;
font-weight: bold;
color: #666;
font-size: 25px;
}
.headpic{
float: left;
margin-left: 30px;
margin-top: 2.5px;
background-color: #eee;
width: 50px;
height: 50px;
}
.name{
float: left;
margin-left: 10px;
}
.myscore{
float: right;
margin-right: 30px;
color: #c33c12;
font-size: 25px;
font-weight: bold;
}
@media screen and (max-width: 850px){
.cell_wrap{
width: 55%;
height: 55vw;
padding: 2.5%;
}
.box{
height: 50vw;
}
.sign{
margin-top: 20px;
}
}
@media screen and (max-width: 780px){
.cell_wrap{
width: 95%;
height: 95vw;
padding: 7.5%;
margin-top: 70px;
}
.span_wrap{
top: 22%;
}
.box{
height: 80vw;
}
.number_cell_con span{
font-size: 40px;
}
.number_cell_con:after{
font-size: 15px;
top: 65%;
}
.pop_center{
width: 85vw;
height: 300px;
}
}
@media screen and (max-width: 480px){
.number_cell_con span{
font-size: 33px;
}
.span_wrap{
top: 22%;
}
.number_cell_con:after{
font-size: 11px;
top: 65%;
}
.pop_center{
width: 90vw;
height: 300px;
}
#headpic{
margin-left: 17px;
}
#name{
margin-left: 7px;
}
}
@media screen and (max-width: 400px){
.number_cell_con span{
font-size: 28px;
}
.span_wrap{
top: 20%;
}
.number_cell_con:after{
font-size: 11px;
top: 65%;
}
.pop_center{
width: 90vw;
height: 300px;
}
}
2048.js
Game2048.prototype = {
constructor:Game2048,
init:function(){
this.score = 0;
this.arr = [];
this.moveAble = false;
$("#score").html("0");
$(".number_cell").remove();
this.creatArr();
},
creatArr:function(){
var i,j;
for (i = 0; i < 4; i++) {
this.arr[i] = [];
for (j = 0; j < 4; j++) {
this.arr[i][j] = {};
this.arr[i][j].value = 0;
}
}
var iRandom,jRandom;
iRandom=getRandom(3);
jRandom=getRandom(3);
this.arrValueUpdate(2,iRandom,jRandom);
this.drawCell(iRandom,jRandom);
},
arrValueUpdate:function(num,i,j){
this.arr[i][j].value = num;
},
//画出格子时,是按照css样式来添加的
drawCell:function(i,j){
var item = '<div class="number_cell pos'+i+j+'" ><a class="number_cell_con n2"><div class="span_wrap"><span>'
+this.arr[i][j].value+'</span></div></a></div>';
$(".box").append(item);
},
addEvent:function(){
var that = this;
document.onkeydown=function(event){
var e = event || window.event || arguments.callee.caller.arguments[0];
var direction = that.direction;
var keyCode = e.keyCode;
switch(keyCode){
case 39:
that.moveAble = false;
that.moveRight();
that.checkLose();
break;
case 40:
that.moveAble = false;
that.moveDown();
that.checkLose();
break;
case 37:
that.moveAble = false;
that.moveLeft();
that.checkLose();
break;
case 38:
that.moveAble = false;
that.moveUp();
that.checkLose();
break;
}
};
},
newCell:function(){
var i,j,len,index;
var ableArr = [];
if(this.moveAble != true){
console.log('不能增加新格子,请尝试其他方向移动!');
return;
}
//将所有的是0的点添加到ableArr数组中,
for (i = 0; i < 4; i++) {
for (j = 0; j < 4; j++) {
if(this.arr[i][j].value == 0){
ableArr.push([i,j]);
}
}
}
len = ableArr.length;
if(len > 0){
index = getRandom(len);
i = ableArr[index][0];
j = ableArr[index][1];
this.arrValueUpdate(2,i,j);
this.drawCell(i,j);
}
},
//向上
moveUp:function(){
for(var j = 0 ;j<=3;j++){
for(var i=0;i<=3;i++){
var curVal = this.arr[i][j].value;
if(curVal != 0){
var k = i + 1;
while(k<=3){
var nextVal = this.arr[k][j].value;
if(nextVal != 0){
if(nextVal == curVal){
this.moveAble = true;
this.mergeCells(k,j,i,j);
}
break;
}
k++;
}
}
}
}
for(var j = 0 ;j<=3;j++){
for(var i=0;i<=3;i++){
var curVal = this.arr[i][j].value;
if(curVal == 0){
var k = i + 1;
while(k<=3){
var nextVal = this.arr[k][j].value;
if(nextVal !=0 ){
this.moveAble = true;
this.moveCell(k,j,i,j);
break;
}
k++;
}
}
}
}
this.newCell();
},
//向下
moveDown:function(){
for(var j = 0 ;j<=3;j++){
for(var i=3;i>=0;i--){
var curVal = this.arr[i][j].value;
if(curVal != 0){
var k = i - 1;
while(k>=0){
var nextVal = this.arr[k][j].value;
if(nextVal != 0){
if(nextVal == curVal){
this.moveAble = true;
this.mergeCells(k,j,i,j);
}
break;
}
k--;
}
}
}
}
for(var j = 0 ;j<=3;j++){
for(var i=3;i>=0;i--){
var curVal = this.arr[i][j].value;
if(curVal == 0){
var k = i - 1;
while(k>=0){
var nextVal = this.arr[k][j].value;
if(nextVal !=0 ){
this.moveAble = true;
this.moveCell(k,j,i,j);
break;
}
k--;
}
}
}
}
this.newCell();
},
//向左
moveLeft:function(){
//合并
//[4,4,8,8] - > [8,0,16,0]
for(var i = 0 ; i<=3;i++){
for(var j = 0 ; j<=3; j++){
var curVal = this.arr[i][j].value;
if(curVal != 0){
var k = j + 1;
while(k <= 3){
var nextVal = this.arr[i][k].value;
if(nextVal!=0){
if(nextVal == curVal){
this.moveAble = true;
this.mergeCells(i,k,i,j);
}
break;
}
k++;
}
}
}
}
//移动[8,0,16,0] -> [8,16,0,0]
for(var i = 0 ; i<=3; i++){
for(var j=0;j<=3; j++){
var curVal = this.arr[i][j].value;
if(curVal == 0 ){
var k = j +1;
while(k <=3){
var nextVal = this.arr[i][k].value;
if(nextVal != 0){
this.moveCell(i,k,i,j);
break;
}
k++;
}
}
}
}
this.newCell();
},
//向右
moveRight:function(){
console.log("右移动");
//合并[4,4,8,8] -> [0 , 4 , 0 , 16]
//合并[4,8,0,8] -> [4,0,0,16]
//合并[8,0,0,8] -> [0,0,0,16]
//合并[4,0,4,0] -> [0,0,8,0]
//从右边找到第一个不为0的点,循环取他的下一个不为0的点,判断是不是和当前点的值相等
//如果相等就合并,并且设置标志位,表示可以移动或者合并,不管相等不相等,都要跳出while循环
for(var i = 0 ; i<=3;i++){
for(var j = 3 ; j>=0; j--){
var curVal = this.arr[i][j].value;
if(curVal != 0){
var k = j - 1;
while(k >= 0){
var nextVal = this.arr[i][k].value;
if(nextVal!=0){
if(nextVal == curVal){
this.moveAble = true;
this.mergeCells(i,k,i,j);
// this.arr[i][j] = 2 * this.arr[i][j];
// this.arr[i][k] = 0;
}
break;
}
k--;
}
}
}
}
//移动[0,0,4,0] -> [0,0,0,4]
//移动[8,0,0,4] -> [0,0,8,4]
//从右边找到第一个为0的点,循环取他的下一个不为0的点,重新设置两点的值
for(var i = 0 ; i<=3; i++){
for(var j=3;j>=0; j--){
var curVal = this.arr[i][j].value;
if(curVal == 0 ){
var k = j -1;
while(k >= 0){
var nextVal = this.arr[i][k].value;
if(nextVal != 0){
// this.moveAble = true;
// this.arr[i][j].value = nextVal;
// this.arr[i][k].value = 0;
this.moveCell(i,k,i,j);
break;
}
k--;
}
}
}
}
this.newCell();
},
mergeCells:function(i1,j1,i2,j2){
//合并
var temp =this.arr[i2][j2].value;
var temp1 = temp * 2;
this.moveAble = true;
this.arr[i2][j2].value = temp1;
this.arr[i1][j1].value = 0;
$(".pos"+i2+j2).addClass('toRemove');
var theDom = $(".pos"+i1+j1).removeClass("pos"+i1+j1).addClass("pos"+i2+j2).find('.number_cell_con');
setTimeout(function(){
$(".toRemove").remove();
theDom.addClass('n'+temp1).removeClass('n'+temp).find('span').html(temp1);
},200);
this.score += temp1;
$("#score").html(this.score);
if(temp1 == 2048){
alert('人才啊!祖国的明天就靠你了^o^');
this.init();
}
},
moveCell:function(i1,j1,i2,j2){
this.arr[i2][j2].value = this.arr[i1][j1].value;
this.arr[i1][j1].value = 0;
this.moveAble = true;
$(".pos"+i1+j1).removeClass("pos"+i1+j1).addClass("pos"+i2+j2);
},
//由于每个方向都有判断游戏是否结束,这里只判断两个方向的即可
checkLose:function(){
//判断游戏结束
var i,j,temp;
for (i = 0; i < 4; i++) {
for (j = 0; j < 4; j++) {
temp = this.arr[i][j].value;
if(temp == 0){
return false;
}
if(this.arr[i+1] && (this.arr[i+1][j].value==temp)){
return false;
}
if((this.arr[i][j+1]!=undefined) && (this.arr[i][j+1].value==temp)){
return false;
}
}
}
alert('革命尚未成功,同志仍需努力^_^');
this.init();
return true;
}
}
//弹出自定义提示窗口start
var showAlert= function(msg, url){
//弹框存在
if ( $("#alert_box").length > 0) {
$('#pop_box_msg').html(msg);
} else {
var alertHtml = '<div id="alert_box" class="pop_box">'
+ '<div class="center_wrap">'
+ '<div class="pop_center">'
+ '<div class="pop_head"></div>'
+ '<span id="pop_box_msg">' + msg + '</span>'
+ '<button class="closebtn" onclick="closeAlert()">再来一次</button>'
+ '</div>'
+ '</div>'
+ '</div>';
$("body").append(alertHtml);
}
$("#alert_box").show();
if(url){
setTimeout(function(){
window.location.href = url + '?id=' + 10000*Math.random();
} , 2000 );
}
}
//重定义alert
window.alert=showAlert;
//点击遮罩关闭
function closeAlert(){
$("#alert_box").hide();
}
//弹出自定义提示窗口end
//排行榜start 静静等待后台传数据
function showRanking(){
if ( $("#ranking_box").length > 0) {
} else {
//id名为rank_cell 的div块随用户玩获取成绩而增++
//id ranking 排名1 2 3...
//id headpic 用户头像
//id name 用户名
//id score 用户成绩
//
var rankingHtml = '<div id="ranking_box" class="pop_box">'
+ '<div class="center_wrap">'
+ '<div class="pop_center">'
+ '<div class="pop_head"><b>排行榜</b></div>'
+ '<div class="rank_wrap">'
+ '<div id="rank_cell">'
+ '<span id="ranking" class="ranking">1</span>'
+ '<img id="headpic" class="headpic">'
+ '<span id="name" class="name">xxx</span>'
+ '<span id="myscore" class="myscore"></span>'
+ '</div>'
+ '</div><div class="close" onclick="closeRanking()">+</div>'
+ '</div>'
+ '</div>'
+ '</div>';
$("body").append(rankingHtml);
$("#myscore").html(this.score);
}
$("#ranking_box").show();
}
function closeRanking(){
$("#ranking_box").hide();
}
//排行榜end
function getRandom(n){
return Math.floor(Math.random()*n)
}
function Game2048(){
this.addEvent();
}
var g = new Game2048();
g.init();
还要在index.html中引入jquery.js。