#根据慕课网教导尝试做的一个2048小游戏
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>2048</title>
<link rel="stylesheet" type="text/css" href="2048.css" />
<script src="http://libs.baidu.com/jquery/1.9.0/jquery.min.js" type="text/javascript" charset="utf-8"></script>
<script src="main2048.js" type="text/javascript" charset="utf-8"></script>
<script src="showanimation2048.js" type="text/javascript" charset="utf-8"></script>
<script src="support2048.js" type="text/javascript" charset="utf-8"></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: 500px;
text-align: center;
}
header h1 {
font-family: arial;
font-size: 60px;
font-weight: bold;
}
header #newgamebutton {
margin: 20 auto;
width: 100px;
padding: 10px;
background-color: #8f7a66;
font-family: arial;
color: #fff;
border-radius: 10px;
text-decoration: none;
}
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 {
font-family: arial;
font-size: 20px;
font-weight: bold;
line-height: 100px;
text-align: center;
border-radius: 6px;
position: absolute;
}
// 游戏主逻辑
var board = new Array();
var score = 0;
var hasConflicted = new Array();
$(document).ready(function() {
newgame();
});
function newgame() {
// 初始化棋盘格
init();
// 在随机两个格子生成数字
generateOneNumber();
generateOneNumber();
}
function init() {
for (var i = 0; i < 4; i++)
for (var j = 0; j < 4; j++) {
var gridCell = $("#grid-cell-" + i + "-" + j);
gridCell.css('top', getPosTop(i, j));
gridCell.css('left', getPosLeft(i, j));
}
for (var i = 0; i < 4; i++) {
board[i] = new Array();
hasConflicted[i] = new Array();
for (var j = 0; j < 4; j++) {
board[i][j] = 0;
hasConflicted[i][j] = false;
}
}
// 根据board值进行操作
updateBoardView();
// 分数初始化
score = 0;
}
function updateBoardView() {
// 如果有.number-cell将其移除
$(".number-cell").remove();
for (var i = 0; i < 4; i++)
for (var j = 0; j < 4; j++) {
$("#grid-container").append('<div class="number-cell" id="number-cell-' + i + '-' + j + '"></div>');
var theNumberCell = $("#number-cell-" + i + "-" + j);
if (board[i][j] == 0) {
theNumberCell.css('width', '0px');
theNumberCell.css('heigth', '0px');
theNumberCell.css('top', getPosTop(i, j) + 50);
theNumberCell.css('left', getPosLeft(i, j) + 50);
} else {
theNumberCell.css('width', '100px');
theNumberCell.css('heigth', '100px');
theNumberCell.css('top', getPosTop(i, j));
theNumberCell.css('left', getPosLeft(i, j));
theNumberCell.css('background-color', getNumberBackgroundColor(board[i][j]));
theNumberCell.css('color', getNumberColor(board[i][j]));
theNumberCell.text(board[i][j]);
}
hasConflicted[i][j] = false;
}
}
function generateOneNumber() {
if (nospace(board))
return false;
// 随机一个位置
var randx = parseInt(Math.floor(Math.random() * 4));
var randy = parseInt(Math.floor(Math.random() * 4));
var times = 0;
while (times < 50) {
if (board[randx][randy] == 0)
break;
randx = parseInt(Math.floor(Math.random() * 4));
randy = parseInt(Math.floor(Math.random() * 4));
times++;
}
if (times == 50) {
for (var i = 0; i < 4; i++)
for (var j = 0; j < 4; j++) {
if (board[i][j] == 0) {
randx = i;
randy = j;
}
}
}
// 随机一个数字
var randNumber = Math.random() < 0.5 ? 2 : 4;
// 在随机位置显示出随机数字
board[randx][randy] = randNumber;
showNumberWithAnimation(randx, randy, randNumber);
return true;
}
$(document).keydown(function(event) {
switch (event.keyCode) {
case 37: //left
if (moveLeft()) {
setTimeout("generateOneNumber()", 210);
setTimeout("isgameover()", 300);
}
break;
case 38: //up
if (moveUp()) {
setTimeout("generateOneNumber()", 210);
setTimeout("isgameover()", 300);
}
break;
case 39: //right
if (moveRight()) {
setTimeout("generateOneNumber()", 210);
setTimeout("isgameover()", 300);
}
break;
case 40: //down
if (moveDown()) {
setTimeout("generateOneNumber()", 210);
setTimeout("isgameover()", 300);
}
break;
default: //defauit
break;
}
});
function isgameover() {
if (nospace(board) && nomove(board)) {
gameover();
}
}
function gameover() {
alert("gameover!")
}
function moveLeft() {
// 判断canMoveLeft()
// 1:左边是否没有数字
// 2:左边数字是否和自己相等
if (!canMoveLeft(board))
return false;
// movLeft
// 1:落脚位置是否为空
// 2:落脚位置数字和待判定元素位置相等i
// 3:移动路径中是否有障碍物
for (var i = 0; i < 4; i++)
for (var j = 1; j < 4; j++) {
if (board[i][j] != 0) {
for (var k = 0; k < j; k++) {
if (board[i][j] == 0 && noBlockHorizontal(i, k, j, board)) {
// move
showMoveAnimation(i, j, i, k);
board[i][k] = board[i][j];
board[i][j] = 0;
continue;
} else if (board[i][k] == board[i][j] && noBlockHorizontal(i, k, j, board) && !hasConflicted[i][k]) {
// move
showMoveAnimation(i, j, i, k);
// add
board[i][k] *= 2;
board[i][j] = 0;
// add score
score += board[i][k];
// 通知前台
updateScore(score);
hasConflicted[i][k] = true;
continue;
}
}
}
}
setTimeout("updateBoardView()", 200);
return true;
}
function moveRight() {
if (!canMoveRight(board))
return false;
for (var i = 0; i < 4; i++)
for (var j = 2; j >= 0; j--) {
if (board[i][j] != 0) {
for (var k = 3; k > j; k--) {
if (board[i][k] == 0 && noBlockHorizontal(i, j, k, board)) {
// move
showMoveAnimation(i, j, i, k);
board[i][k] = board[i][j];
board[i][j] = 0;
continue;
} else if (board[i][k] == board[i][j] && noBlockHorizontal(i, j, k, board) && !hasConflicted[i][k]) {
// move
showMoveAnimation(i, j, i, k);
// add
board[i][k] *= 2;
board[i][j] = 0;
// add score
score += board[i][k];
// 通知前台
updateScore(score);
hasConflicted[i][k] = true;
continue;
}
}
}
}
setTimeout("updateBoardView()", 200);
return true;
}
function moveUp() {
if (!canMoveUp(board))
return false;
for (var j = 0; j < 4; j++)
for (var i = 1; i < 4; i++) {
if (board[i][j] != 0) {
for (var k = 0; k < i; k++) {
if (board[k][j] == 0 && noBlockVertical(j, k, i, board)) {
// move
showMoveAnimation(i, j, k, j);
board[k][j] = board[i][j];
board[i][j] = 0;
continue;
} else if (board[k][j] == board[i][j] && noBlockVertical(j, k, i, board) && !hasConflicted[k][j]) {
// move
showMoveAnimation(i, j, k, j);
// add
board[k][j] *= 2;
board[i][j] = 0;
// add score
score += board[k][j];
// 通知前台
updateScore(score);
hasConflicted[k][j] = true;
continue;
}
}
}
}
setTimeout("updateBoardView()", 200);
return true;
}
function moveDown() {
if (!canMoveDown(board))
return false;
for (var j = 0; j < 4; j++)
for (var i = 2; i >= 0; i--) {
if (board[i][j] != 0) {
for (var k = 3; k > i; k--) {
if (board[k][j] == 0 && noBlockVertical(j, i, k, board)) {
// move
showMoveAnimation(i, j, k, j);
board[k][j] = board[i][j];
board[i][j] = 0;
continue;
} else if (board[k][j] == board[i][j] && noBlockVertical(j, i, k, board) && !hasConflicted[k][j]) {
// move
showMoveAnimation(i, j, k, j);
// add
board[k][j] *= 2;
board[i][j] = 0;
// add score
score += board[k][j];
// 通知前台
updateScore(score);
hasConflicted[k][j] = true;
continue;
}
}
}
}
setTimeout("updateBoardView()", 200);
return true;
}
// 动画效果逻辑
function showNumberWithAnimation(i, j, randNumber) {
var numberCell = $("#number-cell-" + i + "-" + j);
numberCell.css('background-color', getNumberBackgroundColor(randNumber));
numberCell.css('color', getNumberColor(randNumber));
numberCell.text(randNumber);
numberCell.animate({
width: "100px",
height: "100px",
top: getPosTop(i, j),
left: getPosLeft(i, j)
}, 50);
}
function showMoveAnimation(fromx, fromy, tox, toy) {
var numberCell = $("#number-cell-" + fromx + "-" + fromy);
numberCell.animate({
top: getPosTop(tox, toy),
left: getPosLeft(tox, toy)
}, 200);
}
function updateScore(score) {
$("#score").text(score);
}
// 底层逻辑
function getPosTop(i, j) {
return 20 + i * 120
}
function getPosLeft(i, j) {
return 20 + j * 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;
}
return "black";
}
function getNumberColor(number) {
if (number <= 4) {
return "#776e65"
}
return "white";
}
function nospace(board) {
for (var i = 0; i < 4; i++)
for (var j = 0; j < 4; j++)
if (board[i][j] == 0)
return false;
return true;
}
// moveLeft
function canMoveLeft(board) {
for (var i = 0; i < 4; i++)
for (var j = 1; j < 4; j++)
if (board[i][j] != 0)
if (board[i][j - 1] == 0 || board[i][j - 1] == board[i][j])
return true;
return false;
}
// moveRight
function canMoveRight(board) {
for (var i = 0; i < 4; i++)
for (var j = 2; j >= 0; j--)
if (board[i][j] != 0)
if (board[i][j + 1] == 0 || board[i][j + 1] == board[i][j])
return true;
return false;
}
// moveUp
function canMoveUp(board) {
for (var j = 0; j < 4; j++)
for (var i = 1; i < 4; i++)
if (board[i][j] != 0)
if (board[i - 1][j] == 0 || board[i - 1][j] == board[i][j])
return true;
return false;
}
// moveDown
function canMoveDown(board) {
for (var j = 0; j < 4; j++)
for (var i = 2; i >= 0; i--)
if (board[i][j] != 0)
if (board[i + 1][j] == 0 || board[i + 1][j] == board[i][j])
return true;
return false;
}
// left and right
function noBlockHorizontal(row, col1, col2, board) {
for (var i = col1 + 1; i < col2; i++)
if (board[row][i] != 0)
return false;
return true;
}
// up and down
function noBlockVertical(col, row1, row2, board) {
for (var i = row1 + 1; i < row2; i++)
if (board[i][col] != 0)
return false;
return true;
}
function nomove(board) {
if (canMoveLeft(board) || canMoveRight(board) || canMoveUp(board) || canMoveDown(board))
return false;
return true;
}