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
+ } ) ;
0 commit comments