Some product links are affiliate links which means
if you something we'll receive a small commission.
Youtube Link
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="./style.css" />
<title>2048</title>
</head>
<body>
<div class="container">
<div class="header">
<h1 class="title">2048</h1>
<div class="score_box">
<span class="score_title">SCORE</span>
<strong id="score" class="score">0</strong>
</div>
</div>
<div id="game-board"></div>
<button id="new-game-btn" class="game_start_button" type="button">New Game</button>
</div>
<script src="./index.js"></script>
</body>
</html>
css
body {
background-color: #f6f2e9;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
margin: 0;
}
.container {
text-align: center;
width: 412px;
}
.header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 10px;
}
.score_box {
background-color: #c8bdae;
border: 1px solid #baab9f;
padding: 10px 15px;
border-radius: 5px;
}
.score_title {
display: block;
color: #f2e3da;
}
.score {
color: #fff;
font-size: 20px;
display: block;
margin-top: 4px;
}
.title {
font-size: 70px;
color: #776e65;
font-weight: 900;
margin: 0;
}
#game-board {
width: 400px;
height: 400px;
border: 6px solid #baab9f;
border-radius: 8px;
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-template-rows: repeat(4, 1fr);
}
.tile {
display: flex;
align-items: center;
justify-content: center;
font-size: 36px;
font-weight: bold;
background-color: #c8bdae;
border: 4px solid #baad9f;
}
.game_start_button {
background-color: #90786a;
color: #fff;
border: 0;
margin-top: 20px;
padding: 10px 20px;
font-size: 18px;
border-radius: 4px;
}
js
const scoreEl = document.getElementById("score");
let board = [
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
];
let score = 0;
function startGame() {
board = [
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
];
addNewTile();
addNewTile();
updateBoard();
}
function addNewTile() {
const emptyTiles = [];
for (let row = 0; row < 4; row++) {
for (let col = 0; col < 4; col++) {
if (board[row][col] === 0) {
emptyTiles.push({ row, col });
}
}
}
if (emptyTiles.length > 0) {
const randomIndex = Math.floor(Math.random() * emptyTiles.length);
const { row, col } = emptyTiles[randomIndex];
const newValue = Math.random() < 0.9 ? 2 : 4;
board[row][col] = newValue;
}
}
function updateBoard() {
const gameBoard = document.getElementById("game-board");
gameBoard.innerHTML = "";
for (let row = 0; row < 4; row++) {
for (let col = 0; col < 4; col++) {
const tileValue = board[row][col];
const tile = document.createElement("div");
tile.className = "tile";
tile.textContent = tileValue !== 0 ? tileValue : "";
tile.style.backgroundColor = getTileColor(tileValue);
tile.style.color = [2, 4, 8].includes(tileValue) ? "#6b6359" : "#fff";
gameBoard.appendChild(tile);
}
}
}
function getTileColor(value) {
if (value === 0) return "#c8bdae";
const colors = ["#e7dfd3", "#E7DBBD", "#EFAC73", "#F48E5F", "#EB7A54", "#F45B38", "#E8C96A", "#ECC95C"];
for (let i in colors) {
if (2 ** i === value) {
return colors[i];
}
}
return "#ecc95c";
}
function moveTiles(direction) {
let tileMoved = false;
console.log(direction);
const rowIndices = direction === "up" ? [0, 1, 2, 3] : [3, 2, 1, 0];
const colIndices = direction === "left" ? [0, 1, 2, 3] : [3, 2, 1, 0];
for (let row of rowIndices) {
for (let col of colIndices) {
const currentValue = board[row][col];
if (currentValue === 0) continue;
let newRow = row;
let newCol = col;
let currentRow = row;
let currentCol = col;
while (true) {
if (direction === "up") {
newRow--;
currentRow = newRow + 1;
} else if (direction === "down") {
newRow++;
currentRow = newRow - 1;
} else if (direction === "left") {
newCol--;
currentCol = newCol + 1;
} else if (direction === "right") {
newCol++;
currentCol = newCol - 1;
}
if (newRow < 0 || newRow >= 4 || newCol < 0 || newCol >= 4) {
newRow -= direction === "up" ? -1 : 1;
newCol -= direction === "left" ? -1 : 1;
break;
}
const newValue = board[newRow][newCol];
if (newValue === 0) {
board[newRow][newCol] = currentValue;
board[currentRow][currentCol] = 0;
tileMoved = true;
} else if (newValue === currentValue) {
board[newRow][newCol] += currentValue;
board[currentRow][currentCol] = 0;
tileMoved = true;
score += currentValue;
scoreEl.innerText = score;
break;
} else {
newRow -= direction === "up" ? -1 : 1;
newCol -= direction === "left" ? -1 : 1;
break;
}
}
}
}
if (tileMoved) {
addNewTile();
updateBoard();
}
}
document.addEventListener("keydown", function (event) {
console.log(event.key);
if (event.key === "ArrowUp") {
moveTiles("up");
} else if (event.key === "ArrowDown") {
moveTiles("down");
} else if (event.key === "ArrowLeft") {
moveTiles("left");
} else if (event.key === "ArrowRight") {
moveTiles("right");
}
});
const newGameBtn = document.getElementById("new-game-btn");
newGameBtn.addEventListener("click", startGame);
startGame();