目录
1.文件目录
2.代码
2.1 javascript代码
2.2 css代码
2.3 html代码
序言:前端大作业,html+css+js实现2048游戏,有方块移动动画、计分板和历史记录回放。有任何问题,欢迎在评论区指出。
var game = {
data: [],//储存游戏数据
score: 0,//当前分数
dataCopy: [],//三维数组,存放历史记录
scoreCopy: [],//存放分数历史记录
copyNum: 0,//记录备份的数量
isMoved: false,
isEnd: false,
//初始化
initial: function () {
//将胜利与结束图层隐藏
document.getElementById("gameWinContainer").style.display = "none";
document.getElementById("gameOverContainer").style.display = "none";
//初始化游戏数据
for (var i = 0; i < 4; i++) {
this.data[i] = [];
for (var j = 0; j < 4; j++) {
this.data[i][j] = 0;
}
}
this.dataCopy = [];
this.dataCopyNum = 0;
this.isMoved = false;
this.isEnd = false;
this.score = 0;
this.getRandomNumber();
this.getRandomNumber();
//将数组显示在网页上
this.updateView();
//保存历史记录
this.save();
//按键绑定以移动
this.move();
},
//在数组中上生成随机数
getRandomNumber: function () {
var di = [];
var dj = [];
var index = 0;
for (var i = 0; i < 4; i++) {
for (var j = 0; j < 4; j++) {
if (this.data[i][j] == 0) {
di[index] = i;
dj[index] = j;
index++;
}
}
}
if (index == 0) {
return;
}
var rand = Math.floor(Math.random() * index);
var i = di[rand];
var j = dj[rand];
this.data[i][j] = Math.random() < 0.85 ? 2 : 4;
},
//监测键盘按键并移动元素
move: function () {
document.onkeydown = function (event) {
switch (event.keyCode) {
case 37:
game.moveLeft();
break;
case 65:
game.moveLeft();
break;
case 38:
game.moveUp();
break;
case 87:
game.moveUp();
break;
case 39: game.moveRight();
break;
case 68:
game.moveRight();
break;
case 40:
game.moveDown();
break;
case 83:
game.moveDown();
break;
default:
break;
}
}
},
//保存历史数据
save: function () {
//三维数组,备份数据
this.dataCopy[this.copyNum] = [];
this.scoreCopy[this.copyNum] = this.score;
for (var i = 0; i < 4; i++) {
this.dataCopy[this.copyNum][i] = [];
for (var j = 0; j < 4; j++) {
this.dataCopy[this.copyNum][i][j] = this.data[i][j];
}
}
this.copyNum++;
},
//更新界面显示
updateView: function () {
for (var i = 0; i < 4; i++) {
for (var j = 0; j < 4; j++) {
var element = document.getElementById("elem_" + i + "_" + j);
var elemNum = this.data[i][j];
// 如果数组中对应的值是0,方块的内容设置为空
if (elemNum == 0) {
element.innerHTML = "";
element.className = "elem_" + i + "_" + j;
}
else {
element.innerHTML = elemNum;
element.className = "elem_" + i + "_" + j + " " + "n" + elemNum;
}
}
}
//更新分数
var score = document.getElementById("userScore");
score.innerHTML = this.score;
},
//移动一个元素
moveSingle: function (i, j, di, dj) {
if (this.isEnd) {
return;
}
if (this.data[i][j] == 0) {
return;
}
var ti = i + di;//结束位置
var tj = j + dj;//结束位置
var ts = this.data[i][j];//移动产生的分数
//没越界且是空格子就可以移动
while (ti >= 0 && ti < 4 && tj >= 0 && tj < 4 && this.data[ti][tj] == 0) {
ti += di;
tj += dj;
}
//如果移动到越界
if (ti < 0 || ti > 3 || tj < 0 || tj > 3) {
ti = ti - di;
tj = tj - dj;
}
//遇到其他方块
else {
if (this.data[ti][tj] == this.data[i][j]) {
ts = 2 * this.data[ti][tj];
this.score += this.data[ti][tj];
}
else {
ti = ti - di;
tj = tj - dj;
}
}
//能否滑动的关键
if (ti != i || tj != j) {
this.data[ti][tj] = ts;
this.data[i][j] = 0;
this.isMoved = true;
//通过修改elem元素的类名,使其定位发生变化,并通过transition属性产生动画
var elems = document.getElementById("elem_" + i + "_" + j);
var elemt = document.getElementById("elem_" + ti + "_" + tj);
elems.id = "elem_" + ti + "_" + tj;
elems.className = "elem_" + ti + "_" + tj;
elemt.id = "elem_" + i + "_" + j;
elemt.classname = "elem_" + i + "_" + j;
elemt.innerHTML = "";
}
},
//全部元素向左移
moveLeft: function () {
this.isMoved = false;
var di = 0;
var dj = -1;
for (var i = 0; i < 4; i++) {
for (var j = 0; j < 4; j++) {
this.moveSingle(i, j, di, dj);
}
}
this.check();
},
//向右移
moveRight: function () {
this.isMoved = false;
var di = 0;
var dj = 1;
//位移矢量为(0,1)
for (var i = 0; i <= 3; i++) {
for (var j = 3; j >= 0; j--) {
this.moveSingle(i, j, di, dj);
}
}
this.check();
},
//向下移
moveDown: function () {
this.isMoved = false;
var di = 1;
var dj = 0;
for (var j = 0; j < 4; j++) {
for (var i = 3; i >= 0; i--) {
this.moveSingle(i, j, di, dj);
}
}
this.check();
},
//向上移
moveUp: function () {
this.isMoved = false;
var di = -1;
var dj = 0;
for (var j = 0; j < 4; j++) {
for (var i = 0; i < 4; i++) {
this.moveSingle(i, j, di, dj);
}
}
this.check();
},
//检测是否应当生成随机数,游戏是否结束,是否胜利
check: function () {
if (this.isMoved) {
this.getRandomNumber();
this.updateView();
this.save();
}
if (this.isWin()) {
this.isEnd = true;
var elem = document.getElementById("gameWinContainer");
elem.style.display = "block";
} else if (this.isOver()) {
this.isEnd = true;
var elem = document.getElementById("gameOverContainer");
elem.style.display = "block";
}
},
//判断游戏是否失败
isOver: function () {
var di = [0, 0, 1, -1];
var dj = [1, -1, 0, 0];
for (var i = 0; i < 4; i++) {
for (var j = 0; j < 4; j++) {
for (var k = 0; k < 4; k++) {
if (this.data[i][j] == 0) {
return false;
}
var ti = i + di[k];
var tj = j + dj[k];
if (0 <= ti && ti < 4 && 0 <= tj && tj < 4) {
if (this.data[ti][tj] == this.data[i][j]) {
return false;
}
}
}
}
}
return true;
},
//判断游戏是否胜利
isWin: function () {
for (var i = 0; i < 4; i++) {
for (var j = 0; j < 4; j++) {
if (this.data[i][j] == 2048) {
return true;
}
}
}
return false;
},
//撤回一步
goBack: function () {
//第一步或游戏结束无法撤回
if (this.copyNum <= 1 || this.isEnd) {
return;
}
//将数组转化为历史记录中的数组
for (var i = 0; i < 4; i++) {
for (var j = 0; j < 4; j++) {
this.data[i][j] = this.dataCopy[this.copyNum - 2][i][j];
}
}
//修改分数
this.score = this.scoreCopy[this.copyNum - 2];
//修改备份数量
this.copyNum--;
//更新网页显示
this.updateView();
}
}
body {
background: #faf8ef;
}
.title {
display: inline-block;
width: 200px;
height: 100px;
font-size: 80px;
font-weight: 700;
line-height: 100px;
color: #776e65;
position: absolute;
top: 60px;
left: 480px;
}
.score_newGame {
width: 250px;
height: 100px;
position: absolute;
top: 60px;
left: 700px;
}
.newGame {
display: block;
width: 150px;
height: 45px;
font-size: 20px;
text-decoration-line: none;
text-align: center;
line-height: 45px;
background-color: #CAC0B4;
border-radius: 5px;
color: #faf8ef;
position: absolute;
top: 10px;
left: 5px;
}
.back {
display: block;
width: 80px;
height: 45px;
font-size: 20px;
text-decoration-line: none;
text-align: center;
line-height: 45px;
background-color: #CAC0B4;
border-radius: 5px;
color: #faf8ef;
position: absolute;
top: 10px;
left: 170px;
}
/*伪类选择器*/
a:hover {
color: #CAC0B4;
background-color: #faf8ef;
transition: color 0.2s;
}
a:active {
color: white;
background-color: #faf8ef;
transition: color 0.2s;
}
.score {
font-size: 30px;
color: #776e65;
position: absolute;
top: 55px;
left: 5px;
}
.userScore {
font-size: 30px;
color: #776e65;
position: absolute;
top: 55px;
left: 90px;
}
.container_base {
display: block;
position: absolute;
top: 170px;
left: 470px;
bottom: 150px;
background-color: rgba(185, 173, 161, 0.3);
height: 495px;
width: 495px;
border-radius: 10px;
z-index: -1;
}
.container {
display: block;
position: absolute;
top: 170px;
left: 470px;
bottom: 150px;
background-color: rgba(185, 173, 161, 0);
height: 495px;
width: 495px;
border-radius: 10px;
}
.gameOverContainer {
display: none;
position: absolute;
top: 170px;
left: 470px;
background-color: rgba(0, 0, 0, 0.4);
color: black;
height: 495px;
width: 495px;
border-radius: 10px;
font-size: 50px;
text-align: center;
}
.gameWinContainer {
display: none;
position: absolute;
top: 170px;
left: 470px;
background-color: rgba(139, 197, 89, 0.4);
color: #f67c5f;
height: 495px;
width: 495px;
border-radius: 10px;
font-size: 50px;
text-align: center;
}
.container_base div {
border-radius: 15px;
width: 110px;
height: 110px;
background-color: rgb(202, 192, 180);
position: absolute;
z-index: -1;
}
.container div {
font-size: 45px;
text-align: center;
color: #ffffff;
border-radius: 15px;
width: 110px;
height: 110px;
background-color: rgba(red, green, blue, 0);
line-height: 110px;
position: absolute;
/*平滑移动*/
transition: top 0.15s, left 0.15s, background-color 0.15s, color 0.15s;
}
.elem_0_0 {
top: 11px;
left: 11px;
}
.elem_0_1 {
top: 11px;
left: 132px;
}
.elem_0_2 {
top: 11px;
left: 253px;
}
.elem_0_3 {
top: 11px;
left: 374px;
}
.elem_1_0 {
top: 132px;
left: 11px;
}
.elem_1_1 {
top: 132px;
left: 132px;
}
.elem_1_2 {
top: 132px;
left: 253px;
}
.elem_1_3 {
top: 132px;
left: 374px;
}
.elem_2_0 {
top: 253px;
left: 11px;
}
.elem_2_1 {
top: 253px;
left: 132px;
}
.elem_2_2 {
top: 253px;
left: 253px;
}
.elem_2_3 {
top: 253px;
left: 374px;
}
.elem_3_0 {
top: 374px;
left: 11px;
}
.elem_3_1 {
top: 374px;
left: 132px;
}
.elem_3_2 {
top: 374px;
left: 253px;
}
.elem_3_3 {
top: 374px;
left: 374px;
}
.n2 {
background-color: #eee3da
}
.n4 {
background-color: #efe0c8
}
.n8 {
background-color: #f26179
}
.n16 {
background-color: #f59563
}
.n32 {
background-color: #ef7c2f
}
.n64 {
background-color: #f65e36
}
.n128 {
background-color: #edcf72
}
.n256 {
background-color: #edcc61
}
.n512 {
background-color: #9c0
}
.n1024 {
background-color: #3365a5
}
.n2048 {
background-color: #09c
}
2048游戏
Game over,
You lose!
Game over,
You win!