版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/funkstill/article/details/85089320
目录
效果图:
游戏页面:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>2048</title>
<link href="2048.css" rel="stylesheet" type="text/css">
<script type="text/javascript" src="jquery-1.11.0.js"></script>
<script type="text/javascript" src="support.js"></script>
<script type="text/javascript" src="animation.js"></script>
<script type="text/javascript" src="main.js"></script>
<script type="text/javascript" src="game.js"></script>
</head>
<body>
<header>
<h1>2048</h1>
<a href="javascript:newgame();" id="newgamebutton">New Game</a>
<p>score:<span id="score">0</span> </p>
</header>
<div id="grid-container">
<div class="grid-cell" id="grid-cell-0-0"></div>
<div class="grid-cell" id="grid-cell-0-1"></div>
<div class="grid-cell" id="grid-cell-0-2"></div>
<div class="grid-cell" id="grid-cell-0-3"></div>
<div class="grid-cell" id="grid-cell-1-0"></div>
<div class="grid-cell" id="grid-cell-1-1"></div>
<div class="grid-cell" id="grid-cell-1-2"></div>
<div class="grid-cell" id="grid-cell-1-3"></div>
<div class="grid-cell" id="grid-cell-2-0"></div>
<div class="grid-cell" id="grid-cell-2-1"></div>
<div class="grid-cell" id="grid-cell-2-2"></div>
<div class="grid-cell" id="grid-cell-2-3"></div>
<div class="grid-cell" id="grid-cell-3-0"></div>
<div class="grid-cell" id="grid-cell-3-1"></div>
<div class="grid-cell" id="grid-cell-3-2"></div>
<div class="grid-cell" id="grid-cell-3-3"></div>
</div>
</body>
</html>
游戏页面样式:
/*设置游戏整体位置*/
header{
display: block;
margin: 0 auto;
width: 100%;
text-align: center;
}
header h1{
font-family: Arial;
font-size: 40px;
font-weight: bold;
}
/* 设置按钮样式*/
header #newgamebutton{
display: block;
margin: 20px auto;
width: 100px;
padding: 10px 10px;
background-color: #8f7a66;
font-family: "Arial";
color: white;
border-radius: 10px;
text-decoration: none;
}
/*按钮hover响应*/
header #newgamebutton:hover{
background-color: #9f8b77;
}
/*分数样式*/
header p{
font-family: Arial;
font-size: 25px;
margin: 20px auto;
}
/*主体方块样式*/
#grid-container{
width: 460px;
height: 460px;
padding: 20px;
margin: 50px auto;
background-color: #bbada0;
border-radius: 10px;
position: relative;
}
/*设置小方块样式*/
.grid-cell{
width: 100px;
height: 100px;
border-radius: 6px;
background-color: #ccc0b3;
position: absolute;
}
/*设置数字方格的字体样式*/
.number-cell{
border-radius: 6px;
font-family: Arial;
font-weight: bold;
font-size: 60px;
line-height: 100px;
text-align: center;
position: absolute;
}
.gameover{
display: block;
margin: 0 auto;
width: 500px;
text-align: center;
vertical-align: middle;
position: absolute;
}
.gameover p{
font-family: Arial;
font-size: 50px;
color: white;
margin: 20px auto;
margin-top: 150px;
}
.gameover span {
font-family: Arial;
font-size: 50px;
color: white;
margin: 20px auto;
}
#restartgamebutton {
display: block;
margin: 20px auto;
width: 180px;
padding: 10px 10px;
background-color: #8f7a66;
font-family: Arial;
font-size: 30px;
color: white;
border-radius: 10px;
text-decoration: none;
}
#restartgamebutton:hover {
background-color: #9f8b77;
}
游戏基础逻辑:
/**
* Created by cell on 2018/12/18.
*/
//设置小格子顶端距离
function getPosTop(dx,dy) {
return 20+dx*120;
}
//设置小格子左端距离
function getPosLeft(dx,dy) {
return 20+dy*120;
}
//获取数字背景颜色
function getNumberBackgroundColor(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;
default:return "#222";break;
}
}
function getNumberColor(number) {
if (number<=4){
return "#776e65";
}
return "white";
}
//判断是否可以移动
function canMoveLeft(board) {
for(var r=0;r<4;r++){
for(var c=1;c<4;c++){//第一列无法左移
//当前小格有值
if(board[r][c]!=0){
//前面为空或者前面的值和当前值相等
if(board[r][c-1]==0||board[r][c-1]==board[r][c]){
return true;
}
}
}
}
return false;
}
function canMoveRight(board) {
for(var r=0;r<4;r++){
for(var c=2;c>=0;c--){//倒数第一列无法右移
//当前小格有值
if(board[r][c]!=0){
//右面为空或者右面的值和当前值相等
if(board[r][c+1]==0||board[r][c+1]==board[r][c]){
return true;
}
}
}
}
return false;
}
function canMoveUp(board) {
for(var r=1;r<4;r++){//第一行无法上移
for(var c=0;c<4;c++){
//当前小格有值
if(board[r][c]!=0){
//上面为空或者上面的值和当前值相等
if(board[r-1][c]==0||board[r-1][c]==board[r][c]){
return true;
}
}
}
}
return false;
}
function canMoveDown(board) {
for(var r=2;r>=0;r--){//最下面一行无法下移
for(var c=0;c<4;c++){
//当前小格有值
if(board[r][c]!=0){
//下面为空或者下面的值和当前值相等
if(board[r+1][c]==0||board[r+1][c]==board[r][c]){
return true;
}
}
}
}
return false;
}
//判断中间是否有空格
function noBlokHorizontalCol(r,temp,c,board) {
//判断第r行的第c列和第temp列之间是否有空格,temp<c即temp在左
for (var i = temp+1;i<c;i++){
if(board[r][i]!=0){
return false;
}
}
return true;
}
function noBlokHorizontalRow(r1,r2,c,board) {
//判断(r1,c)和(r2,c)之间是否有空格
for (var i=r1+1;i<r2;i++){
if(board[i][c]!=0){
return false;
}
}
return true;
}
//判断是否有未赋值的块
function noSpace(board) {
for(var r=0;r<4;r++){
for(var c=0;c<4;c++){
if(board[r][c]==0){
return false;
}
}
}
return true;
}
function noMove(board) {
if(canMoveUp(board)||canMoveDown(board)||canMoveLeft(board)||canMoveRight(board)){
return false;
}
return true;
}
游戏动画逻辑:
/**
* Created by cell on 2018/12/18.
*/
function ShowNumberWithAnimation(x,y,number) {
//获取当前的数字格
var numberCell = $("#number-cell-"+x+"-"+y);
//设置当前数字格的背景和前景色及数字值
numberCell.css("background-color",getNumberBackgroundColor(number));
numberCell.css("color",getNumberColor(number));
numberCell.text(number);
//设置当前数字格显示动画
numberCell.animate({
width:"100px",
height:"100px",
top:getPosTop(x,y),
left:getPosLeft(x,y)
},50);
}
function showMoveAnimation(origx,origy,tagtx,tagty) {
//获取当前数字格内容
var numberCell = $("#number-cell-"+origx+"-"+origy);
numberCell.animate({
top:getPosTop(tagtx,tagty),
left:getPosLeft(tagtx,tagty)
},200);
}
function updateScore(score) {
$("#score").text(score);
}
游戏主逻辑:
/**
* Created by cell on 2018/12/18.
*/
//创建数组
var board = new Array();
var hasConfilcted = new Array();
var score = 0;
$(function () {
newgame()
});
function newgame() {
//棋盘初始化
init();
//在随机两个格子生成数字
generateOneNumber();
generateOneNumber();
}
function restartgame() {
$("#gameover").remove();
updateScore(0);
newgame();
}
function init() {
//UI初始化
for (var row=0;row<4;row++){
for (var column=0;column<4;column++){
var griCell = $("#grid-cell-"+row+"-"+column);
//设置每个格子顶端距离
griCell.css("top",getPosTop(row,column));
//设置每个格子左端距离
griCell.css("left",getPosLeft(row,column));
}
}
//数据初始化
for (var row=0;row<4;row++){
//创建二维数组
board[row]=new Array();
hasConfilcted[row]=new Array();
for (var column=0;column<4;column++){
//每个小格子初始值为0
board[row][column]=0;
hasConfilcted[row][column]=false;
}
}
updateBoardView();
score = 0;
}
//刷新页面
function updateBoardView() {
//清除已有的
$(".number-cell").remove();
//添加新的
for (var row=0;row<4;row++){
for(var column=0;column<4;column++){
$("#grid-container").append("<div class='number-cell' id='number-cell-"+row+"-"+column+"'></div>");
var numberCell = $("#number-cell-"+row+"-"+column);
//如果棋盘数字的值都为0,设置数字格高度宽度为0
if(board[row][column]==0){
numberCell.css("width","0px");
numberCell.css("height","0px");
numberCell.css("top",getPosTop(row,column)+50);
numberCell.css("left",getPosLeft(row,column)+50);
}
//如果不为0,设置高宽、背景色及数字值
else{
numberCell.css("width","100px");
numberCell.css("height","100px");
numberCell.css("top",getPosTop(row,column));
numberCell.css("left",getPosLeft(row,column));
numberCell.css("background-color",getNumberBackgroundColor(board[row][column]));
numberCell.css("color",getNumberColor(board[row][column]));
if(board[row][column]>999){//当数字大于四位数时按位数缩小字体
numberCell.css("font-size",(3*60/(board[row][column].toString().length)).toString()+"px");
}else {
numberCell.css("font-size","60px");
}
numberCell.text(board[row][column]);
}
hasConfilcted[row][column]=false;
}
}
}
function generateOneNumber() {
if(noSpace(board)){
return false;
}
//生成随机位置随机数字
//1.生成随机位置
var randx=parseInt(Math.floor(Math.random()*4));
var randy=parseInt(Math.floor(Math.random()*4));
while (true){
//若当前格子值为0,则可以生成
if(board[randx][randy]==0){
break;
}
//否则重新寻找空格子
var randx=parseInt(Math.floor(Math.random()*4));
var randy=parseInt(Math.floor(Math.random()*4));
}
//2.生成随机数字(需求规定:只可以生成2或4)
var randNumber = Math.random()<0.5?2:4;
//3.将生成的数字显示到生成的位置
board[randx][randy]=randNumber;
ShowNumberWithAnimation(randx,randy,randNumber);
return true;
}
游戏交互逻辑:
/**
* Created by cell on 2018/12/18.
*/
//keydown事件
$(document).keydown(function (event) {
switch (event.keyCode){
case 65://left
case 37:
/*
* moveLeft()
* 完成向左移动逻辑
* 返回值为Boolean类型,判断是否可以向左移动
* */
if(moveLeft()){
setTimeout("generateOneNumber();",210)//填充空位
setTimeout("isGameOver();",300)//判断是否无空格
}
break;
case 87://up
case 38:
if(moveUp()){
setTimeout("generateOneNumber();",210)//填充空位
setTimeout("isGameOver();",300)//判断是否无空格
}
break;
case 68://right
case 38:
if(moveRight()){
setTimeout("generateOneNumber();",210)//填充空位
setTimeout("isGameOver();",300)//判断是否无空格
}
break;
case 83://down
case 40:
if(moveDown()){
setTimeout("generateOneNumber();",210)//填充空位
setTimeout("isGameOver();",300)//判断是否无空格
}
break;
default:
break;
}
})
function moveLeft() {
//返回值为Boolean类型,判断是否可以向左移动
if(!canMoveLeft(board)){
return false;
}
//向左移动逻辑
for(var r=0;r<4;r++){
for(var c=1;c<4;c++){//第一列无法左移
//当前小格有值
if(board[r][c]!=0){
//向左移动
for(var temp=0;temp<c;temp++){//c列左边的列
if(board[r][temp]==0&&noBlokHorizontalCol(r,temp,c,board)){
//当前遍历值为0且与目标块之间无有值块
showMoveAnimation(r,c,r,temp);
//当前值传递到目标块
board[r][temp]=board[r][c];
board[r][c]=0;
continue;
}else if(board[r][temp]==board[r][c]
&&noBlokHorizontalCol(r,temp,c,board)
&&!hasConfilcted[r][temp]){
//当前遍历值和目标块的值相等,且之间无有值的块
showMoveAnimation(r,c,r,temp);
//当前值加到目标块
board[r][temp]+=board[r][c];
board[r][c]=0;
//更新分数
score+=board[r][temp];
updateScore(score);
hasConfilcted[r][temp]=true;
continue;
}
}
}
}
}
setTimeout("updateBoardView();",200);
return true;
}
function moveRight() {
if(!canMoveRight(board)){
return false;
}
for(var r=0;r<4;r++){
for(var c=2;c>=0;c--){
if(board[r][c]!=0){
for(var temp=3;temp>c;temp--){
if(board[r][temp]==0&&noBlokHorizontalCol(r,temp,c,board)){
showMoveAnimation(r,c,r,temp);
board[r][temp]=board[r][c];
board[r][c]=0;
continue;
}else if(board[r][temp]==board[r][c]
&&noBlokHorizontalCol(r,temp,c,board)
&&!hasConfilcted[r][temp]){
showMoveAnimation(r,c,r,temp);
board[r][temp]+=board[r][c];
board[r][c]=0;
score+=board[r][temp];
updateScore(score);
hasConfilcted[r][temp]=true;
continue;
}
}
}
}
}
setTimeout("updateBoardView();",200);
return true;
}
function moveUp() {
if(!canMoveUp(board)){
return false;
}
for(var r=1;r<4;r++){
for(var c=0;c<4;c++){
if(board[r][c]!=0){
for(var temp=0;temp<r;temp++){
if(board[temp][c]==0&&noBlokHorizontalRow(temp,r,c,board)){
showMoveAnimation(r,c,temp,c);
board[temp][c]=board[r][c];
board[r][c]=0;
continue;
}else if(board[temp][c]==board[r][c]
&&noBlokHorizontalRow(temp,r,c,board)
&&!hasConfilcted[temp][c]){
showMoveAnimation(r,c,temp,c);
board[temp][c]+=board[r][c];
board[r][c]=0;
score+=board[temp][c];
updateScore(score);
hasConfilcted[temp][c]=true;
continue;
}
}
}
}
}
setTimeout("updateBoardView();",200);
return true;
}
function moveDown() {
if(!canMoveDown(board)){
return false;
}
for(var r=2;r>=0;r--){
for(var c=0;c<4;c++){
if(board[r][c]!=0){
for(var temp=3;temp>r;temp--){
if(board[temp][c]==0&&noBlokHorizontalRow(temp,r,c,board)){
showMoveAnimation(r,c,temp,c);
board[temp][c]=board[r][c];
board[r][c]=0;
continue;
}else if(board[temp][c]==board[r][c]
&&noBlokHorizontalRow(temp,r,c,board)
&&!hasConfilcted[temp][c]){
showMoveAnimation(r,c,temp,c);
board[temp][c]+=board[r][c];
board[r][c]=0;
score+=board[temp][c];
updateScore(score);
hasConfilcted[temp][c]=true;
continue;
}
}
}
}
}
setTimeout("updateBoardView();",200);
return true;
}
//判读游戏结束条件
function isGameOver() {
//没有未赋值的块并且不能继续滑动合并
if(noSpace(board)&&noMove(board)){
gameover();
}
}
//游戏结束响应
function gameover() {
alert("Game Over!");
$("#grid-container").append(
"<div id='gameover' class='gameover'>" +
"<p>本次得分</p>" +
"<span>" +score+ "</span>" +
"<a href='javascript:restartgame();' id='restartgamebutton'>Restart</a>" +
"</div>");
var gameover = $("#gameover");
gameover.css("width","500px");
gameover.css("height","500px");
gameover.css("background-color","rgba(0,0,0,0.5)");
}