gg9909 commited on
Commit
dbae5c2
·
verified ·
1 Parent(s): 19d0fba

Add 2 files

Browse files
Files changed (2) hide show
  1. README.md +6 -4
  2. index.html +1099 -19
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: Nffnrnfn
3
- emoji:
4
  colorFrom: blue
5
- colorTo: green
6
  sdk: static
7
  pinned: false
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
+ title: nffnrnfn
3
+ emoji: 🐳
4
  colorFrom: blue
5
+ colorTo: blue
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite
10
  ---
11
 
12
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
index.html CHANGED
@@ -1,19 +1,1099 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Neon 2048 - Futuristic Edition</title>
7
+ <style>
8
+ @import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700&display=swap');
9
+
10
+ :root {
11
+ --primary-color: #00f7ff;
12
+ --secondary-color: #ff00f7;
13
+ --bg-color: #0a0a20;
14
+ --grid-bg: rgba(15, 15, 40, 0.7);
15
+ --text-color: #e0e0ff;
16
+ --tile-bg: rgba(30, 30, 60, 0.5);
17
+ --glow: 0 0 10px var(--primary-color), 0 0 20px var(--primary-color);
18
+ --glow-secondary: 0 0 10px var(--secondary-color), 0 0 20px var(--secondary-color);
19
+ }
20
+
21
+ * {
22
+ margin: 0;
23
+ padding: 0;
24
+ box-sizing: border-box;
25
+ }
26
+
27
+ body {
28
+ font-family: 'Orbitron', sans-serif;
29
+ background-color: var(--bg-color);
30
+ color: var(--text-color);
31
+ min-height: 100vh;
32
+ display: flex;
33
+ flex-direction: column;
34
+ align-items: center;
35
+ justify-content: center;
36
+ overflow: hidden;
37
+ position: relative;
38
+ }
39
+
40
+ body::before {
41
+ content: '';
42
+ position: absolute;
43
+ top: 0;
44
+ left: 0;
45
+ width: 100%;
46
+ height: 100%;
47
+ background:
48
+ radial-gradient(circle at 20% 30%, var(--primary-color), transparent 30%),
49
+ radial-gradient(circle at 80% 70%, var(--secondary-color), transparent 30%);
50
+ opacity: 0.1;
51
+ z-index: -1;
52
+ }
53
+
54
+ .header {
55
+ text-align: center;
56
+ margin-bottom: 2rem;
57
+ position: relative;
58
+ }
59
+
60
+ h1 {
61
+ font-size: 3rem;
62
+ margin-bottom: 1rem;
63
+ text-transform: uppercase;
64
+ letter-spacing: 3px;
65
+ color: var(--primary-color);
66
+ text-shadow: var(--glow);
67
+ position: relative;
68
+ }
69
+
70
+ h1::after {
71
+ content: '';
72
+ position: absolute;
73
+ bottom: -10px;
74
+ left: 50%;
75
+ transform: translateX(-50%);
76
+ width: 100px;
77
+ height: 3px;
78
+ background: linear-gradient(90deg, transparent, var(--primary-color), transparent);
79
+ box-shadow: var(--glow);
80
+ }
81
+
82
+ .scores {
83
+ display: flex;
84
+ justify-content: center;
85
+ gap: 2rem;
86
+ margin-bottom: 1rem;
87
+ }
88
+
89
+ .score-box {
90
+ background: var(--tile-bg);
91
+ border: 1px solid var(--primary-color);
92
+ border-radius: 5px;
93
+ padding: 0.5rem 1rem;
94
+ min-width: 100px;
95
+ box-shadow: 0 0 5px var(--primary-color);
96
+ position: relative;
97
+ overflow: hidden;
98
+ }
99
+
100
+ .score-box::before {
101
+ content: '';
102
+ position: absolute;
103
+ top: 0;
104
+ left: 0;
105
+ width: 100%;
106
+ height: 100%;
107
+ background: linear-gradient(45deg, transparent, rgba(0, 247, 255, 0.1), transparent);
108
+ z-index: -1;
109
+ }
110
+
111
+ .score-title {
112
+ font-size: 0.8rem;
113
+ color: var(--secondary-color);
114
+ text-transform: uppercase;
115
+ letter-spacing: 1px;
116
+ }
117
+
118
+ .score-value {
119
+ font-size: 1.5rem;
120
+ font-weight: bold;
121
+ color: var(--primary-color);
122
+ }
123
+
124
+ .game-container {
125
+ position: relative;
126
+ width: 100%;
127
+ max-width: 500px;
128
+ padding: 20px;
129
+ }
130
+
131
+ .grid-container {
132
+ background: var(--grid-bg);
133
+ border-radius: 10px;
134
+ padding: 15px;
135
+ position: relative;
136
+ overflow: hidden;
137
+ box-shadow: 0 0 20px rgba(0, 247, 255, 0.2);
138
+ }
139
+
140
+ .grid-container::before {
141
+ content: '';
142
+ position: absolute;
143
+ top: 0;
144
+ left: 0;
145
+ width: 100%;
146
+ height: 100%;
147
+ background:
148
+ linear-gradient(45deg, transparent 48%, var(--primary-color) 49%, var(--primary-color) 51%, transparent 52%),
149
+ linear-gradient(-45deg, transparent 48%, var(--primary-color) 49%, var(--primary-color) 51%, transparent 52%);
150
+ background-size: 20px 20px;
151
+ opacity: 0.1;
152
+ z-index: -1;
153
+ }
154
+
155
+ .grid {
156
+ display: grid;
157
+ grid-template-columns: repeat(4, 1fr);
158
+ grid-template-rows: repeat(4, 1fr);
159
+ gap: 15px;
160
+ width: 100%;
161
+ aspect-ratio: 1/1;
162
+ position: relative;
163
+ }
164
+
165
+ .grid-cell {
166
+ background: var(--tile-bg);
167
+ border-radius: 5px;
168
+ display: flex;
169
+ align-items: center;
170
+ justify-content: center;
171
+ position: relative;
172
+ overflow: hidden;
173
+ border: 1px solid rgba(0, 247, 255, 0.2);
174
+ }
175
+
176
+ .grid-cell::before {
177
+ content: '';
178
+ position: absolute;
179
+ top: 0;
180
+ left: 0;
181
+ width: 100%;
182
+ height: 100%;
183
+ background: linear-gradient(135deg, transparent, rgba(0, 247, 255, 0.05), transparent);
184
+ }
185
+
186
+ .tile {
187
+ position: absolute;
188
+ width: calc(25% - 15px);
189
+ height: calc(25% - 15px);
190
+ border-radius: 5px;
191
+ display: flex;
192
+ align-items: center;
193
+ justify-content: center;
194
+ font-size: 1.8rem;
195
+ font-weight: bold;
196
+ transition: all 0.15s ease-out;
197
+ z-index: 10;
198
+ background: var(--tile-bg);
199
+ border: 1px solid;
200
+ animation: appear 0.2s ease-out;
201
+ }
202
+
203
+ @keyframes appear {
204
+ 0% {
205
+ opacity: 0;
206
+ transform: scale(0.5);
207
+ }
208
+ 100% {
209
+ opacity: 1;
210
+ transform: scale(1);
211
+ }
212
+ }
213
+
214
+ .tile-2 {
215
+ color: #e0e0ff;
216
+ border-color: rgba(224, 224, 255, 0.3);
217
+ box-shadow: 0 0 5px rgba(224, 224, 255, 0.5);
218
+ }
219
+
220
+ .tile-4 {
221
+ color: #a0a0ff;
222
+ border-color: rgba(160, 160, 255, 0.4);
223
+ box-shadow: 0 0 8px rgba(160, 160, 255, 0.6);
224
+ }
225
+
226
+ .tile-8 {
227
+ color: #8080ff;
228
+ border-color: rgba(128, 128, 255, 0.5);
229
+ box-shadow: 0 0 10px rgba(128, 128, 255, 0.7);
230
+ background: rgba(30, 30, 80, 0.6);
231
+ }
232
+
233
+ .tile-16 {
234
+ color: #6060ff;
235
+ border-color: rgba(96, 96, 255, 0.6);
236
+ box-shadow: 0 0 12px rgba(96, 96, 255, 0.8);
237
+ background: rgba(30, 30, 100, 0.6);
238
+ }
239
+
240
+ .tile-32 {
241
+ color: #4040ff;
242
+ border-color: rgba(64, 64, 255, 0.7);
243
+ box-shadow: 0 0 14px rgba(64, 64, 255, 0.9);
244
+ background: rgba(30, 30, 120, 0.6);
245
+ }
246
+
247
+ .tile-64 {
248
+ color: #2020ff;
249
+ border-color: rgba(32, 32, 255, 0.8);
250
+ box-shadow: 0 0 16px rgba(32, 32, 255, 1);
251
+ background: rgba(30, 30, 140, 0.6);
252
+ }
253
+
254
+ .tile-128 {
255
+ color: var(--primary-color);
256
+ border-color: rgba(0, 247, 255, 0.7);
257
+ box-shadow: var(--glow);
258
+ background: rgba(30, 60, 150, 0.6);
259
+ font-size: 1.6rem;
260
+ }
261
+
262
+ .tile-256 {
263
+ color: var(--primary-color);
264
+ border-color: rgba(0, 247, 255, 0.8);
265
+ box-shadow: var(--glow);
266
+ background: rgba(30, 80, 160, 0.6);
267
+ font-size: 1.6rem;
268
+ }
269
+
270
+ .tile-512 {
271
+ color: var(--primary-color);
272
+ border-color: rgba(0, 247, 255, 0.9);
273
+ box-shadow: var(--glow);
274
+ background: rgba(30, 100, 170, 0.6);
275
+ font-size: 1.6rem;
276
+ }
277
+
278
+ .tile-1024 {
279
+ color: var(--primary-color);
280
+ border-color: rgba(0, 247, 255, 1);
281
+ box-shadow: var(--glow);
282
+ background: rgba(30, 120, 180, 0.6);
283
+ font-size: 1.4rem;
284
+ }
285
+
286
+ .tile-2048 {
287
+ color: var(--primary-color);
288
+ border-color: rgba(0, 247, 255, 1);
289
+ box-shadow: var(--glow), var(--glow-secondary);
290
+ background: rgba(30, 150, 200, 0.6);
291
+ font-size: 1.4rem;
292
+ animation: pulse 1.5s infinite;
293
+ }
294
+
295
+ @keyframes pulse {
296
+ 0% {
297
+ box-shadow: var(--glow), var(--glow-secondary);
298
+ }
299
+ 50% {
300
+ box-shadow: 0 0 20px var(--primary-color), 0 0 40px var(--primary-color), 0 0 20px var(--secondary-color), 0 0 40px var(--secondary-color);
301
+ }
302
+ 100% {
303
+ box-shadow: var(--glow), var(--glow-secondary);
304
+ }
305
+ }
306
+
307
+ .tile-super {
308
+ color: var(--secondary-color);
309
+ border-color: rgba(255, 0, 247, 0.7);
310
+ box-shadow: var(--glow-secondary);
311
+ background: rgba(150, 30, 150, 0.6);
312
+ font-size: 1.2rem;
313
+ }
314
+
315
+ .merge-effect {
316
+ position: absolute;
317
+ width: calc(25% - 15px);
318
+ height: calc(25% - 15px);
319
+ border-radius: 5px;
320
+ background: radial-gradient(circle, var(--primary-color), transparent 70%);
321
+ opacity: 0;
322
+ z-index: 5;
323
+ animation: mergePulse 0.4s ease-out;
324
+ }
325
+
326
+ @keyframes mergePulse {
327
+ 0% {
328
+ transform: scale(0.5);
329
+ opacity: 0.8;
330
+ }
331
+ 100% {
332
+ transform: scale(1.5);
333
+ opacity: 0;
334
+ }
335
+ }
336
+
337
+ .game-message {
338
+ position: absolute;
339
+ top: 0;
340
+ left: 0;
341
+ width: 100%;
342
+ height: 100%;
343
+ display: none;
344
+ flex-direction: column;
345
+ align-items: center;
346
+ justify-content: center;
347
+ background: rgba(10, 10, 32, 0.9);
348
+ border-radius: 10px;
349
+ z-index: 100;
350
+ animation: fadeIn 0.3s ease-out;
351
+ }
352
+
353
+ @keyframes fadeIn {
354
+ 0% {
355
+ opacity: 0;
356
+ }
357
+ 100% {
358
+ opacity: 1;
359
+ }
360
+ }
361
+
362
+ .game-message.game-won {
363
+ background: rgba(10, 10, 32, 0.95);
364
+ }
365
+
366
+ .game-message.game-over {
367
+ background: rgba(32, 10, 10, 0.95);
368
+ }
369
+
370
+ .game-message p {
371
+ font-size: 3rem;
372
+ font-weight: bold;
373
+ margin-bottom: 2rem;
374
+ text-align: center;
375
+ text-transform: uppercase;
376
+ }
377
+
378
+ .game-won p {
379
+ color: var(--primary-color);
380
+ text-shadow: var(--glow);
381
+ }
382
+
383
+ .game-over p {
384
+ color: #ff4040;
385
+ text-shadow: 0 0 10px #ff4040, 0 0 20px #ff4040;
386
+ }
387
+
388
+ .btn {
389
+ background: var(--tile-bg);
390
+ border: 1px solid var(--primary-color);
391
+ color: var(--primary-color);
392
+ padding: 0.8rem 1.5rem;
393
+ font-family: 'Orbitron', sans-serif;
394
+ font-size: 1rem;
395
+ border-radius: 5px;
396
+ cursor: pointer;
397
+ transition: all 0.2s;
398
+ text-transform: uppercase;
399
+ letter-spacing: 1px;
400
+ box-shadow: 0 0 5px var(--primary-color);
401
+ }
402
+
403
+ .btn:hover {
404
+ background: rgba(0, 247, 255, 0.1);
405
+ box-shadow: 0 0 10px var(--primary-color);
406
+ }
407
+
408
+ .btn:active {
409
+ transform: scale(0.98);
410
+ }
411
+
412
+ .instructions {
413
+ margin-top: 2rem;
414
+ text-align: center;
415
+ max-width: 500px;
416
+ padding: 0 20px;
417
+ color: rgba(224, 224, 255, 0.7);
418
+ font-size: 0.9rem;
419
+ line-height: 1.5;
420
+ }
421
+
422
+ .instructions strong {
423
+ color: var(--primary-color);
424
+ }
425
+
426
+ .particles {
427
+ position: absolute;
428
+ top: 0;
429
+ left: 0;
430
+ width: 100%;
431
+ height: 100%;
432
+ pointer-events: none;
433
+ z-index: -1;
434
+ }
435
+
436
+ .particle {
437
+ position: absolute;
438
+ background: var(--primary-color);
439
+ border-radius: 50%;
440
+ pointer-events: none;
441
+ opacity: 0.5;
442
+ }
443
+
444
+ @media (max-width: 600px) {
445
+ h1 {
446
+ font-size: 2rem;
447
+ }
448
+
449
+ .tile {
450
+ font-size: 1.4rem;
451
+ }
452
+
453
+ .tile-128, .tile-256, .tile-512 {
454
+ font-size: 1.2rem;
455
+ }
456
+
457
+ .tile-1024, .tile-2048 {
458
+ font-size: 1rem;
459
+ }
460
+
461
+ .grid {
462
+ gap: 10px;
463
+ }
464
+ }
465
+ </style>
466
+ </head>
467
+ <body>
468
+ <div class="particles" id="particles"></div>
469
+
470
+ <div class="header">
471
+ <h1>Neon 2048</h1>
472
+ <div class="scores">
473
+ <div class="score-box">
474
+ <div class="score-title">Score</div>
475
+ <div class="score-value" id="score">0</div>
476
+ </div>
477
+ <div class="score-box">
478
+ <div class="score-title">Best</div>
479
+ <div class="score-value" id="best-score">0</div>
480
+ </div>
481
+ </div>
482
+ </div>
483
+
484
+ <div class="game-container">
485
+ <div class="grid-container">
486
+ <div class="grid" id="grid">
487
+ <!-- Grid cells will be generated by JavaScript -->
488
+ </div>
489
+
490
+ <div class="game-message" id="game-message">
491
+ <p id="message-text">You Win!</p>
492
+ <button class="btn" id="restart-btn">Play Again</button>
493
+ </div>
494
+ </div>
495
+ </div>
496
+
497
+ <div class="instructions">
498
+ <p><strong>HOW TO PLAY:</strong> Use your arrow keys or swipe to move the tiles. When two tiles with the same number touch, they merge into one!</p>
499
+ </div>
500
+
501
+ <script>
502
+ document.addEventListener('DOMContentLoaded', () => {
503
+ const grid = document.getElementById('grid');
504
+ const scoreDisplay = document.getElementById('score');
505
+ const bestScoreDisplay = document.getElementById('best-score');
506
+ const gameMessage = document.getElementById('game-message');
507
+ const messageText = document.getElementById('message-text');
508
+ const restartBtn = document.getElementById('restart-btn');
509
+ const particlesContainer = document.getElementById('particles');
510
+
511
+ let board = [];
512
+ let score = 0;
513
+ let bestScore = localStorage.getItem('bestScore') || 0;
514
+ let isGameOver = false;
515
+ let isGameWon = false;
516
+ let touchStartX = 0;
517
+ let touchStartY = 0;
518
+ let touchEndX = 0;
519
+ let touchEndY = 0;
520
+
521
+ bestScoreDisplay.textContent = bestScore;
522
+
523
+ // Initialize the game
524
+ function initGame() {
525
+ // Create grid cells
526
+ grid.innerHTML = '';
527
+ for (let i = 0; i < 16; i++) {
528
+ const cell = document.createElement('div');
529
+ cell.classList.add('grid-cell');
530
+ grid.appendChild(cell);
531
+ }
532
+
533
+ // Initialize board
534
+ board = [
535
+ [0, 0, 0, 0],
536
+ [0, 0, 0, 0],
537
+ [0, 0, 0, 0],
538
+ [0, 0, 0, 0]
539
+ ];
540
+
541
+ score = 0;
542
+ scoreDisplay.textContent = score;
543
+ isGameOver = false;
544
+ isGameWon = false;
545
+
546
+ gameMessage.style.display = 'none';
547
+ gameMessage.classList.remove('game-won', 'game-over');
548
+
549
+ // Add two initial tiles
550
+ addRandomTile();
551
+ addRandomTile();
552
+
553
+ updateView();
554
+ }
555
+
556
+ // Add a random tile (2 or 4) to an empty cell
557
+ function addRandomTile() {
558
+ const emptyCells = [];
559
+
560
+ for (let r = 0; r < 4; r++) {
561
+ for (let c = 0; c < 4; c++) {
562
+ if (board[r][c] === 0) {
563
+ emptyCells.push({ r, c });
564
+ }
565
+ }
566
+ }
567
+
568
+ if (emptyCells.length > 0) {
569
+ const randomCell = emptyCells[Math.floor(Math.random() * emptyCells.length)];
570
+ board[randomCell.r][randomCell.c] = Math.random() < 0.9 ? 2 : 4;
571
+
572
+ // Animation for new tile
573
+ const tileElement = createTileElement(randomCell.r, randomCell.c, board[randomCell.r][randomCell.c]);
574
+ tileElement.style.animation = 'appear 0.2s ease-out';
575
+ grid.appendChild(tileElement);
576
+ }
577
+ }
578
+
579
+ // Create a tile element
580
+ function createTileElement(row, col, value) {
581
+ const tile = document.createElement('div');
582
+ tile.classList.add('tile', `tile-${value}`);
583
+ if (value > 2048) tile.classList.add('tile-super');
584
+ tile.textContent = value;
585
+ tile.id = `tile-${row}-${col}`;
586
+ updateTilePosition(tile, row, col);
587
+ return tile;
588
+ }
589
+
590
+ // Update tile position
591
+ function updateTilePosition(tile, row, col) {
592
+ const cellSize = grid.offsetWidth / 4;
593
+ tile.style.left = `${col * cellSize + 15}px`;
594
+ tile.style.top = `${row * cellSize + 15}px`;
595
+ }
596
+
597
+ // Update the view based on the board state
598
+ function updateView() {
599
+ // Remove all existing tiles
600
+ document.querySelectorAll('.tile').forEach(tile => tile.remove());
601
+
602
+ // Create tiles for non-zero cells
603
+ for (let r = 0; r < 4; r++) {
604
+ for (let c = 0; c < 4; c++) {
605
+ if (board[r][c] !== 0) {
606
+ const tile = createTileElement(r, c, board[r][c]);
607
+ grid.appendChild(tile);
608
+ }
609
+ }
610
+ }
611
+ }
612
+
613
+ // Move tiles left
614
+ function moveLeft() {
615
+ let moved = false;
616
+
617
+ for (let r = 0; r < 4; r++) {
618
+ // Remove zeros and compact to the left
619
+ let row = board[r].filter(val => val !== 0);
620
+ const zeros = Array(4 - row.length).fill(0);
621
+ row = row.concat(zeros);
622
+
623
+ // Check if the row changed
624
+ if (JSON.stringify(row) !== JSON.stringify(board[r])) {
625
+ moved = true;
626
+ board[r] = row;
627
+ }
628
+
629
+ // Merge adjacent equal tiles
630
+ for (let c = 0; c < 3; c++) {
631
+ if (board[r][c] !== 0 && board[r][c] === board[r][c + 1]) {
632
+ board[r][c] *= 2;
633
+ board[r][c + 1] = 0;
634
+ score += board[r][c];
635
+ moved = true;
636
+
637
+ // Create merge effect
638
+ createMergeEffect(r, c);
639
+
640
+ // Update best score if needed
641
+ if (score > bestScore) {
642
+ bestScore = score;
643
+ localStorage.setItem('bestScore', bestScore);
644
+ bestScoreDisplay.textContent = bestScore;
645
+ }
646
+
647
+ // Check for win condition
648
+ if (board[r][c] === 2048 && !isGameWon) {
649
+ gameWon();
650
+ }
651
+
652
+ // Compact again after merging
653
+ row = board[r].filter(val => val !== 0);
654
+ const newZeros = Array(4 - row.length).fill(0);
655
+ board[r] = row.concat(newZeros);
656
+ }
657
+ }
658
+ }
659
+
660
+ return moved;
661
+ }
662
+
663
+ // Move tiles right
664
+ function moveRight() {
665
+ let moved = false;
666
+
667
+ for (let r = 0; r < 4; r++) {
668
+ // Remove zeros and compact to the right
669
+ let row = board[r].filter(val => val !== 0);
670
+ const zeros = Array(4 - row.length).fill(0);
671
+ row = zeros.concat(row);
672
+
673
+ // Check if the row changed
674
+ if (JSON.stringify(row) !== JSON.stringify(board[r])) {
675
+ moved = true;
676
+ board[r] = row;
677
+ }
678
+
679
+ // Merge adjacent equal tiles
680
+ for (let c = 3; c > 0; c--) {
681
+ if (board[r][c] !== 0 && board[r][c] === board[r][c - 1]) {
682
+ board[r][c] *= 2;
683
+ board[r][c - 1] = 0;
684
+ score += board[r][c];
685
+ moved = true;
686
+
687
+ // Create merge effect
688
+ createMergeEffect(r, c);
689
+
690
+ // Update best score if needed
691
+ if (score > bestScore) {
692
+ bestScore = score;
693
+ localStorage.setItem('bestScore', bestScore);
694
+ bestScoreDisplay.textContent = bestScore;
695
+ }
696
+
697
+ // Check for win condition
698
+ if (board[r][c] === 2048 && !isGameWon) {
699
+ gameWon();
700
+ }
701
+
702
+ // Compact again after merging
703
+ row = board[r].filter(val => val !== 0);
704
+ const newZeros = Array(4 - row.length).fill(0);
705
+ board[r] = newZeros.concat(row);
706
+ }
707
+ }
708
+ }
709
+
710
+ return moved;
711
+ }
712
+
713
+ // Move tiles up
714
+ function moveUp() {
715
+ let moved = false;
716
+
717
+ for (let c = 0; c < 4; c++) {
718
+ // Get column values
719
+ let column = [board[0][c], board[1][c], board[2][c], board[3][c]];
720
+
721
+ // Remove zeros and compact up
722
+ let newColumn = column.filter(val => val !== 0);
723
+ const zeros = Array(4 - newColumn.length).fill(0);
724
+ newColumn = newColumn.concat(zeros);
725
+
726
+ // Check if the column changed
727
+ if (JSON.stringify(newColumn) !== JSON.stringify(column)) {
728
+ moved = true;
729
+ for (let r = 0; r < 4; r++) {
730
+ board[r][c] = newColumn[r];
731
+ }
732
+ }
733
+
734
+ // Merge adjacent equal tiles
735
+ for (let r = 0; r < 3; r++) {
736
+ if (board[r][c] !== 0 && board[r][c] === board[r + 1][c]) {
737
+ board[r][c] *= 2;
738
+ board[r + 1][c] = 0;
739
+ score += board[r][c];
740
+ moved = true;
741
+
742
+ // Create merge effect
743
+ createMergeEffect(r, c);
744
+
745
+ // Update best score if needed
746
+ if (score > bestScore) {
747
+ bestScore = score;
748
+ localStorage.setItem('bestScore', bestScore);
749
+ bestScoreDisplay.textContent = bestScore;
750
+ }
751
+
752
+ // Check for win condition
753
+ if (board[r][c] === 2048 && !isGameWon) {
754
+ gameWon();
755
+ }
756
+
757
+ // Compact again after merging
758
+ column = [board[0][c], board[1][c], board[2][c], board[3][c]];
759
+ newColumn = column.filter(val => val !== 0);
760
+ const newZeros = Array(4 - newColumn.length).fill(0);
761
+ newColumn = newColumn.concat(newZeros);
762
+ for (let r = 0; r < 4; r++) {
763
+ board[r][c] = newColumn[r];
764
+ }
765
+ }
766
+ }
767
+ }
768
+
769
+ return moved;
770
+ }
771
+
772
+ // Move tiles down
773
+ function moveDown() {
774
+ let moved = false;
775
+
776
+ for (let c = 0; c < 4; c++) {
777
+ // Get column values
778
+ let column = [board[0][c], board[1][c], board[2][c], board[3][c]];
779
+
780
+ // Remove zeros and compact down
781
+ let newColumn = column.filter(val => val !== 0);
782
+ const zeros = Array(4 - newColumn.length).fill(0);
783
+ newColumn = zeros.concat(newColumn);
784
+
785
+ // Check if the column changed
786
+ if (JSON.stringify(newColumn) !== JSON.stringify(column)) {
787
+ moved = true;
788
+ for (let r = 0; r < 4; r++) {
789
+ board[r][c] = newColumn[r];
790
+ }
791
+ }
792
+
793
+ // Merge adjacent equal tiles
794
+ for (let r = 3; r > 0; r--) {
795
+ if (board[r][c] !== 0 && board[r][c] === board[r - 1][c]) {
796
+ board[r][c] *= 2;
797
+ board[r - 1][c] = 0;
798
+ score += board[r][c];
799
+ moved = true;
800
+
801
+ // Create merge effect
802
+ createMergeEffect(r, c);
803
+
804
+ // Update best score if needed
805
+ if (score > bestScore) {
806
+ bestScore = score;
807
+ localStorage.setItem('bestScore', bestScore);
808
+ bestScoreDisplay.textContent = bestScore;
809
+ }
810
+
811
+ // Check for win condition
812
+ if (board[r][c] === 2048 && !isGameWon) {
813
+ gameWon();
814
+ }
815
+
816
+ // Compact again after merging
817
+ column = [board[0][c], board[1][c], board[2][c], board[3][c]];
818
+ newColumn = column.filter(val => val !== 0);
819
+ const newZeros = Array(4 - newColumn.length).fill(0);
820
+ newColumn = newZeros.concat(newColumn);
821
+ for (let r = 0; r < 4; r++) {
822
+ board[r][c] = newColumn[r];
823
+ }
824
+ }
825
+ }
826
+ }
827
+
828
+ return moved;
829
+ }
830
+
831
+ // Create merge effect animation
832
+ function createMergeEffect(row, col) {
833
+ const effect = document.createElement('div');
834
+ effect.classList.add('merge-effect');
835
+ updateTilePosition(effect, row, col);
836
+ grid.appendChild(effect);
837
+
838
+ // Create particles
839
+ createParticles(row, col);
840
+
841
+ // Remove effect after animation
842
+ setTimeout(() => {
843
+ effect.remove();
844
+ }, 400);
845
+ }
846
+
847
+ // Create particles animation
848
+ function createParticles(row, col) {
849
+ const cellSize = grid.offsetWidth / 4;
850
+ const x = col * cellSize + cellSize / 2;
851
+ const y = row * cellSize + cellSize / 2;
852
+
853
+ for (let i = 0; i < 10; i++) {
854
+ const particle = document.createElement('div');
855
+ particle.classList.add('particle');
856
+
857
+ const size = Math.random() * 5 + 2;
858
+ particle.style.width = `${size}px`;
859
+ particle.style.height = `${size}px`;
860
+
861
+ const angle = Math.random() * Math.PI * 2;
862
+ const distance = Math.random() * 30 + 20;
863
+ const duration = Math.random() * 0.5 + 0.3;
864
+
865
+ particle.style.left = `${x}px`;
866
+ particle.style.top = `${y}px`;
867
+ particle.style.opacity = '0.8';
868
+
869
+ particlesContainer.appendChild(particle);
870
+
871
+ setTimeout(() => {
872
+ particle.style.transition = `all ${duration}s ease-out`;
873
+ particle.style.transform = `translate(${Math.cos(angle) * distance}px, ${Math.sin(angle) * distance}px)`;
874
+ particle.style.opacity = '0';
875
+ }, 10);
876
+
877
+ setTimeout(() => {
878
+ particle.remove();
879
+ }, duration * 1000 + 100);
880
+ }
881
+ }
882
+
883
+ // Check if game is over
884
+ function checkGameOver() {
885
+ // Check if there are any empty cells
886
+ for (let r = 0; r < 4; r++) {
887
+ for (let c = 0; c < 4; c++) {
888
+ if (board[r][c] === 0) {
889
+ return false;
890
+ }
891
+ }
892
+ }
893
+
894
+ // Check if any adjacent tiles can be merged
895
+ for (let r = 0; r < 4; r++) {
896
+ for (let c = 0; c < 3; c++) {
897
+ if (board[r][c] === board[r][c + 1]) {
898
+ return false;
899
+ }
900
+ }
901
+ }
902
+
903
+ for (let c = 0; c < 4; c++) {
904
+ for (let r = 0; r < 3; r++) {
905
+ if (board[r][c] === board[r + 1][c]) {
906
+ return false;
907
+ }
908
+ }
909
+ }
910
+
911
+ return true;
912
+ }
913
+
914
+ // Game won
915
+ function gameWon() {
916
+ isGameWon = true;
917
+ gameMessage.classList.add('game-won');
918
+ messageText.textContent = 'You Win!';
919
+ gameMessage.style.display = 'flex';
920
+ }
921
+
922
+ // Game over
923
+ function gameOver() {
924
+ isGameOver = true;
925
+ gameMessage.classList.add('game-over');
926
+ messageText.textContent = 'Game Over!';
927
+ gameMessage.style.display = 'flex';
928
+ }
929
+
930
+ // Handle keyboard input
931
+ function handleKeyDown(e) {
932
+ if (isGameOver && !isGameWon) return;
933
+
934
+ let moved = false;
935
+
936
+ switch (e.key) {
937
+ case 'ArrowLeft':
938
+ moved = moveLeft();
939
+ break;
940
+ case 'ArrowRight':
941
+ moved = moveRight();
942
+ break;
943
+ case 'ArrowUp':
944
+ moved = moveUp();
945
+ break;
946
+ case 'ArrowDown':
947
+ moved = moveDown();
948
+ break;
949
+ default:
950
+ return;
951
+ }
952
+
953
+ if (moved) {
954
+ scoreDisplay.textContent = score;
955
+ addRandomTile();
956
+ updateView();
957
+
958
+ if (!isGameWon && checkGameOver()) {
959
+ gameOver();
960
+ }
961
+ }
962
+ }
963
+
964
+ // Handle touch events for mobile
965
+ function handleTouchStart(e) {
966
+ touchStartX = e.touches[0].clientX;
967
+ touchStartY = e.touches[0].clientY;
968
+ }
969
+
970
+ function handleTouchEnd(e) {
971
+ if (isGameOver && !isGameWon) return;
972
+
973
+ touchEndX = e.changedTouches[0].clientX;
974
+ touchEndY = e.changedTouches[0].clientY;
975
+
976
+ const dx = touchEndX - touchStartX;
977
+ const dy = touchEndY - touchStartY;
978
+
979
+ // Determine the direction of the swipe
980
+ if (Math.abs(dx) > Math.abs(dy)) {
981
+ // Horizontal swipe
982
+ if (dx > 50) {
983
+ // Right swipe
984
+ if (moveRight()) {
985
+ scoreDisplay.textContent = score;
986
+ addRandomTile();
987
+ updateView();
988
+
989
+ if (!isGameWon && checkGameOver()) {
990
+ gameOver();
991
+ }
992
+ }
993
+ } else if (dx < -50) {
994
+ // Left swipe
995
+ if (moveLeft()) {
996
+ scoreDisplay.textContent = score;
997
+ addRandomTile();
998
+ updateView();
999
+
1000
+ if (!isGameWon && checkGameOver()) {
1001
+ gameOver();
1002
+ }
1003
+ }
1004
+ }
1005
+ } else {
1006
+ // Vertical swipe
1007
+ if (dy > 50) {
1008
+ // Down swipe
1009
+ if (moveDown()) {
1010
+ scoreDisplay.textContent = score;
1011
+ addRandomTile();
1012
+ updateView();
1013
+
1014
+ if (!isGameWon && checkGameOver()) {
1015
+ gameOver();
1016
+ }
1017
+ }
1018
+ } else if (dy < -50) {
1019
+ // Up swipe
1020
+ if (moveUp()) {
1021
+ scoreDisplay.textContent = score;
1022
+ addRandomTile();
1023
+ updateView();
1024
+
1025
+ if (!isGameWon && checkGameOver()) {
1026
+ gameOver();
1027
+ }
1028
+ }
1029
+ }
1030
+ }
1031
+ }
1032
+
1033
+ // Restart game
1034
+ restartBtn.addEventListener('click', initGame);
1035
+
1036
+ // Event listeners
1037
+ document.addEventListener('keydown', handleKeyDown);
1038
+ document.addEventListener('touchstart', handleTouchStart, false);
1039
+ document.addEventListener('touchend', handleTouchEnd, false);
1040
+
1041
+ // Initialize the game
1042
+ initGame();
1043
+
1044
+ // Create background particles
1045
+ function createBackgroundParticles() {
1046
+ const particleCount = 30;
1047
+
1048
+ for (let i = 0; i < particleCount; i++) {
1049
+ const particle = document.createElement('div');
1050
+ particle.classList.add('particle');
1051
+
1052
+ const size = Math.random() * 3 + 1;
1053
+ particle.style.width = `${size}px`;
1054
+ particle.style.height = `${size}px`;
1055
+
1056
+ // Random position
1057
+ const x = Math.random() * 100;
1058
+ const y = Math.random() * 100;
1059
+ particle.style.left = `${x}%`;
1060
+ particle.style.top = `${y}%`;
1061
+
1062
+ // Random opacity
1063
+ particle.style.opacity = Math.random() * 0.5 + 0.1;
1064
+
1065
+ // Random animation
1066
+ const duration = Math.random() * 20 + 10;
1067
+ const delay = Math.random() * 5;
1068
+
1069
+ particle.style.animation = `float ${duration}s ease-in-out ${delay}s infinite`;
1070
+
1071
+ particlesContainer.appendChild(particle);
1072
+ }
1073
+ }
1074
+
1075
+ // Add floating animation
1076
+ const style = document.createElement('style');
1077
+ style.textContent = `
1078
+ @keyframes float {
1079
+ 0%, 100% {
1080
+ transform: translate(0, 0);
1081
+ }
1082
+ 25% {
1083
+ transform: translate(${Math.random() * 50 - 25}px, ${Math.random() * 50 - 25}px);
1084
+ }
1085
+ 50% {
1086
+ transform: translate(${Math.random() * 50 - 25}px, ${Math.random() * 50 - 25}px);
1087
+ }
1088
+ 75% {
1089
+ transform: translate(${Math.random() * 50 - 25}px, ${Math.random() * 50 - 25}px);
1090
+ }
1091
+ }
1092
+ `;
1093
+ document.head.appendChild(style);
1094
+
1095
+ createBackgroundParticles();
1096
+ });
1097
+ </script>
1098
+ <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <a href="https://enzostvs-deepsite.hf.space" style="color: #fff;" target="_blank" >DeepSite</a> <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;"></p></body>
1099
+ </html>