Skip to content

Commit f8a0811

Browse files
committed
Adding Day #57
1 parent 38a6afd commit f8a0811

File tree

6 files changed

+365
-0
lines changed

6 files changed

+365
-0
lines changed

Day #57 - 2048 Game/README.md

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Day #57
2+
3+
### 2048 Game
4+
In this tutorial ([Open in Youtube](https://youtu.be/rWNHIUjfsvw)), I am gonna showing to you how to code a javascript 2048 game with most simple logic in the world! Also we will use css grids for design, flexbox and some animations for it❗️
5+
6+
# Screenshot
7+
Here we have project screenshot :
8+
9+
![screenshot](screenshot.jpg)

Day #57 - 2048 Game/index.html

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
4+
<head>
5+
<meta charset="UTF-8">
6+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
7+
<link rel="stylesheet" href="style.css">
8+
<title>Day #57 - 2048 Game | AsmrProg</title>
9+
</head>
10+
11+
<body>
12+
13+
<div class="score-container">
14+
<div>Score : <span id="current-score">0</span></div>
15+
<div>High Score : <span id="high-score">0</span></div>
16+
</div>
17+
18+
<div class="game-container">
19+
<div class="grid">
20+
<div class="cell" data-row="0" data-col="0"></div>
21+
<div class="cell" data-row="0" data-col="1"></div>
22+
<div class="cell" data-row="0" data-col="2"></div>
23+
<div class="cell" data-row="0" data-col="3"></div>
24+
<div class="cell" data-row="1" data-col="0"></div>
25+
<div class="cell" data-row="1" data-col="1"></div>
26+
<div class="cell" data-row="1" data-col="2"></div>
27+
<div class="cell" data-row="1" data-col="3"></div>
28+
<div class="cell" data-row="2" data-col="0"></div>
29+
<div class="cell" data-row="2" data-col="1"></div>
30+
<div class="cell" data-row="2" data-col="2"></div>
31+
<div class="cell" data-row="2" data-col="3"></div>
32+
<div class="cell" data-row="3" data-col="0"></div>
33+
<div class="cell" data-row="3" data-col="1"></div>
34+
<div class="cell" data-row="3" data-col="2"></div>
35+
<div class="cell" data-row="3" data-col="3"></div>
36+
</div>
37+
</div>
38+
39+
<div id="game-over">
40+
Game Over!
41+
<button id="restart-btn">Restart Game</button>
42+
</div>
43+
44+
<script src="script.js"></script>
45+
</body>
46+
47+
</html>

Day #57 - 2048 Game/screenshot.jpg

36.4 KB
Loading

Day #57 - 2048 Game/script.js

+175
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
document.addEventListener('DOMContentLoaded', () => {
2+
const grid = document.querySelector('.grid');
3+
const size = 4;
4+
let board = [];
5+
let currentScore = 0;
6+
const currentScoreElem = document.getElementById('current-score');
7+
8+
// Get the high score from local storage or set it to 0 if not found
9+
let highScore = localStorage.getItem('2048-highScore') || 0;
10+
const highScoreElem = document.getElementById('high-score');
11+
highScoreElem.textContent = highScore;
12+
13+
const gameOverElem = document.getElementById('game-over');
14+
15+
// Function to update the score
16+
function updateScore(value) {
17+
currentScore += value;
18+
currentScoreElem.textContent = currentScore;
19+
if (currentScore > highScore) {
20+
highScore = currentScore;
21+
highScoreElem.textContent = highScore;
22+
localStorage.setItem('2048-highScore', highScore);
23+
}
24+
}
25+
26+
// Function to restart the game
27+
function restartGame() {
28+
currentScore = 0;
29+
currentScoreElem.textContent = '0';
30+
gameOverElem.style.display = 'none';
31+
initializeGame();
32+
}
33+
34+
// Function to initialize the game
35+
function initializeGame() {
36+
board = [...Array(size)].map(e => Array(size).fill(0));
37+
placeRandom();
38+
placeRandom();
39+
renderBoard();
40+
}
41+
42+
// Function to render the game board on the UI
43+
function renderBoard() {
44+
for (let i = 0; i < size; i++) {
45+
for (let j = 0; j < size; j++) {
46+
const cell = document.querySelector(`[data-row="${i}"][data-col="${j}"]`);
47+
const prevValue = cell.dataset.value;
48+
const currentValue = board[i][j];
49+
if (currentValue !== 0) {
50+
cell.dataset.value = currentValue;
51+
cell.textContent = currentValue;
52+
// Animation handling
53+
if (currentValue !== parseInt(prevValue) && !cell.classList.contains('new-tile')) {
54+
cell.classList.add('merged-tile');
55+
}
56+
} else {
57+
cell.textContent = '';
58+
delete cell.dataset.value;
59+
cell.classList.remove('merged-tile', 'new-tile');
60+
}
61+
}
62+
}
63+
64+
// Cleanup animation classes
65+
setTimeout(() => {
66+
const cells = document.querySelectorAll('.grid-cell');
67+
cells.forEach(cell => {
68+
cell.classList.remove('merged-tile', 'new-tile');
69+
});
70+
}, 300);
71+
}
72+
73+
// Function to place a random tile on the board
74+
function placeRandom() {
75+
const available = [];
76+
for (let i = 0; i < size; i++) {
77+
for (let j = 0; j < size; j++) {
78+
if (board[i][j] === 0) {
79+
available.push({ x: i, y: j });
80+
}
81+
}
82+
}
83+
84+
if (available.length > 0) {
85+
const randomCell = available[Math.floor(Math.random() * available.length)];
86+
board[randomCell.x][randomCell.y] = Math.random() < 0.9 ? 2 : 4;
87+
const cell = document.querySelector(`[data-row="${randomCell.x}"][data-col="${randomCell.y}"]`);
88+
cell.classList.add('new-tile'); // Animation for new tiles
89+
}
90+
}
91+
92+
// Function to move the tiles based on arrow key input
93+
function move(direction) {
94+
let hasChanged = false;
95+
if (direction === 'ArrowUp' || direction === 'ArrowDown') {
96+
for (let j = 0; j < size; j++) {
97+
const column = [...Array(size)].map((_, i) => board[i][j]);
98+
const newColumn = transform(column, direction === 'ArrowUp');
99+
for (let i = 0; i < size; i++) {
100+
if (board[i][j] !== newColumn[i]) {
101+
hasChanged = true;
102+
board[i][j] = newColumn[i];
103+
}
104+
}
105+
}
106+
} else if (direction === 'ArrowLeft' || direction === 'ArrowRight') {
107+
for (let i = 0; i < size; i++) {
108+
const row = board[i];
109+
const newRow = transform(row, direction === 'ArrowLeft');
110+
if (row.join(',') !== newRow.join(',')) {
111+
hasChanged = true;
112+
board[i] = newRow;
113+
}
114+
}
115+
}
116+
if (hasChanged) {
117+
placeRandom();
118+
renderBoard();
119+
checkGameOver();
120+
}
121+
}
122+
123+
// Function to transform a line (row or column) based on move direction
124+
function transform(line, moveTowardsStart) {
125+
let newLine = line.filter(cell => cell !== 0);
126+
if (!moveTowardsStart) {
127+
newLine.reverse();
128+
}
129+
for (let i = 0; i < newLine.length - 1; i++) {
130+
if (newLine[i] === newLine[i + 1]) {
131+
newLine[i] *= 2;
132+
updateScore(newLine[i]); // Update score when tiles merged
133+
newLine.splice(i + 1, 1);
134+
}
135+
}
136+
while (newLine.length < size) {
137+
newLine.push(0);
138+
}
139+
if (!moveTowardsStart) {
140+
newLine.reverse();
141+
}
142+
return newLine;
143+
}
144+
145+
// Function to check if the game is over
146+
function checkGameOver() {
147+
for (let i = 0; i < size; i++) {
148+
for (let j = 0; j < size; j++) {
149+
if (board[i][j] === 0) {
150+
return; // There is an empty cell, so game not over
151+
}
152+
if (j < size - 1 && board[i][j] === board[i][j + 1]) {
153+
return; // There are horizontally adjacent equal cells, so a move is possible
154+
}
155+
if (i < size - 1 && board[i][j] === board[i + 1][j]) {
156+
return; // There are vertically adjacent equal cells, so a move is possible
157+
}
158+
}
159+
}
160+
161+
// If we reach here, no moves are possible
162+
gameOverElem.style.display = 'flex';
163+
}
164+
165+
// Event listeners
166+
document.addEventListener('keydown', event => {
167+
if (['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'].includes(event.key)) {
168+
move(event.key);
169+
}
170+
});
171+
document.getElementById('restart-btn').addEventListener('click', restartGame);
172+
173+
initializeGame();
174+
175+
});

Day #57 - 2048 Game/style.css

+133
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap');
2+
3+
body{
4+
font-family: 'Poppins', sans-serif;
5+
display: flex;
6+
flex-direction: column;
7+
align-items: center;
8+
justify-content: center;
9+
overflow: hidden;
10+
height: 100vh;
11+
background-color: #fafafa;
12+
}
13+
14+
.game-container{
15+
width: 320px;
16+
height: 320px;
17+
border: 1px solid #ccc;
18+
overflow: hidden;
19+
}
20+
21+
.grid{
22+
display: grid;
23+
grid-template-columns: repeat(4, 1fr);
24+
gap: 5px;
25+
}
26+
27+
.cell{
28+
width: 77px;
29+
height: 77px;
30+
background-color: #f4f4f4;
31+
display: flex;
32+
align-items: center;
33+
justify-content: center;
34+
font-size: 1.5em;
35+
color: #000;
36+
}
37+
38+
.score-container{
39+
width: 320px;
40+
display: flex;
41+
justify-content: space-between;
42+
margin-bottom: 15px;
43+
}
44+
45+
.cell[data-value="2"]{
46+
background-color: #ffc0cb;
47+
}
48+
49+
.cell[data-value="4"]{
50+
background-color: #add8e6;
51+
}
52+
53+
.cell[data-value="8"]{
54+
background-color: #98fb98;
55+
}
56+
57+
.cell[data-value="16"]{
58+
background-color: #ffd700;
59+
}
60+
61+
.cell[data-value="32"]{
62+
background-color: #ffa07a;
63+
}
64+
65+
.cell[data-value="64"]{
66+
background-color: #87ceeb;
67+
}
68+
69+
.cell[data-value="128"]{
70+
background-color: #ffff00;
71+
}
72+
73+
.cell[data-value="256"]{
74+
background-color: #40e0d0;
75+
}
76+
77+
.cell[data-value="512"]{
78+
background-color: #ff69b4;
79+
}
80+
81+
.cell[data-value="1024"]{
82+
background-color: #7b68ee;
83+
}
84+
85+
.cell[data-value="2048"]{
86+
background-color: #ff6347;
87+
}
88+
89+
.cell[data-value="4096"]{
90+
background-color: #a9a9a9;
91+
}
92+
93+
#restart-btn{
94+
margin-top: 15px;
95+
padding: 10px 15px;
96+
background-color: #f4f4f4;
97+
border: none;
98+
cursor: pointer;
99+
transition: all 0.3s ease;
100+
}
101+
102+
#game-over{
103+
position: absolute;
104+
top: 50%;
105+
left: 50%;
106+
padding: 20px;
107+
transform: translate(-50%, -50%);
108+
background-color: rgba(0, 0, 0, 0.8);
109+
color: #fff;
110+
display: none;
111+
flex-direction: column;
112+
align-items: center;
113+
justify-content: center;
114+
}
115+
116+
.grid-cell[data-value]{
117+
transition: transform 0.2s, background-color 0.2s;
118+
}
119+
120+
.new-tile{
121+
animation: appear 0.3s;
122+
}
123+
124+
@keyframes appear {
125+
from{
126+
opacity: 0;
127+
transform: scale(0.5);
128+
}
129+
to{
130+
opacity: 1;
131+
transform: scale(1);
132+
}
133+
}

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ Here we have list of projects:
6666
54. Glassmorphism Generator
6767
55. Alarm App
6868
56. Image Color Picker
69+
57. 2048 Game
6970

7071
## Where is rest 45 Projects
7172

0 commit comments

Comments
 (0)