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="2048.css">
</head>
<body>
<h1>2048</h1>
<ul>
<li id="1"></li>
<li id="2"></li>
<li id="3"></li>
<li id="4"></li>
<li id="5"></li>
<li id="6"></li>
<li id="7"></li>
<li id="8"></li>
<li id="9"></li>
<li id="10"></li>
<li id="11"></li>
<li id="12"></li>
<li id="13"></li>
<li id="14"></li>
<li id="15"></li>
<li id="16"></li>
</ul>
<div class="start">重新开始</div>
<div class="intro">玩法说明:小键盘上下左右键控制方格移动,相邻格子数字相同则可合并,合成2048后游戏胜利</div>
<div id="result"></div>
<script src="2048.js"></script>
</body>
</html>
CSS
* {
margin: 0;
padding: 0;
}
body {
font-family: "微软雅黑";
color: #ffffff;
user-select: none;
}
h1 {
width: 300px;
font-size: 60px;
line-height: 1.5em;
text-align: center;
margin: 20px auto 0;
background: #ecc400;
border-radius: 20px;
}
ul {
width: fit-content;
margin: 50px auto 0;
padding: 10px;
list-style: none;
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-gap: 10px;
background: #bdada0;
}
ul>li {
width: 100px;
height: 100px;
font-size: 50px;
font-weight: bolder;
text-align: center;
line-height: 100px;
background: #ccbeb1;
border-radius: 10px;
transition: background 0.4s;
}
.start {
width: fit-content;
height: 1.5em;
margin: 50px auto;
padding: 0 5px 0 10px;
color: #ffffff;
font-size: 40px;
font-weight: bold;
text-align: center;
line-height: 1.5em;
letter-spacing: 5px;
border-radius: 10px;
background: #f47c63;
cursor: pointer;
}
.start:hover {
background-color: #e9694f;
}
.start:active {
background: #f47c63;
}
#result {
display: none;
position: absolute;
top: 200px;
left: 50%;
transform: translateX(-50%);
width: fit-content;
padding: 50px;
font-size: 50px;
font-weight: bolder;
background: #46c6f9;
border: 10px solid #ffffff;
outline: 10px solid #46c6f9;
}
.intro {
width: 40%;
padding: 20px;
margin: 50px auto;
font-size: 30px;
background: #af6daa;
border-radius: 20px;
}
JS
let keyDownEvent = (e) => {
// console.log(e.keyCode);
switch (e.keyCode) {
case 37:
if (json.left()) {
json.randomGrid();
}
break;
case 38:
if (json.up()) {
json.randomGrid();
}
break;
case 39:
if (json.right()) {
json.randomGrid();
}
break;
case 40:
if (json.down()) {
json.randomGrid();
}
break;
default:
return;
}
};
let json = {
// 开始游戏初始化
start: function() {
for (let i = 1; i < 17; i++) {
let grid = document.getElementById(i);
grid.innerHTML = "";
}
json.randomGrid();
json.randomGrid();
json.color();
document.getElementById("result").style.display = "none";
document.onkeydown = (e) => { return keyDownEvent(e) };
rst = -1;
},
// 随机生成min~max中的数
randomNum: function(min, max) {
return min + Math.floor(Math.random() * (max - min + 1));
},
// 随机生成一个格子
randomGrid: function() {
let id = this.randomNum(1, 16);
let grid = document.getElementById(id);
if (grid.innerHTML == "") {
grid.innerHTML = this.randomNum(1, 2) * 2;
this.color();
} else {
this.randomGrid(); //递归调用直到找到无内容的格子
}
},
//根据内容决定背景颜色
color: function() {
let gridColor = {
"": "#ccbeb1",
"2": "#eee4da",
"4": "#ece0c8",
"8": "#f2b17b",
"16": "#f59563",
"32": "#f57c5f",
"64": "#f65d3b",
"128": "#edce71",
"256": "#edcc61",
"512": "#ecc850",
"1024": "#edc53f",
"2048": "#ecc32d",
};
for (let i = 1; i < 17; i++) {
let grid = document.getElementById(i);
grid.style.backgroundColor = gridColor[grid.innerHTML];
if (grid.innerHTML == 2 || grid.innerHTML == 4) {
grid.style.color = "#796f65";
} else {
grid.style.color = "#ffffff";
}
}
},
fontSize: function() {
for (let i = 1; i <= 16; i++) {
let grid = document.getElementById(i);
if (grid.innerHTML == 2048 || grid.innerHTML == 1024) {
grid.style.fontSize = "40px";
} else {
grid.style.fontSize = "50px";
}
}
},
result: function() {
for (let i = 1; i <= 16; i++) {
let grid = document.getElementById(i);
if (grid.innerHTML == 2048) {
rst = 1;
}
}
if (rst != -1) {
if (rst == 0) {
document.getElementById("result").innerHTML = "YOU LOSE!";
} else if (rst == 1) {
document.getElementById("result").innerHTML = "YOU WIN!";
}
document.getElementById("result").style.display = "block";
document.onkeydown = "return false";
}
},
// 向上
up: function() {
let flag = false; //标记格子是否改变
for (let i = 1; i <= 4; i++) { //合并
loopJ: for (let j = i; j <= i + 12; j += 4) {
let gridJ = document.getElementById(j);
if (gridJ.innerHTML) { //找到不为空的格子等着与下一个不为空的配对
for (let k = j + 4; k <= i + 12; k += 4) {
let gridK = document.getElementById(k);
if (gridK.innerHTML) { //找到第二个不为空的格子
if (gridJ.innerHTML == gridK.innerHTML) { //配对成功合并
gridJ.innerHTML *= 2;
gridK.innerHTML = "";
flag = true;
}
continue loopJ; //下一次从下一个格子开始重新配对
}
}
}
}
}
for (let i = 1; i <= 4; i++) { //填空
for (let j = i; j <= i + 12; j += 4) {
let gridJ = document.getElementById(j);
if (!gridJ.innerHTML) { //找第一个空格
for (let k = j + 4; k <= i + 12; k += 4) {
let gridK = document.getElementById(k);
if (gridK.innerHTML) { //再找下一个非空格子填空
gridJ.innerHTML = gridK.innerHTML;
gridK.innerHTML = "";
flag = true;
break; //找下个空格
}
}
}
}
}
this.color();
this.fontSize();
this.result();
return flag;
},
// 向下
down: function() {
let flag = false;
for (let i = 1; i <= 4; i++) {
loopJ: for (let j = i + 12; j > i; j -= 4) {
let gridJ = document.getElementById(j);
if (gridJ.innerHTML) {
for (let k = j - 4; k >= i; k -= 4) {
let gridK = document.getElementById(k);
if (gridK.innerHTML) {
if (gridJ.innerHTML == gridK.innerHTML) {
gridJ.innerHTML *= 2;
gridK.innerHTML = "";
flag = true;
}
continue loopJ;
}
}
}
}
}
for (let i = 1; i <= 4; i++) {
for (let j = i + 12; j > i; j -= 4) {
let gridJ = document.getElementById(j);
if (!gridJ.innerHTML) {
for (let k = j - 4; k >= i; k -= 4) {
let gridK = document.getElementById(k);
if (gridK.innerHTML) {
gridJ.innerHTML = gridK.innerHTML;
gridK.innerHTML = "";
flag = true;
break;
}
}
}
}
}
this.color();
this.fontSize();
this.result();
return flag;
},
// 向左
left: function() {
let flag = false;
for (let i = 1; i <= 13; i += 4) {
loopJ: for (let j = i; j < i + 3; j++) {
let gridJ = document.getElementById(j);
if (gridJ.innerHTML) {
for (let k = j + 1; k <= i + 3; k++) {
let gridK = document.getElementById(k);
if (gridK.innerHTML) {
if (gridJ.innerHTML == gridK.innerHTML) {
gridJ.innerHTML *= 2;
gridK.innerHTML = "";
flag = true;
}
continue loopJ;
}
}
}
}
}
for (let i = 1; i <= 13; i += 4) {
for (let j = i; j < i + 3; j++) {
let gridJ = document.getElementById(j);
if (!gridJ.innerHTML) {
for (let k = j + 1; k <= i + 3; k++) {
let gridK = document.getElementById(k);
if (gridK.innerHTML) {
gridJ.innerHTML = gridK.innerHTML;
gridK.innerHTML = "";
flag = true;
break;
}
}
}
}
}
this.color();
this.fontSize();
this.result();
return flag;
},
// 向右
right: function() {
let flag = false;
for (let i = 1; i <= 13; i += 4) {
loopJ: for (let j = i + 3; j > i; j--) {
let gridJ = document.getElementById(j);
if (gridJ.innerHTML) {
for (let k = j - 1; k >= i; k--) {
let gridK = document.getElementById(k);
if (gridK.innerHTML) {
if (gridJ.innerHTML == gridK.innerHTML) {
gridJ.innerHTML *= 2;
gridK.innerHTML = "";
flag = true;
}
continue loopJ;
}
}
}
}
}
for (let i = 1; i <= 13; i += 4) {
for (let j = i + 3; j > i; j--) {
let gridJ = document.getElementById(j);
if (!gridJ.innerHTML) {
for (let k = j - 1; k >= i; k--) {
let gridK = document.getElementById(k);
if (gridK.innerHTML) {
gridJ.innerHTML = gridK.innerHTML;
gridK.innerHTML = "";
flag = true;
break;
}
}
}
}
}
this.color();
this.fontSize();
this.result();
return flag;
}
}
let rst = -1;
window.onload = json.start();
let startBtn = document.querySelector(".start")
startBtn.addEventListener("click", json.start);
document.onkeydown = (e) => { return keyDownEvent(e) };