xianbao commited on
Commit
7694999
·
verified ·
1 Parent(s): 67146cd

Upload folder using huggingface_hub

Browse files
Files changed (1) hide show
  1. index.html +1015 -19
index.html CHANGED
@@ -1,19 +1,1015 @@
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="zh-CN">
3
+
4
+ <head>
5
+ <meta charset="UTF-8">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
+ <title>推箱子大冒险 - 儿童益智游戏</title>
8
+ <style>
9
+ * {
10
+ margin: 0;
11
+ padding: 0;
12
+ box-sizing: border-box;
13
+ }
14
+
15
+ :root {
16
+ --primary-color: #6366f1;
17
+ --secondary-color: #8b5cf6;
18
+ --success-color: #10b981;
19
+ --warning-color: #f59e0b;
20
+ --danger-color: #ef4444;
21
+ --dark-color: #1f2937;
22
+ --light-color: #f3f4f6;
23
+ --game-bg: #fef3c7;
24
+ --wall-color: #92400e;
25
+ --box-color: #d97706;
26
+ --box-on-target: #059669;
27
+ --target-color: #fbbf24;
28
+ --player-color: #3b82f6;
29
+ }
30
+
31
+ body {
32
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
33
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
34
+ min-height: 100vh;
35
+ display: flex;
36
+ flex-direction: column;
37
+ align-items: center;
38
+ padding: 20px;
39
+ position: relative;
40
+ overflow-x: hidden;
41
+ }
42
+
43
+ body::before {
44
+ content: '';
45
+ position: absolute;
46
+ top: -50%;
47
+ left: -50%;
48
+ width: 200%;
49
+ height: 200%;
50
+ background: repeating-linear-gradient(45deg,
51
+ transparent,
52
+ transparent 10px,
53
+ rgba(255, 255, 255, 0.05) 10px,
54
+ rgba(255, 255, 255, 0.05) 20px);
55
+ animation: backgroundMove 20s linear infinite;
56
+ }
57
+
58
+ @keyframes backgroundMove {
59
+ 0% {
60
+ transform: translate(0, 0);
61
+ }
62
+
63
+ 100% {
64
+ transform: translate(50px, 50px);
65
+ }
66
+ }
67
+
68
+ header {
69
+ background: rgba(255, 255, 255, 0.95);
70
+ padding: 20px 40px;
71
+ border-radius: 20px;
72
+ box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
73
+ margin-bottom: 30px;
74
+ text-align: center;
75
+ backdrop-filter: blur(10px);
76
+ position: relative;
77
+ z-index: 10;
78
+ }
79
+
80
+ h1 {
81
+ color: var(--primary-color);
82
+ font-size: 2.5rem;
83
+ margin-bottom: 10px;
84
+ text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.1);
85
+ animation: titleBounce 2s ease-in-out infinite;
86
+ }
87
+
88
+ @keyframes titleBounce {
89
+
90
+ 0%,
91
+ 100% {
92
+ transform: translateY(0);
93
+ }
94
+
95
+ 50% {
96
+ transform: translateY(-5px);
97
+ }
98
+ }
99
+
100
+ .subtitle {
101
+ color: var(--secondary-color);
102
+ font-size: 1.2rem;
103
+ margin-bottom: 15px;
104
+ }
105
+
106
+ .built-with {
107
+ color: var(--dark-color);
108
+ font-size: 0.9rem;
109
+ opacity: 0.7;
110
+ transition: opacity 0.3s;
111
+ }
112
+
113
+ .built-with:hover {
114
+ opacity: 1;
115
+ text-decoration: underline;
116
+ }
117
+
118
+ main {
119
+ background: rgba(255, 255, 255, 0.95);
120
+ padding: 30px;
121
+ border-radius: 20px;
122
+ box-shadow: 0 15px 40px rgba(0, 0, 0, 0.2);
123
+ max-width: 800px;
124
+ width: 100%;
125
+ backdrop-filter: blur(10px);
126
+ position: relative;
127
+ z-index: 10;
128
+ }
129
+
130
+ .level-selector {
131
+ display: none;
132
+ grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
133
+ gap: 15px;
134
+ margin-bottom: 30px;
135
+ }
136
+
137
+ .level-selector.active {
138
+ display: grid;
139
+ }
140
+
141
+ .level-btn {
142
+ background: linear-gradient(135deg, var(--primary-color), var(--secondary-color));
143
+ color: white;
144
+ border: none;
145
+ padding: 15px;
146
+ border-radius: 15px;
147
+ font-size: 1.1rem;
148
+ font-weight: bold;
149
+ cursor: pointer;
150
+ transition: all 0.3s ease;
151
+ position: relative;
152
+ overflow: hidden;
153
+ }
154
+
155
+ .level-btn::before {
156
+ content: '';
157
+ position: absolute;
158
+ top: 50%;
159
+ left: 50%;
160
+ width: 0;
161
+ height: 0;
162
+ background: rgba(255, 255, 255, 0.3);
163
+ border-radius: 50%;
164
+ transform: translate(-50%, -50%);
165
+ transition: width 0.6s, height 0.6s;
166
+ }
167
+
168
+ .level-btn:hover::before {
169
+ width: 300px;
170
+ height: 300px;
171
+ }
172
+
173
+ .level-btn:hover {
174
+ transform: translateY(-3px);
175
+ box-shadow: 0 10px 20px rgba(99, 102, 241, 0.3);
176
+ }
177
+
178
+ .level-btn:disabled {
179
+ opacity: 0.5;
180
+ cursor: not-allowed;
181
+ }
182
+
183
+ .level-btn.completed {
184
+ background: linear-gradient(135deg, var(--success-color), #059669);
185
+ }
186
+
187
+ .level-btn.current {
188
+ animation: pulse 2s infinite;
189
+ }
190
+
191
+ @keyframes pulse {
192
+ 0% {
193
+ box-shadow: 0 0 0 0 rgba(99, 102, 241, 0.7);
194
+ }
195
+
196
+ 70% {
197
+ box-shadow: 0 0 0 10px rgba(99, 102, 241, 0);
198
+ }
199
+
200
+ 100% {
201
+ box-shadow: 0 0 0 0 rgba(99, 102, 241, 0);
202
+ }
203
+ }
204
+
205
+ .game-info {
206
+ display: flex;
207
+ justify-content: space-between;
208
+ align-items: center;
209
+ margin-bottom: 20px;
210
+ flex-wrap: wrap;
211
+ gap: 15px;
212
+ }
213
+
214
+ .info-item {
215
+ background: linear-gradient(135deg, #f3f4f6, #e5e7eb);
216
+ padding: 10px 20px;
217
+ border-radius: 10px;
218
+ display: flex;
219
+ align-items: center;
220
+ gap: 10px;
221
+ box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
222
+ }
223
+
224
+ .info-label {
225
+ color: var(--dark-color);
226
+ font-weight: bold;
227
+ }
228
+
229
+ .info-value {
230
+ color: var(--primary-color);
231
+ font-size: 1.2rem;
232
+ font-weight: bold;
233
+ }
234
+
235
+ .game-container {
236
+ display: flex;
237
+ flex-direction: column;
238
+ align-items: center;
239
+ gap: 20px;
240
+ }
241
+
242
+ .game-board {
243
+ display: grid;
244
+ gap: 2px;
245
+ padding: 20px;
246
+ background: var(--game-bg);
247
+ border-radius: 15px;
248
+ box-shadow: inset 0 2px 10px rgba(0, 0, 0, 0.1);
249
+ position: relative;
250
+ }
251
+
252
+ .cell {
253
+ width: 50px;
254
+ height: 50px;
255
+ display: flex;
256
+ align-items: center;
257
+ justify-content: center;
258
+ font-size: 30px;
259
+ transition: all 0.3s ease;
260
+ position: relative;
261
+ }
262
+
263
+ .cell.wall {
264
+ background: linear-gradient(135deg, var(--wall-color), #78350f);
265
+ border-radius: 5px;
266
+ box-shadow: 0 2px 5px rgba(0, 0, 0, 0.3);
267
+ }
268
+
269
+ .cell.floor {
270
+ background: rgba(255, 255, 255, 0.3);
271
+ border-radius: 5px;
272
+ }
273
+
274
+ .cell.target {
275
+ background: var(--target-color);
276
+ border-radius: 50%;
277
+ animation: targetPulse 2s infinite;
278
+ }
279
+
280
+ @keyframes targetPulse {
281
+
282
+ 0%,
283
+ 100% {
284
+ transform: scale(1);
285
+ opacity: 0.8;
286
+ }
287
+
288
+ 50% {
289
+ transform: scale(1.1);
290
+ opacity: 1;
291
+ }
292
+ }
293
+
294
+ .player {
295
+ animation: playerBounce 0.5s ease;
296
+ }
297
+
298
+ @keyframes playerBounce {
299
+
300
+ 0%,
301
+ 100% {
302
+ transform: translateY(0);
303
+ }
304
+
305
+ 50% {
306
+ transform: translateY(-10px);
307
+ }
308
+ }
309
+
310
+ .box {
311
+ animation: boxMove 0.3s ease;
312
+ }
313
+
314
+ @keyframes boxMove {
315
+ 0% {
316
+ transform: scale(1);
317
+ }
318
+
319
+ 50% {
320
+ transform: scale(1.1);
321
+ }
322
+
323
+ 100% {
324
+ transform: scale(1);
325
+ }
326
+ }
327
+
328
+ .box-on-target {
329
+ animation: successPulse 1s infinite;
330
+ }
331
+
332
+ @keyframes successPulse {
333
+
334
+ 0%,
335
+ 100% {
336
+ transform: scale(1) rotate(0deg);
337
+ }
338
+
339
+ 50% {
340
+ transform: scale(1.1) rotate(5deg);
341
+ }
342
+ }
343
+
344
+ .controls {
345
+ display: flex;
346
+ gap: 10px;
347
+ justify-content: center;
348
+ flex-wrap: wrap;
349
+ }
350
+
351
+ .btn {
352
+ background: linear-gradient(135deg, var(--primary-color), var(--secondary-color));
353
+ color: white;
354
+ border: none;
355
+ padding: 12px 24px;
356
+ border-radius: 10px;
357
+ font-size: 1rem;
358
+ font-weight: bold;
359
+ cursor: pointer;
360
+ transition: all 0.3s ease;
361
+ display: flex;
362
+ align-items: center;
363
+ gap: 8px;
364
+ }
365
+
366
+ .btn:hover {
367
+ transform: translateY(-2px);
368
+ box-shadow: 0 5px 15px rgba(99, 102, 241, 0.3);
369
+ }
370
+
371
+ .btn:active {
372
+ transform: translateY(0);
373
+ }
374
+
375
+ .btn-secondary {
376
+ background: linear-gradient(135deg, #6b7280, #4b5563);
377
+ }
378
+
379
+ .btn-success {
380
+ background: linear-gradient(135deg, var(--success-color), #059669);
381
+ }
382
+
383
+ .btn-danger {
384
+ background: linear-gradient(135deg, var(--danger-color), #dc2626);
385
+ }
386
+
387
+ .arrow-keys {
388
+ display: grid;
389
+ grid-template-columns: repeat(3, 60px);
390
+ grid-template-rows: repeat(3, 60px);
391
+ gap: 5px;
392
+ margin-top: 20px;
393
+ }
394
+
395
+ .arrow-key {
396
+ background: linear-gradient(135deg, #e5e7eb, #d1d5db);
397
+ border: 2px solid #9ca3af;
398
+ border-radius: 10px;
399
+ font-size: 24px;
400
+ cursor: pointer;
401
+ transition: all 0.2s ease;
402
+ display: flex;
403
+ align-items: center;
404
+ justify-content: center;
405
+ }
406
+
407
+ .arrow-key:hover {
408
+ background: linear-gradient(135deg, var(--primary-color), var(--secondary-color));
409
+ border-color: var(--primary-color);
410
+ transform: scale(1.05);
411
+ }
412
+
413
+ .arrow-key:active {
414
+ transform: scale(0.95);
415
+ }
416
+
417
+ .arrow-key.up {
418
+ grid-column: 2;
419
+ grid-row: 1;
420
+ }
421
+
422
+ .arrow-key.left {
423
+ grid-column: 1;
424
+ grid-row: 2;
425
+ }
426
+
427
+ .arrow-key.down {
428
+ grid-column: 2;
429
+ grid-row: 2;
430
+ }
431
+
432
+ .arrow-key.right {
433
+ grid-column: 3;
434
+ grid-row: 2;
435
+ }
436
+
437
+ .win-message {
438
+ display: none;
439
+ position: fixed;
440
+ top: 50%;
441
+ left: 50%;
442
+ transform: translate(-50%, -50%);
443
+ background: white;
444
+ padding: 40px;
445
+ border-radius: 20px;
446
+ box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
447
+ text-align: center;
448
+ z-index: 1000;
449
+ animation: winPop 0.5s ease;
450
+ }
451
+
452
+ @keyframes winPop {
453
+ 0% {
454
+ transform: translate(-50%, -50%) scale(0);
455
+ }
456
+
457
+ 50% {
458
+ transform: translate(-50%, -50%) scale(1.1);
459
+ }
460
+
461
+ 100% {
462
+ transform: translate(-50%, -50%) scale(1);
463
+ }
464
+ }
465
+
466
+ .win-message.active {
467
+ display: block;
468
+ }
469
+
470
+ .win-title {
471
+ font-size: 2rem;
472
+ color: var(--success-color);
473
+ margin-bottom: 20px;
474
+ }
475
+
476
+ .stars {
477
+ font-size: 3rem;
478
+ margin-bottom: 20px;
479
+ animation: starSpin 1s ease;
480
+ }
481
+
482
+ @keyframes starSpin {
483
+ 0% {
484
+ transform: rotate(0deg) scale(0);
485
+ }
486
+
487
+ 100% {
488
+ transform: rotate(360deg) scale(1);
489
+ }
490
+ }
491
+
492
+ .overlay {
493
+ display: none;
494
+ position: fixed;
495
+ top: 0;
496
+ left: 0;
497
+ width: 100%;
498
+ height: 100%;
499
+ background: rgba(0, 0, 0, 0.5);
500
+ z-index: 999;
501
+ }
502
+
503
+ .overlay.active {
504
+ display: block;
505
+ }
506
+
507
+ @media (max-width: 768px) {
508
+ h1 {
509
+ font-size: 2rem;
510
+ }
511
+
512
+ .cell {
513
+ width: 40px;
514
+ height: 40px;
515
+ font-size: 24px;
516
+ }
517
+
518
+ .arrow-keys {
519
+ grid-template-columns: repeat(3, 50px);
520
+ grid-template-rows: repeat(3, 50px);
521
+ }
522
+
523
+ .game-board {
524
+ padding: 15px;
525
+ }
526
+ }
527
+
528
+ @media (max-width: 480px) {
529
+ .cell {
530
+ width: 30px;
531
+ height: 30px;
532
+ font-size: 18px;
533
+ }
534
+
535
+ .arrow-keys {
536
+ grid-template-columns: repeat(3, 40px);
537
+ grid-template-rows: repeat(3, 40px);
538
+ }
539
+
540
+ main {
541
+ padding: 20px;
542
+ }
543
+ }
544
+ </style>
545
+ </head>
546
+
547
+ <body>
548
+ <header>
549
+ <h1>🎮 推箱子大冒险 📦</h1>
550
+ <div class="subtitle">和小朋友一起玩益智游戏!</div>
551
+ <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" class="built-with">
552
+ Built with anycoder
553
+ </a>
554
+ </header>
555
+
556
+ <main>
557
+ <div class="level-selector active" id="levelSelector">
558
+ <button class="level-btn" onclick="startLevel(0)">关卡 1<br>🌱 简单</button>
559
+ <button class="level-btn" onclick="startLevel(1)">关卡 2<br>🌿 简单</button>
560
+ <button class="level-btn" onclick="startLevel(2)">关卡 3<br>🍀 中等</button>
561
+ <button class="level-btn" onclick="startLevel(3)">关卡 4<br>🌳 中等</button>
562
+ <button class="level-btn" onclick="startLevel(4)">关卡 5<br>🌲 困难</button>
563
+ <button class="level-btn" onclick="startLevel(5)">关卡 6<br>🎄 困难</button>
564
+ </div>
565
+
566
+ <div class="game-container" id="gameContainer" style="display: none;">
567
+ <div class="game-info">
568
+ <div class="info-item">
569
+ <span class="info-label">关卡:</span>
570
+ <span class="info-value" id="currentLevel">1</span>
571
+ </div>
572
+ <div class="info-item">
573
+ <span class="info-label">步数:</span>
574
+ <span class="info-value" id="moveCount">0</span>
575
+ </div>
576
+ <div class="info-item">
577
+ <span class="info-label">最佳:</span>
578
+ <span class="info-value" id="bestScore">-</span>
579
+ </div>
580
+ </div>
581
+
582
+ <div class="game-board" id="gameBoard"></div>
583
+
584
+ <div class="controls">
585
+ <button class="btn btn-secondary" onclick="undoMove()">
586
+ ↶ 撤销
587
+ </button>
588
+ <button class="btn btn-danger" onclick="resetLevel()">
589
+ 🔄 重置
590
+ </button>
591
+ <button class="btn btn-success" onclick="backToMenu()">
592
+ 📋 选关
593
+ </button>
594
+ </div>
595
+
596
+ <div class="arrow-keys">
597
+ <button class="arrow-key up" onclick="movePlayer('up')">↑</button>
598
+ <button class="arrow-key left" onclick="movePlayer('left')">←</button>
599
+ <button class="arrow-key down" onclick="movePlayer('down')">↓</button>
600
+ <button class="arrow-key right" onclick="movePlayer('right')">→</button>
601
+ </div>
602
+ </div>
603
+ </main>
604
+
605
+ <div class="overlay" id="overlay"></div>
606
+ <div class="win-message" id="winMessage">
607
+ <div class="win-title">🎉 恭喜过关!</div>
608
+ <div class="stars">⭐⭐⭐</div>
609
+ <div style="margin-bottom: 20px;">
610
+ 用了 <span id="finalMoves" style="color: var(--primary-color); font-weight: bold;">0</span> 步完成!
611
+ </div>
612
+ <div class="controls" style="justify-content: center;">
613
+ <button class="btn btn-success" onclick="nextLevel()">下一关</button>
614
+ <button class="btn btn-secondary" onclick="backToMenu()">选关菜单</button>
615
+ </div>
616
+ </div>
617
+
618
+ <script>
619
+ // 游戏数据
620
+ const levels = [
621
+ {
622
+ name: "入门练习",
623
+ width: 7,
624
+ height: 7,
625
+ map: [
626
+ "#######",
627
+ "# #",
628
+ "# $@$.#",
629
+ "# $ #",
630
+ "# . #",
631
+ "# #",
632
+ "#######"
633
+ ]
634
+ },
635
+ {
636
+ name: "双箱挑战",
637
+ width: 8,
638
+ height: 7,
639
+ map: [
640
+ "########",
641
+ "# . #",
642
+ "# $@$. #",
643
+ "# $ #",
644
+ "# . #",
645
+ "# #",
646
+ "########"
647
+ ]
648
+ },
649
+ {
650
+ name: "转角遇到爱",
651
+ width: 9,
652
+ height: 8,
653
+ map: [
654
+ "#########",
655
+ "# # #",
656
+ "# $ @ $ #",
657
+ "# . # . #",
658
+ "# # #",
659
+ "# $ $ #",
660
+ "# . . #",
661
+ "#########"
662
+ ]
663
+ },
664
+ {
665
+ name: "迷宫探险",
666
+ width: 10,
667
+ height: 8,
668
+ map: [
669
+ "##########",
670
+ "# # #",
671
+ "# $ @ $ #",
672
+ "# . # . #",
673
+ "# # #",
674
+ "# $ $ #",
675
+ "# . . #",
676
+ "##########"
677
+ ]
678
+ },
679
+ {
680
+ name: "极限挑战",
681
+ width: 11,
682
+ height: 9,
683
+ map: [
684
+ "###########",
685
+ "# # #",
686
+ "# $ @ $ #",
687
+ "# . # . #",
688
+ "# # #",
689
+ "# $ $ $ #",
690
+ "# . . . . #",
691
+ "# #",
692
+ "###########"
693
+ ]
694
+ },
695
+ {
696
+ name: "终极考验",
697
+ width: 12,
698
+ height: 10,
699
+ map: [
700
+ "############",
701
+ "# # #",
702
+ "# $ @ $ #",
703
+ "# . # . #",
704
+ "# # #",
705
+ "# $ $ $ #",
706
+ "# . . . . . #",
707
+ "# # #",
708
+ "# $ $ $ #",
709
+ "############"
710
+ ]
711
+ }
712
+ ];
713
+
714
+ let currentLevelIndex = 0;
715
+ let gameState = null;
716
+ let moveHistory = [];
717
+ let completedLevels = JSON.parse(localStorage.getItem('completedLevels') || '[]');
718
+ let bestScores = JSON.parse(localStorage.getItem('bestScores') || '{}');
719
+
720
+ // 初始化
721
+ function init() {
722
+ updateLevelButtons();
723
+ setupKeyboardControls();
724
+ }
725
+
726
+ // 更新关卡按钮状态
727
+ function updateLevelButtons() {
728
+ const buttons = document.querySelectorAll('.level-btn');
729
+ buttons.forEach((btn, index) => {
730
+ if (completedLevels.includes(index)) {
731
+ btn.classList.add('completed');
732
+ } else {
733
+ btn.classList.remove('completed');
734
+ }
735
+ });
736
+ }
737
+
738
+ // 开始关卡
739
+ function startLevel(levelIndex) {
740
+ currentLevelIndex = levelIndex;
741
+ const level = levels[levelIndex];
742
+
743
+ gameState = {
744
+ map: JSON.parse(JSON.stringify(level.map)),
745
+ playerPos: findPlayer(level.map),
746
+ boxes: findBoxes(level.map),
747
+ targets: findTargets(level.map),
748
+ moveCount: 0
749
+ };
750
+
751
+ moveHistory = [];
752
+
753
+ document.getElementById('levelSelector').classList.remove('active');
754
+ document.getElementById('gameContainer').style.display = 'flex';
755
+ document.getElementById('currentLevel').textContent = levelIndex + 1;
756
+ document.getElementById('moveCount').textContent = '0';
757
+ document.getElementById('bestScore').textContent = bestScores[levelIndex] || '-';
758
+
759
+ renderGame();
760
+ }
761
+
762
+ // 渲染游戏
763
+ function renderGame() {
764
+ const board = document.getElementById('gameBoard');
765
+ const level = levels[currentLevelIndex];
766
+ board.style.gridTemplateColumns = `repeat(${level.width}, 1fr)`;
767
+ board.innerHTML = '';
768
+
769
+ for (let y = 0; y < level.height; y++) {
770
+ for (let x = 0; x < level.width; x++) {
771
+ const cell = document.createElement('div');
772
+ cell.className = 'cell';
773
+
774
+ const char = gameState.map[y][x];
775
+ const isTarget = gameState.targets.some(t => t.x === x && t.y === y);
776
+ const hasBox = gameState.boxes.some(b => b.x === x && b.y === y);
777
+ const isPlayer = gameState.playerPos.x === x && gameState.playerPos.y === y;
778
+
779
+ if (char === '#') {
780
+ cell.classList.add('wall');
781
+ cell.textContent = '🧱';
782
+ } else if (isTarget && !hasBox && !isPlayer) {
783
+ cell.classList.add('target');
784
+ cell.textContent = '🎯';
785
+ } else {
786
+ cell.classList.add('floor');
787
+ if (hasBox) {
788
+ cell.classList.add('box');
789
+ if (isTarget) {
790
+ cell.classList.add('box-on-target');
791
+ cell.textContent = '✅';
792
+ } else {
793
+ cell.textContent = '📦';
794
+ }
795
+ } else if (isPlayer) {
796
+ cell.classList.add('player');
797
+ cell.textContent = '🤖';
798
+ }
799
+ }
800
+
801
+ board.appendChild(cell);
802
+ }
803
+ }
804
+ }
805
+
806
+ // 查找玩家位置
807
+ function findPlayer(map) {
808
+ for (let y = 0; y < map.length; y++) {
809
+ for (let x = 0; x < map[y].length; x++) {
810
+ if (map[y][x] === '@') {
811
+ return { x, y };
812
+ }
813
+ }
814
+ }
815
+ return null;
816
+ }
817
+
818
+ // 查找箱子位置
819
+ function findBoxes(map) {
820
+ const boxes = [];
821
+ for (let y = 0; y < map.length; y++) {
822
+ for (let x = 0; x < map[y].length; x++) {
823
+ if (map[y][x] === '$') {
824
+ boxes.push({ x, y });
825
+ }
826
+ }
827
+ }
828
+ return boxes;
829
+ }
830
+
831
+ // 查找目标位置
832
+ function findTargets(map) {
833
+ const targets = [];
834
+ for (let y = 0; y < map.length; y++) {
835
+ for (let x = 0; x < map[y].length; x++) {
836
+ if (map[y][x] === '.') {
837
+ targets.push({ x, y });
838
+ }
839
+ }
840
+ }
841
+ return targets;
842
+ }
843
+
844
+ // 移动玩家
845
+ function movePlayer(direction) {
846
+ if (!gameState) return;
847
+
848
+ const dirs = {
849
+ 'up': { x: 0, y: -1 },
850
+ 'down': { x: 0, y: 1 },
851
+ 'left': { x: -1, y: 0 },
852
+ 'right': { x: 1, y: 0 }
853
+ };
854
+
855
+ const dir = dirs[direction];
856
+ const newPos = {
857
+ x: gameState.playerPos.x + dir.x,
858
+ y: gameState.playerPos.y + dir.y
859
+ };
860
+
861
+ // 保存历史
862
+ const history = {
863
+ playerPos: { ...gameState.playerPos },
864
+ boxes: gameState.boxes.map(b => ({ ...b })),
865
+ moveCount: gameState.moveCount
866
+ };
867
+
868
+ // 检查是否撞墙
869
+ if (gameState.map[newPos.y][newPos.x] === '#') {
870
+ return;
871
+ }
872
+
873
+ // 检查是否有箱子
874
+ const boxIndex = gameState.boxes.findIndex(b => b.x === newPos.x && b.y === newPos.y);
875
+ if (boxIndex !== -1) {
876
+ const newBoxPos = {
877
+ x: newPos.x + dir.x,
878
+ y: newPos.y + dir.y
879
+ };
880
+
881
+ // 检查箱子是否能移动
882
+ if (gameState.map[newBoxPos.y][newBoxPos.x] === '#') {
883
+ return;
884
+ }
885
+
886
+ // 检查是否有其他箱子
887
+ if (gameState.boxes.some(b => b.x === newBoxPos.x && b.y === newBoxPos.y)) {
888
+ return;
889
+ }
890
+
891
+ // 移动箱子
892
+ gameState.boxes[boxIndex] = newBoxPos;
893
+ moveHistory.push(history);
894
+ gameState.playerPos = newPos;
895
+ gameState.moveCount++;
896
+ } else {
897
+ // 只移动玩家
898
+ moveHistory.push(history);
899
+ gameState.playerPos = newPos;
900
+ gameState.moveCount++;
901
+ }
902
+
903
+ document.getElementById('moveCount').textContent = gameState.moveCount;
904
+ renderGame();
905
+
906
+ // 检查是否获胜
907
+ if (checkWin()) {
908
+ setTimeout(() => showWinMessage(), 500);
909
+ }
910
+ }
911
+
912
+ // 检查是否获胜
913
+ function checkWin() {
914
+ return gameState.targets.every(target =>
915
+ gameState.boxes.some(box => box.x === target.x && box.y === target.y)
916
+ );
917
+ }
918
+
919
+ // 显示获胜消息
920
+ function showWinMessage() {
921
+ if (!completedLevels.includes(currentLevelIndex)) {
922
+ completedLevels.push(currentLevelIndex);
923
+ localStorage.setItem('completedLevels', JSON.stringify(completedLevels));
924
+ }
925
+
926
+ if (!bestScores[currentLevelIndex] || gameState.moveCount < bestScores[currentLevelIndex]) {
927
+ bestScores[currentLevelIndex] = gameState.moveCount;
928
+ localStorage.setItem('bestScores', JSON.stringify(bestScores));
929
+ }
930
+
931
+ document.getElementById('finalMoves').textContent = gameState.moveCount;
932
+ document.getElementById('overlay').classList.add('active');
933
+ document.getElementById('winMessage').classList.add('active');
934
+ }
935
+
936
+ // 下一关
937
+ function nextLevel() {
938
+ document.getElementById('overlay').classList.remove('active');
939
+ document.getElementById('winMessage').classList.remove('active');
940
+
941
+ if (currentLevelIndex < levels.length - 1) {
942
+ startLevel(currentLevelIndex + 1);
943
+ } else {
944
+ backToMenu();
945
+ }
946
+ }
947
+
948
+ // 撤销移动
949
+ function undoMove() {
950
+ if (moveHistory.length === 0) return;
951
+
952
+ const history = moveHistory.pop();
953
+ gameState.playerPos = history.playerPos;
954
+ gameState.boxes = history.boxes;
955
+ gameState.moveCount = history.moveCount;
956
+
957
+ document.getElementById('moveCount').textContent = gameState.moveCount;
958
+ renderGame();
959
+ }
960
+
961
+ // 重置关卡
962
+ function resetLevel() {
963
+ startLevel(currentLevelIndex);
964
+ }
965
+
966
+ // 返回菜单
967
+ function backToMenu() {
968
+ document.getElementById('overlay').classList.remove('active');
969
+ document.getElementById('winMessage').classList.remove('active');
970
+ document.getElementById('levelSelector').classList.add('active');
971
+ document.getElementById('gameContainer').style.display = 'none';
972
+ updateLevelButtons();
973
+ }
974
+
975
+ // 设置键盘控制
976
+ function setupKeyboardControls() {
977
+ document.addEventListener('keydown', (e) => {
978
+ if (!gameState) return;
979
+
980
+ const keyMap = {
981
+ 'ArrowUp': 'up',
982
+ 'ArrowDown': 'down',
983
+ 'ArrowLeft': 'left',
984
+ 'ArrowRight': 'right',
985
+ 'w': 'up',
986
+ 's': 'down',
987
+ 'a': 'left',
988
+ 'd': 'right',
989
+ 'W': 'up',
990
+ 'S': 'down',
991
+ 'A': 'left',
992
+ 'D': 'right'
993
+ };
994
+
995
+ if (keyMap[e.key]) {
996
+ e.preventDefault();
997
+ movePlayer(keyMap[e.key]);
998
+ }
999
+
1000
+ if (e.key === 'z' || e.key === 'Z') {
1001
+ undoMove();
1002
+ }
1003
+
1004
+ if (e.key === 'r' || e.key === 'R') {
1005
+ resetLevel();
1006
+ }
1007
+ });
1008
+ }
1009
+
1010
+ // 启动游戏
1011
+ init();
1012
+ </script>
1013
+ </body>
1014
+
1015
+ </html>