学习过程,来源B站大佬的代码,b站视频2048游戏
(全是对大佬代码的注释。自己加了一个重开游戏的热键Q,就一行代码)
文件如下:
2048.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="style.css">
<title>2048</title>
</head>
<body>
<h1>2048</h1>
<p>按“Q”重开</p>
<div class="score-container">
<div>分数 : <span id="current-score">0</span></div>
<div>最高分 : <span id="high-score">0</span></div>
</div>
<div class="game-container">
<div class="grid">
<!-- 每行每列每个格子 -->
<div class="cell" data-row="0" data-col="0"></div>
<div class="cell" data-row="0" data-col="1"></div>
<div class="cell" data-row="0" data-col="2"></div>
<div class="cell" data-row="0" data-col="3"></div>
<div class="cell" data-row="1" data-col="0"></div>
<div class="cell" data-row="1" data-col="1"></div>
<div class="cell" data-row="1" data-col="2"></div>
<div class="cell" data-row="1" data-col="3"></div>
<div class="cell" data-row="2" data-col="0"></div>
<div class="cell" data-row="2" data-col="1"></div>
<div class="cell" data-row="2" data-col="2"></div>
<div class="cell" data-row="2" data-col="3"></div>
<div class="cell" data-row="3" data-col="0"></div>
<div class="cell" data-row="3" data-col="1"></div>
<div class="cell" data-row="3" data-col="2"></div>
<div class="cell" data-row="3" data-col="3"></div>
</div>
</div>
<div id="game-over">
Game Over!
<button id="restart-btn">Restart Game</button>
</div>
<script src="script.js"></script>
</body>
</html>
style.css
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap');
body {
font-family: 'Poppins', sans-serif;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
overflow: hidden;
height: 100vh;
background-color: #dabb0c73;
}
h1 {
margin-bottom: 0;
}
p {
margin-top: 0;
font-size: 50;
font-family:"Simsun";
}
.game-container {
width: 320px;
height: 320px;
border: 1px solid #ccc;
overflow: hidden;
}
.grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 5px;
}
.cell {
width: 77px;
height: 77px;
background-color: #f4f4f4;
display: flex;
align-items: center;
justify-content: center;
font-size: 1.5em;
color: #000;
}
.score-container {
width: 320px;
display: flex;
justify-content: space-between;
margin-bottom: 15px;
}
.cell[data-value="2"] {
background-color: #ffc0cb;
}
.cell[data-value="4"] {
background-color: #add8e6;
}
.cell[data-value="8"] {
background-color: #98fb98;
}
.cell[data-value="16"] {
background-color: #ffd700;
}
.cell[data-value="32"] {
background-color: #ffa07a;
}
.cell[data-value="64"] {
background-color: #87ceeb;
}
.cell[data-value="128"] {
background-color: #ffff00;
}
.cell[data-value="256"] {
background-color: #40e0d0;
}
.cell[data-value="512"] {
background-color: #ff69b4;
}
.cell[data-value="1024"] {
background-color: #7b68ee;
}
.cell[data-value="2048"] {
background-color: #ff6347;
}
.cell[data-value="4096"] {
background-color: #a9a9a9;
}
#restart-btn {
margin-top: 15px;
padding: 10px 15px;
background-color: #f4f4f4;
border: none;
cursor: pointer;
transition: all 0.3s ease;
}
#game-over {
position: absolute;
top: 50%;
left: 50%;
padding: 20px;
transform: translate(-50%, -50%);
background-color: rgba(0, 0, 0, 0.8);
color: #fff;
display: none;
flex-direction: column;
align-items: center;
justify-content: center;
}
.grid-cell[data-value] {
transition: transform 0.2s, background-color 0.2s;
}
.new-tile {
animation: appear 0.3s;
}
@keyframes appear {
from {
opacity: 0;
transform: scale(0.5);
}
to {
opacity: 1;
transform: scale(1);
}
}
script.js
document.addEventListener('DOMContentLoaded', () => {
const grid = document.querySelector('.grid');
const size = 4;
let board = [];//存储数组
let currentScore = 0;//存储分数
const currentScoreElem = document.getElementById('current-score');//读取分数
//使用localStorage存储最高分,如果没有那么就是0分
let highScore = localStorage.getItem('2048-highScore') || 0;
const highScoreElem = document.getElementById('high-score');
highScoreElem.textContent = highScore;//输入最高分
const gameOverElem = document.getElementById('game-over');
// 更新最高分函数和当前分数
function updateScore(value) {
currentScore += value;
currentScoreElem.textContent = currentScore;//当前分数
if (currentScore > highScore) {//如果当前分数比最高分高,那么更新
highScore = currentScore;
highScoreElem.textContent = highScore;
localStorage.setItem('2048-highScore', highScore);//保存
}
}
// 重开游戏
function restartGame() {
currentScore = 0;
currentScoreElem.textContent = '0';
gameOverElem.style.display = 'none';
initializeGame();
}
// 初始化游戏
function initializeGame() {
board = [...Array(size)].map(e => Array(size).fill(0));
placeRandom();
placeRandom();
renderBoard();//绘制图形
}
// 画图,每个格子遍历一遍,让其拥有对应数字的属性
function renderBoard() {
for (let i = 0; i < size; i++) {
for (let j = 0; j < size; j++) {
const cell = document.querySelector(`[data-row="${i}"][data-col="${j}"]`);
const prevValue = cell.dataset.value;
const currentValue = board[i][j];
if (currentValue !== 0) {
cell.dataset.value = currentValue;
cell.textContent = currentValue;
// Animation handling
if (currentValue !== parseInt(prevValue) && !cell.classList.contains('new-tile')) {
cell.classList.add('merged-tile');
}
} else {
cell.textContent = '';
delete cell.dataset.value;
cell.classList.remove('merged-tile', 'new-tile');
}
}
}
// 设置UI动画
setTimeout(() => {
const cells = document.querySelectorAll('.grid-cell');
cells.forEach(cell => {
cell.classList.remove('merged-tile', 'new-tile');
});
}, 300);
}
// 随机位置
function placeRandom() {
const available = [];
for (let i = 0; i < size; i++) {
for (let j = 0; j < size; j++) {
if (board[i][j] === 0) {
available.push({ x: i, y: j });
}
}
}
if (available.length > 0) {//如果格子不满
const randomCell = available[Math.floor(Math.random() * available.length)];
board[randomCell.x][randomCell.y] = Math.random() < 0.5 ? 2 : 4;//生成2或4的概率,
const cell = document.querySelector(`[data-row="${randomCell.x}"][data-col="${randomCell.y}"]`);
cell.classList.add('new-tile'); // 格子生成的动画
}
}
// 获取键盘值,控制上下左右
function move(direction) {
let hasChanged = false;
if (direction === 'ArrowUp' || direction === 'ArrowDown'||direction === 'W' || direction === 'S'||direction === 'w' || direction === 's') {
for (let j = 0; j < size; j++) {
const column = [...Array(size)].map((_, i) => board[i][j]);
const newColumn = transform(column, direction === 'ArrowUp'||direction === 'w'||direction === "W");
for (let i = 0; i < size; i++) {
if (board[i][j] !== newColumn[i]) {
hasChanged = true;
board[i][j] = newColumn[i];
}
}
}
} else if (direction === 'ArrowLeft' || direction === 'ArrowRight'||direction === 'A' || direction === 'D'||direction === 'a' || direction === 'd') {
for (let i = 0; i < size; i++) {
const row = board[i];
const newRow = transform(row, direction === 'ArrowLeft'||direction === 'A'||direction === "a");
if (row.join(',') !== newRow.join(',')) {
hasChanged = true;
board[i] = newRow;
}
}
}
else if(direction==="Q"||direction==="q"){
restartGame() ;
}
if (hasChanged) {
placeRandom();
renderBoard();
checkGameOver();
}
}
// Function to transform a line (row or column) based on move direction
function transform(line, moveTowardsStart) {
let newLine = line.filter(cell => cell !== 0);
if (!moveTowardsStart) {
newLine.reverse();
}
for (let i = 0; i < newLine.length - 1; i++) {
if (newLine[i] === newLine[i + 1]) {
newLine[i] *= 2;
updateScore(newLine[i]); // Update score when tiles merged
newLine.splice(i + 1, 1);
}
}
while (newLine.length < size) {
newLine.push(0);
}
if (!moveTowardsStart) {
newLine.reverse();
}
return newLine;
}
// 检查游戏是否结束
function checkGameOver() {
for (let i = 0; i < size; i++) {
for (let j = 0; j < size; j++) {
if (board[i][j] === 0) {
return; // There is an empty cell, so game not over
}
if (j < size - 1 && board[i][j] === board[i][j + 1]) {
return; // There are horizontally adjacent equal cells, so a move is possible
}
if (i < size - 1 && board[i][j] === board[i + 1][j]) {
return; // There are vertically adjacent equal cells, so a move is possible
}
}
}
// 数组已满,不能更改
gameOverElem.style.display = 'flex';
}
// 时间接听,只能接受上下左右和Q
document.addEventListener('keydown', event => {
if (['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight',"Q","q","w","W","S","s","A","a","d","D"].includes(event.key)) {
move(event.key);
}
});
document.getElementById('restart-btn').addEventListener('click', restartGame);
initializeGame();
});
希望可以帮到各位深陷苦恼的朋友们。