html部分代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>2048</title>
<link rel="stylesheet" href="css/2048.css">
</head>
<body>
<header>
<div class="container">
<h1><span>2</span><span>0</span><span>4</span><span>8</span></h1>
<p class="inspired">2048</p>
</div>
</header>
<div class="container">
<div class="directions">
<p><strong>如何玩:</strong> 使用你的箭头键移动瓷砖。两个瓷砖相互滑动时,它们合并成一个!</p>
</div>
<div class="scores">
<div class="score-container">
分数:
<div class="score">
<div id="score">0</div>
<div class="add" id="add"></div>
</div>
</div>
</div>
<div class="game">
<div class="main_box">
<div class="min_box" id="number00"></div>
<div class="min_box" id="number01"></div>
<div class="min_box" id="number02"></div>
<div class="min_box" id="number03"></div>
<div class="min_box" id="number10"></div>
<div class="min_box" id="number11"></div>
<div class="min_box" id="number12"></div>
<div class="min_box" id="number13"></div>
<div class="min_box" id="number20"></div>
<div class="min_box" id="number21"></div>
<div class="min_box" id="number22"></div>
<div class="min_box" id="number23"></div>
<div class="min_box" id="number30"></div>
<div class="min_box" id="number31"></div>
<div class="min_box" id="number32"></div>
<div class="min_box" id="number33"></div>
</div>
<div class="end" id="end">游戏结束
<div class="monkey"></div>
<button class="btn not-recommended__item js-restart-btn" id="try-again">再来一次</button>
</div>
</div>
<div class="not-recommended">
<button class="btn not-recommended__item js-restart-btn" id="restart">重新开始游戏</button>
</div>
<script src="js/2048.js"></script>
</body>
</html>
css部分
* {
margin: 0px;
padding: 0px;
}
.case {
width: 450px;
height: 600px;
margin: 20px auto;
position: relative;
}
.above_box {
width: 450px;
height: 150px;
margin: 0px auto;
}
.logo {
width: 350px;
height: 150px;
float: left;
}
.logo_num {
color: #766f67;
font-size: 60px;
font-family: '微软雅黑';
font-weight: bold;
}
.logo_font {
color: #9B988F;
float: left;
font-size: 16px;
}
.above_box button {
width: 100px;
height: 50px;
color: white;
font-size: 15px;
background-color: #8b7c65;
border: none;
margin-top: 10px;
float: right;
}
.countScore {
width: 100px;
height: 70px;
background-color: #8b7c65;
color: white;
float: right;
margin-top: 10px;
}
.countScore p {
line-height: 30px;
text-align: center;
}
.countScore span {
display: block;
line-height: 30px;
text-align: center;
font-weight: bold;
font-size: 20px;
}
.main_box {
width: 450px;
height: 450px;
margin: 0px auto;
background-color: #bbada0;
border-radius: 10px;
}
.main_box2 {
width: 450px;
height: 450px;
margin: 0px auto;
border-radius: 10px;
background-color: rgba(0, 0, 0, 0.4);
position: absolute;
font-size: 50px;
color: white;
text-align: center;
line-height: 450px;
}
.main_box2 button {
width: 101px;
height: 50px;
color: white;
font-size: 20px;
background-color: rgba(0, 0, 0, 0);
border: none;
position: absolute;
top: 260px;
left: 165px;
}
.game {
z-index: 1;
}
.min_box {
width: 100px;
height: 100px;
background-color: #ccc0b2;
float: left;
margin: 10px 0 0 10px;
border-radius: 5px;
font-size: 35px;
line-height: 100px;
text-align: center;
color: #796f65;
}
.n2 {
background-color: #aae3da
}
.n4 {
background-color: #ede0c8
}
.n8 {
background-color: #f2b179
}
.n16 {
background-color: #f59563
}
.n32 {
background-color: #f67c5f
}
.n64 {
background-color: #f65e3b
}
.n128 {
background-color: #edcf72
}
.n256 {
background-color: #edcc61
}
.n512 {
background-color: #9c0
}
.n1024 {
background-color: #33b5e5
}
.n2048 {
background-color: #09c9c0
}
.n4096 {
background-color: #a6c
}
.n8192 {
background-color: #93c
}
.n2,
.n4 {
color: #776e65
}
.n1024,
.n2048,
.n4096,
.n8192 {
font-size: 40px
}
.btn {
font-family: inherit;
font-size: 1rem;
border: none;
background: #1B9AAA;
letter-spacing: 1px;
color: white;
font-weight: 300;
padding: 0.9em 1.5em;
border-radius: 3px;
border: 1px solid transparent;
cursor: pointer;
}
.btn:hover {
background-color: #14727e;
}
.btn:active {
background-color: #0d4a52;
}
.btn:focus {
box-shadow: 0 0 10px #0d4a52 inset;
outline: none;
}
.not-recommended {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
margin-top: 3rem;
}
body,
html {
position: relative;
width: 100%;
height: 100%;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-ms-flex-direction: column;
flex-direction: column;
font-family: "Arvo", Helvetica, sans-serif;
font-family: 12px;
color: #555;
background: #F8FFE5;
}
strong {
font-weight: bold;
}
p {
line-height: 1.6;
}
.inspired {
height: 20px;
font-size: 0.9rem;
color: #9a9a95;
}
header {
height: 120px;
color: #F8FFE5;
text-align: center;
}
header span {
display: inline-block;
box-sizing: border-box;
width: 4rem;
height: 4rem;
line-height: 4rem;
margin: 0 0.4rem;
background: #FFC43D;
}
header span:nth-of-type(2) {
background: #EF476F;
}
header span:nth-of-type(3) {
background: #1B9AAA;
}
header span:nth-of-type(4) {
background: #06D6A0;
}
h1 {
font-size: 2.2rem;
}
.directions {
padding: 1rem;
border-top: 1px solid #9a9a95;
border-bottom: 1px solid #9a9a95;
}
.container {
margin: 0 auto;
padding-bottom: 3.5rem;
-webkit-box-flex: 1;
-ms-flex: 1;
flex: 1;
width: 100%;
max-width: 550px;
text-align: center;
}
header .container {
padding: 0;
padding: 2rem 4rem;
max-width: 900px;
}
.scores {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center;
}
.score-container {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
margin: 1.8rem;
font-size: 1.2rem;
line-height: 1;
color: #555;
}
.score-container.best-score {
color: #9a9a95;
}
.score {
margin-left: 1rem;
position: relative;
font-weight: bold;
font-size: 1.5rem;
vertical-align: middle;
text-align: right;
}
.game {
position: relative;
margin: 0 auto;
background: #9a9a95;
padding: 7px;
display: inline-block;
border-radius: 3px;
box-sizing: border-box;
}
.tile-container {
border-radius: 6px;
position: relative;
width: 400px;
height: 400px;
}
.game {
position: relative;
margin: 0 auto;
background: #9a9a95;
padding: 7px;
display: inline-block;
border-radius: 3px;
box-sizing: border-box;
}
.tile-container {
border-radius: 6px;
position: relative;
width: 400px;
height: 400px;
}
.tile,
.background {
display: block;
color: #F8FFE5;
position: absolute;
width: 100px;
height: 100px;
box-sizing: border-box;
text-align: center;
}
.background {
z-index: 1;
text-align: center;
border: 7px solid #9a9a95;
background-color: #F8FFE5;
}
.tile {
opacity: 0;
z-index: 2;
background: #FFC43D;
color: #F8FFE5;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center;
font-size: 1.8rem;
align-items: center;
-webkit-transition: 110ms ease-in-out;
transition: 110ms ease-in-out;
border-radius: 3px;
border: 7px solid #9a9a95;
box-sizing: border-box;
}
.end {
opacity: 0;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: -1;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-ms-flex-direction: column;
flex-direction: column;
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
background: rgba(85, 85, 85, 0.4);
color: white;
font-size: 2rem;
-webkit-transition: opacity 0.3s ease-in-out;
transition: opacity 0.3s ease-in-out;
}
.end .btn {
margin-top: 1rem;
}
.end.active {
opacity: 1;
z-index: 1000;
}
JS部分
var game = {
// 定义二维数组
data: [],
// 定义行数
RN: 4,
// 定义列数
CN: 4,
//记录分数
score: 0,
// 游戏结束
gameover: 0,
// 游戏开始
start() {
// 初始化数组
this.data = [
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0]
];
this.score = 0;
var that = this;
// 生成开始的二个随机位置的随机2或4
this.randomNum();
this.randomNum();
// 渲染函数
this.updataeView();
// 定义4个键盘事件
document.onkeydown = function(e) {
switch (e.keyCode) {
case 37: //左移
that.moveLeft();
break;
case 38: // 上移
that.moveUp();
break;
case 39: // 右移
that.moveRight();
break;
case 40: // 下移
that.moveDown();
break;
}
};
},
// 定义随机函数
randomNum() {
var r, c;
// 判断数组中但前位置是否为空
while (true) {
r = parseInt(Math.random() * this.RN);
c = parseInt(Math.random() * this.CN);
if (this.data[r][c] == 0) {
this.data[r][c] = Math.random() < 0.6 ? 2 : 4;
break;
} else if (this.isFull()) {
break;
}
}
},
// 定义渲染函数
updataeView() {
for (var r = 0; r < this.RN; r++) {
for (var c = 0; c < this.CN; c++) {
if (this.data[r][c]) {
// 不为0 将值赋给div
document.getElementById("number" + r + c).innerHTML = this.data[r][c];
// 上色
document.getElementById("number" + r + c).className = "min_box n" + this.data[r][c];
} else {
document.getElementById("number" + r + c).innerHTML = "";
document.getElementById("number" + r + c).className = "min_box n";
}
}
}
//更新分数
document.getElementById("score").innerHTML = this.score;
},
// 左移前拍照
moveLeft() {
for (var r = 0; r < this.RN; r++) { //遍历data中的每一列
this.moveLeftdown(r); //上移当前行
}
// 先判断是否是满格
// 不是满格 生成随机数
// 是满格 判断游戏是否结束
if (!this.isFull()) {
this.randomNum();
this.updataeView();
} else if (this.gameOver()) {
this.start = this.gameOver;
}
},
// 左移事件
moveLeftdown(r) {
//c从0开始,遍历当前列中的元素,到<CN-1结束,每次+1
for (var c = 0; c < this.CN; c++) {
//找到r之后下一个不为0的值的位置,存在nextc中
var nextc = this.moveLeftinrow(r, c);
//找到c之后下一个不为0的值的位置,存在nextc中
if (nextc == -1) {
break; //如果nextr等于-1,退出循环
} else {
if (this.data[r][c] == 0) { //如果当前位置等于0
this.data[r][c] = this.data[r][nextc]; //将当前位置设为下一个位置的值
this.data[r][nextc] = 0; //将下一位置设为0
c--; //保证下次依然检查当前元素
} else if (this.data[r][c] == this.data[r][nextc]) {
this.data[r][c] *= 2; //当前位置 = 当前位置值*2
this.data[r][nextc] = 0; // 将下一位置设为0
this.score += this.data[r][c]; // 增加分数
}
}
}
},
// 找r行c列位置之后,不为0的下一个位置
moveLeftinrow(r, c) {
for (var i = c + 1; i < this.CN; i++) { //i+1开始,遍历r行剩余元素
if (this.data[r][i] != 0) { //如果i不等于0
return i;
}
}
return -1; //循环结束,返回-1
},
// 上移前拍照
moveUp() {
// 判断是否移动
for (var c = 0; c < this.CN; c++) { //遍历data中的每一列
this.moveUpdown(c); //右移当前行
}
// 先判断是否是满格
// 不是满格 生成随机数
// 是满格 判断游戏是否结束
if (!this.isFull()) {
this.randomNum();
this.updataeView();
} else if (this.gameOver()) {
this.start = this.gameOver;
}
},
//上移事件
moveUpdown(c) {
//r从0开始,遍历当前列中的元素,到<RN-1结束,每次+1
for (var r = 0; r < this.RN - 1; r++) {
//找到c之后下一个不为0的值的位置,存在next中
var nextr = this.moveUpinrow(r, c);
if (nextr == -1) {
break; //如果nextr等于-1,退出循环
} else {
if (this.data[r][c] == 0) { //如果当前位置等于0
this.data[r][c] = this.data[nextr][c]; //将当前位置设为下一个位置的值
this.data[nextr][c] = 0; //将下一位置设为0
r--; //保证下次依然检查当前元素
} else if (this.data[r][c] == this.data[nextr][c]) { //否则,如果当前位置等于下一位置
this.data[r][c] *= 2; //当前位置 = 当前位置值*2
this.score += this.data[r][c]; //增加分数
this.data[nextr][c] = 0; //将下一位置设为0
}
}
}
},
//找r行c列位置之后,不为0的下一个位置
moveUpinrow(r, c) {
for (var i = r + 1; i < this.RN; i++) { //i+1开始,遍历c列剩余元素
if (this.data[i][c] != 0) { //如果i不等于0
return i;
}
}
return -1; //循环结束,返回-1
},
//右移前拍照
moveRight() {
for (var r = 0; r < this.RN; r++) { //遍历data中的每一行
this.moveRightdown(r); //右移当前行
}
// 先判断是否是满格
// 不是满格 生成随机数
// 是满格 判断游戏是否结束
if (!this.isFull()) {
this.randomNum();
this.updataeView();
} else if (this.gameOver()) {
this.start = this.gameOver;
}
},
//右移事件
moveRightdown(r) {
//c从CN-1开始,到>0结束,每次-1
for (var c = this.CN - 1; c > 0; c--) {
//找到c之后下一个不为0的值的位置,存在nextc中
var nextc = this.moveRightinrow(r, c);
if (nextc == -1) {
break; //如果nextc等于-1,退出循环
} else {
if (this.data[r][c] == 0) { //如果当前位置等于0
this.data[r][c] = this.data[r][nextc]; //将当前位置设为下一个位置的值
this.data[r][nextc] = 0; //将下一位置设为0
c++; //保证下次依然检查当前元素
} else if (this.data[r][c] == this.data[r][nextc]) { //否则,如果当前位置等于下一位置
this.data[r][c] *= 2; //当前位置 = 当前位置值*2
this.score += this.data[r][c]; //增加分数
this.data[r][nextc] = 0; //将下一位置设为0
}
}
}
},
//找r行c列位置之后,不为0的下一个位置
moveRightinrow(r, c) {
for (var i = c - 1; i >= 0; i--) { //i从c+1开始,遍历r行剩余元素
if (this.data[r][i] != 0) { //如果i不等于0
return i;
}
}
return -1; //循环结束,返回-1
},
// 下移前拍照
moveDown() {
for (var c = 0; c < this.CN; c++) { //遍历data中的每一列
this.moveDowndown(c); //下移当前行
}
// 先判断是否是满格
// 不是满格 生成随机数
// 是满格 判断游戏是否结束
if (!this.isFull()) {
this.randomNum();
this.updataeView();
} else if (this.gameOver()) {
this.start = this.gameOver;
}
},
//下移事件
moveDowndown(c) {
//r从RN-1开始,遍历当前列中的元素,到>0结束,每次-1
for (var r = this.RN - 1; r > 0; r--) {
//找到c之后下一个不为0的值的位置,存在nextr中
var nextr = this.moveDowninrow(r, c);
if (nextr == -1) {
break; //如果nextr等于-1,退出循环
} else { //否则
if (this.data[r][c] == 0) { //如果当前位置等于0
this.data[r][c] = this.data[nextr][c]; //将当前位置设为下一个位置的值
this.data[nextr][c] = 0; //将下一位置设为0
r++; //保证下次依然检查当前元素
} else if (this.data[r][c] == this.data[nextr][c]) { //否则,如果当前位置等于下一位置
this.data[r][c] *= 2; //当前位置 = 当前位置值*2
this.score += this.data[r][c]; //增加分数
this.data[nextr][c] = 0; //将下一位置设为0
}
}
}
},
//找r行c列位置之后,不为0的下一个位置
moveDowninrow(r, c) {
for (var i = r - 1; i >= 0; i--) { //i从r-1开始,遍历c列剩余元素
if (this.data[i][c] != 0) { //如果i不等于0
return i;
}
}
return -1; //循环结束,返回-1
},
//判断游戏状态为结束
gameOver() {
//如果没有满,则返回false
if (!this.isFull()) {
return false;
} else {
//从左上角第一个元素开始,遍历二维数组
for (var r = 0; r < this.RN; r++) {
for (var c = 0; c < this.CN; c++) {
//如果当前元素不是最右侧元素
if (c < this.CN - 1) {
// 如果当前元素==右侧元素
if (this.data[r][c] == this.data[r][c + 1]) {
return false;
}
}
//如果当前元素不是最下方元素
if (r < this.RN - 1) {
// 如果当前元素==下方元素
if (this.data[r][c] == this.data[r + 1][c]) {
return false;
}
}
}
}
return this.gameoverupdate();
}
},
//判断是否满格
isFull() {
for (var r = 0; r < this.RN; r++) {
for (var c = 0; c < this.CN; c++) {
if (this.data[r][c] == 0) { //如果当前元素等于0
return false; //返回false
}
}
}
return true; //遍历结束,返回true
},
gameoverupdate() {
var end = document.getElementById("end");
end.classList.add("active")
},
}
game.start();
var btn = document.getElementsByClassName("btn")[0];
var btn2 = document.getElementsByClassName("btn")[1];
btn.onclick = function() {
game.start();
end.classList.remove("active");
game.score = 0;
}
btn2.onclick = function() {
game.start();
game.score = 0;
}