Lashtw commited on
Commit
30a5040
·
verified ·
1 Parent(s): 54f74c4

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +1456 -19
index.html CHANGED
@@ -1,19 +1,1456 @@
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-TW">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>數戰棋 - 互動式數學遊戲</title>
7
+ <style>
8
+ * {
9
+ margin: 0;
10
+ padding: 0;
11
+ box-sizing: border-box;
12
+ }
13
+
14
+ body {
15
+ font-family: 'PingFang TC', 'Heiti TC', 'Microsoft JhengHei', sans-serif;
16
+ background: linear-gradient(135deg, #0f172a 0%, #1e1b4b 100%);
17
+ color: #f1f5f9;
18
+ min-height: 100vh;
19
+ padding: 20px;
20
+ display: flex;
21
+ align-items: center;
22
+ justify-content: center;
23
+ }
24
+
25
+ .container {
26
+ width: 100%;
27
+ max-width: 1200px;
28
+ background: rgba(30, 41, 59, 0.7);
29
+ backdrop-filter: blur(12px);
30
+ -webkit-backdrop-filter: blur(12px);
31
+ border: 1px solid rgba(255, 255, 255, 0.1);
32
+ border-radius: 20px;
33
+ box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.5);
34
+ overflow: hidden;
35
+ }
36
+
37
+ .header {
38
+ background: linear-gradient(90deg, #10b981, #059669);
39
+ color: white;
40
+ padding: 24px;
41
+ text-align: center;
42
+ border-bottom: 1px solid rgba(255, 255, 255, 0.1);
43
+ }
44
+
45
+ .header h1 {
46
+ font-size: 2.6em;
47
+ margin-bottom: 8px;
48
+ text-shadow: 0 4px 6px rgba(0,0,0,0.2);
49
+ font-weight: 800;
50
+ letter-spacing: 2px;
51
+ }
52
+
53
+ .header p {
54
+ font-size: 1.1em;
55
+ opacity: 0.9;
56
+ }
57
+
58
+ .game-area {
59
+ display: flex;
60
+ gap: 24px;
61
+ padding: 24px;
62
+ flex-wrap: wrap;
63
+ }
64
+
65
+ .board-container {
66
+ flex: 1;
67
+ min-width: 550px;
68
+ }
69
+
70
+ .board {
71
+ display: grid;
72
+ grid-template-columns: repeat(10, 1fr);
73
+ gap: 4px;
74
+ background: #0f172a;
75
+ padding: 12px;
76
+ border-radius: 16px;
77
+ margin: 20px 0;
78
+ border: 2px solid rgba(255, 255, 255, 0.05);
79
+ box-shadow: inset 0 2px 8px rgba(0,0,0,0.5);
80
+ }
81
+
82
+ .cell {
83
+ aspect-ratio: 1;
84
+ background: #1e293b;
85
+ display: flex;
86
+ align-items: center;
87
+ justify-content: center;
88
+ font-weight: bold;
89
+ font-size: 1.1em;
90
+ cursor: pointer;
91
+ position: relative;
92
+ transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
93
+ border-radius: 8px;
94
+ color: #64748b;
95
+ user-select: none;
96
+ }
97
+
98
+ .cell:hover {
99
+ background: #334155;
100
+ color: #f1f5f9;
101
+ transform: scale(1.05);
102
+ z-index: 10;
103
+ }
104
+
105
+ .cell.white-territory {
106
+ background: rgba(33, 150, 243, 0.1);
107
+ border: 1px solid rgba(33, 150, 243, 0.3);
108
+ color: #60a5fa;
109
+ }
110
+
111
+ .cell.black-territory {
112
+ background: rgba(233, 30, 99, 0.1);
113
+ border: 1px solid rgba(233, 30, 99, 0.3);
114
+ color: #f472b6;
115
+ }
116
+
117
+ .cell.possible-move {
118
+ background: rgba(16, 185, 129, 0.25) !important;
119
+ border: 2px solid #10b981;
120
+ color: #34d399;
121
+ animation: pulse 1.2s infinite;
122
+ }
123
+
124
+ @keyframes pulse {
125
+ 0 { transform: scale(1); box-shadow: 0 0 0 0 rgba(16, 185, 129, 0.4); }
126
+ 70% { transform: scale(1.03); box-shadow: 0 0 0 8px rgba(16, 185, 129, 0); }
127
+ 100% { transform: scale(1); box-shadow: 0 0 0 0 rgba(16, 185, 129, 0); }
128
+ }
129
+
130
+ .piece {
131
+ width: 85%;
132
+ height: 85%;
133
+ border-radius: 50%;
134
+ display: flex;
135
+ align-items: center;
136
+ justify-content: center;
137
+ font-weight: 800;
138
+ color: white;
139
+ text-shadow: 0 2px 4px rgba(0,0,0,0.5);
140
+ cursor: pointer;
141
+ transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
142
+ position: relative;
143
+ z-index: 5;
144
+ box-shadow: 0 4px 6px rgba(0,0,0,0.3);
145
+ }
146
+
147
+ .piece.white {
148
+ background: linear-gradient(135deg, #3b82f6, #1d4ed8);
149
+ border: 2px solid #60a5fa;
150
+ }
151
+
152
+ .piece.black {
153
+ background: linear-gradient(135deg, #ec4899, #be185d);
154
+ border: 2px solid #f472b6;
155
+ }
156
+
157
+ .piece.selected {
158
+ transform: scale(1.15);
159
+ box-shadow: 0 0 15px #f59e0b;
160
+ border-color: #f59e0b;
161
+ animation: selectionGlow 1s infinite alternate;
162
+ }
163
+
164
+ @keyframes selectionGlow {
165
+ from { box-shadow: 0 0 10px rgba(245, 158, 11, 0.5); }
166
+ to { box-shadow: 0 0 20px rgba(245, 158, 11, 0.9); }
167
+ }
168
+
169
+ .piece.white.upgraded {
170
+ background: linear-gradient(135deg, #fbbf24, #1d4ed8);
171
+ border: 2px solid #fef08a;
172
+ box-shadow: 0 0 15px rgba(59, 130, 246, 0.8);
173
+ }
174
+
175
+ .piece.black.upgraded {
176
+ background: linear-gradient(135deg, #fbbf24, #be185d);
177
+ border: 2px solid #fef08a;
178
+ box-shadow: 0 0 15px rgba(236, 72, 153, 0.8);
179
+ }
180
+
181
+ .piece.upgraded::after {
182
+ content: '★';
183
+ position: absolute;
184
+ top: -6px;
185
+ right: -6px;
186
+ font-size: 14px;
187
+ color: #fef08a;
188
+ text-shadow: 0 1px 2px rgba(0,0,0,0.8);
189
+ }
190
+
191
+ .controls {
192
+ flex: 0 0 320px;
193
+ padding: 24px;
194
+ background: rgba(15, 23, 42, 0.4);
195
+ border-radius: 16px;
196
+ display: flex;
197
+ flex-direction: column;
198
+ gap: 16px;
199
+ border: 1px solid rgba(255, 255, 255, 0.05);
200
+ }
201
+
202
+ .game-info {
203
+ background: rgba(30, 41, 59, 0.6);
204
+ padding: 16px;
205
+ border-radius: 12px;
206
+ border: 1px solid rgba(255, 255, 255, 0.05);
207
+ }
208
+
209
+ .game-info h3 {
210
+ color: #34d399;
211
+ margin-bottom: 6px;
212
+ font-size: 1.1em;
213
+ display: flex;
214
+ align-items: center;
215
+ gap: 6px;
216
+ }
217
+
218
+ .current-player {
219
+ font-size: 1.1em;
220
+ font-weight: bold;
221
+ text-align: center;
222
+ padding: 12px;
223
+ border-radius: 10px;
224
+ transition: all 0.3s ease;
225
+ letter-spacing: 1px;
226
+ box-shadow: 0 2px 4px rgba(0,0,0,0.15);
227
+ }
228
+
229
+ .current-player.white {
230
+ background: rgba(59, 130, 246, 0.15);
231
+ color: #60a5fa;
232
+ border: 1px solid rgba(59, 130, 246, 0.3);
233
+ }
234
+
235
+ .current-player.black {
236
+ background: rgba(236, 72, 153, 0.15);
237
+ color: #f472b6;
238
+ border: 1px solid rgba(236, 72, 153, 0.3);
239
+ }
240
+
241
+ .button {
242
+ background: linear-gradient(135deg, #10b981 0%, #059669 100%);
243
+ color: white;
244
+ border: none;
245
+ padding: 12px 20px;
246
+ border-radius: 12px;
247
+ cursor: pointer;
248
+ font-size: 1em;
249
+ font-weight: bold;
250
+ transition: all 0.2s ease;
251
+ width: 100%;
252
+ display: flex;
253
+ align-items: center;
254
+ justify-content: center;
255
+ gap: 8px;
256
+ box-shadow: 0 4px 6px rgba(0,0,0,0.15);
257
+ }
258
+
259
+ .button:hover {
260
+ transform: translateY(-2px);
261
+ box-shadow: 0 6px 12px rgba(16, 185, 129, 0.3);
262
+ filter: brightness(1.1);
263
+ }
264
+
265
+ .button:active {
266
+ transform: translateY(0);
267
+ }
268
+
269
+ .button:disabled {
270
+ background: #475569;
271
+ color: #94a3b8;
272
+ cursor: not-allowed;
273
+ transform: none;
274
+ box-shadow: none;
275
+ filter: none;
276
+ }
277
+
278
+ .button.secondary {
279
+ background: linear-gradient(135deg, #475569 0%, #334155 100%);
280
+ border: 1px solid rgba(255, 255, 255, 0.1);
281
+ }
282
+
283
+ .button.secondary:hover {
284
+ box-shadow: 0 6px 12px rgba(0,0,0,0.2);
285
+ }
286
+
287
+ .instructions {
288
+ background: rgba(30, 41, 59, 0.6);
289
+ padding: 16px;
290
+ border-radius: 12px;
291
+ font-size: 0.9em;
292
+ border: 1px solid rgba(255, 255, 255, 0.05);
293
+ }
294
+
295
+ .instructions h3 {
296
+ color: #38bdf8;
297
+ margin-bottom: 10px;
298
+ font-size: 1.1em;
299
+ }
300
+
301
+ .instructions ul {
302
+ list-style-type: none;
303
+ padding: 0;
304
+ display: flex;
305
+ flex-direction: column;
306
+ gap: 8px;
307
+ }
308
+
309
+ .instructions li {
310
+ padding-bottom: 6px;
311
+ border-bottom: 1px solid rgba(255, 255, 255, 0.05);
312
+ line-height: 1.4;
313
+ color: #cbd5e1;
314
+ }
315
+
316
+ .instructions li:last-child {
317
+ border-bottom: none;
318
+ padding-bottom: 0;
319
+ }
320
+
321
+ /* 彈出���窗(Mode Selection & Rules) */
322
+ .modal {
323
+ position: fixed;
324
+ top: 50%;
325
+ left: 50%;
326
+ transform: translate(-50%, -50%) scale(0.9);
327
+ background: #1e293b;
328
+ border: 1px solid rgba(255, 255, 255, 0.15);
329
+ padding: 32px;
330
+ border-radius: 20px;
331
+ box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.7);
332
+ text-align: center;
333
+ z-index: 1000;
334
+ display: none;
335
+ width: 95%;
336
+ max-width: 600px;
337
+ color: #f1f5f9;
338
+ transition: all 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
339
+ }
340
+
341
+ .modal.show {
342
+ display: block;
343
+ transform: translate(-50%, -50%) scale(1);
344
+ }
345
+
346
+ .modal h2 {
347
+ font-size: 2em;
348
+ color: #10b981;
349
+ margin-bottom: 16px;
350
+ font-weight: 800;
351
+ }
352
+
353
+ .modal-body {
354
+ text-align: left;
355
+ background: #0f172a;
356
+ padding: 20px;
357
+ border-radius: 12px;
358
+ margin-bottom: 24px;
359
+ max-height: 220px;
360
+ overflow-y: auto;
361
+ border: 1px solid rgba(255, 255, 255, 0.05);
362
+ }
363
+
364
+ .modal-body h4 {
365
+ color: #38bdf8;
366
+ margin-bottom: 8px;
367
+ }
368
+
369
+ .modal-body p {
370
+ margin-bottom: 12px;
371
+ font-size: 0.95em;
372
+ line-height: 1.5;
373
+ color: #cbd5e1;
374
+ }
375
+
376
+ .mode-selection {
377
+ display: grid;
378
+ grid-template-columns: repeat(2, 1fr);
379
+ gap: 16px;
380
+ }
381
+
382
+ .mode-btn {
383
+ padding: 16px 12px;
384
+ border-radius: 12px;
385
+ border: 2px solid rgba(255, 255, 255, 0.1);
386
+ background: #1e293b;
387
+ color: white;
388
+ cursor: pointer;
389
+ font-weight: bold;
390
+ font-size: 1.05em;
391
+ transition: all 0.2s ease;
392
+ display: flex;
393
+ flex-direction: column;
394
+ align-items: center;
395
+ gap: 8px;
396
+ }
397
+
398
+ .mode-btn:hover {
399
+ border-color: #10b981;
400
+ background: rgba(16, 185, 129, 0.1);
401
+ transform: translateY(-4px);
402
+ box-shadow: 0 4px 12px rgba(0,0,0,0.3);
403
+ }
404
+
405
+ .mode-btn .icon {
406
+ font-size: 2em;
407
+ }
408
+
409
+ /* AI 卡片式選單樣式 */
410
+ .ai-selection-list {
411
+ display: flex;
412
+ flex-direction: column;
413
+ gap: 12px;
414
+ margin-bottom: 20px;
415
+ text-align: left;
416
+ }
417
+
418
+ .ai-card {
419
+ background: rgba(15, 23, 42, 0.6);
420
+ border: 1px solid rgba(255, 255, 255, 0.08);
421
+ border-radius: 12px;
422
+ padding: 14px 18px;
423
+ cursor: pointer;
424
+ transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
425
+ display: flex;
426
+ flex-direction: column;
427
+ gap: 6px;
428
+ }
429
+
430
+ .ai-card:hover {
431
+ transform: translateY(-2px);
432
+ background: rgba(30, 41, 59, 0.8);
433
+ box-shadow: 0 10px 20px -10px rgba(0, 0, 0, 0.5);
434
+ }
435
+
436
+ .ai-card.easy {
437
+ border-left: 5px solid #10b981;
438
+ }
439
+ .ai-card.easy:hover {
440
+ border-color: #10b981;
441
+ box-shadow: 0 8px 16px -8px rgba(16, 185, 129, 0.3);
442
+ }
443
+
444
+ .ai-card.medium {
445
+ border-left: 5px solid #f59e0b;
446
+ }
447
+ .ai-card.medium:hover {
448
+ border-color: #f59e0b;
449
+ box-shadow: 0 8px 16px -8px rgba(245, 158, 11, 0.3);
450
+ }
451
+
452
+ .ai-card.hard {
453
+ border-left: 5px solid #ef4444;
454
+ }
455
+ .ai-card.hard:hover {
456
+ border-color: #ef4444;
457
+ box-shadow: 0 8px 16px -8px rgba(239, 68, 68, 0.3);
458
+ }
459
+
460
+ .ai-card-title {
461
+ font-size: 1.1em;
462
+ font-weight: 800;
463
+ color: #f8fafc;
464
+ display: flex;
465
+ align-items: center;
466
+ gap: 6px;
467
+ }
468
+
469
+ .ai-card-desc {
470
+ font-size: 0.9em;
471
+ color: #94a3b8;
472
+ line-height: 1.4;
473
+ }
474
+
475
+ .ai-card-desc b, .ai-card-strategy b {
476
+ color: #cbd5e1;
477
+ }
478
+
479
+ .ai-card-strategy {
480
+ font-size: 0.85em;
481
+ color: #64748b;
482
+ border-top: 1px solid rgba(255, 255, 255, 0.05);
483
+ padding-top: 6px;
484
+ margin-top: 2px;
485
+ }
486
+
487
+ .overlay {
488
+ position: fixed;
489
+ top: 0;
490
+ left: 0;
491
+ width: 100%;
492
+ height: 100%;
493
+ background: rgba(15, 23, 42, 0.8);
494
+ backdrop-filter: blur(8px);
495
+ -webkit-backdrop-filter: blur(8px);
496
+ z-index: 999;
497
+ display: none;
498
+ }
499
+
500
+ .overlay.show {
501
+ display: block;
502
+ }
503
+
504
+ .score-board {
505
+ display: flex;
506
+ justify-content: space-between;
507
+ margin-bottom: 15px;
508
+ gap: 16px;
509
+ }
510
+
511
+ .score {
512
+ flex: 1;
513
+ text-align: center;
514
+ padding: 12px;
515
+ border-radius: 10px;
516
+ font-weight: bold;
517
+ box-shadow: 0 4px 6px rgba(0,0,0,0.1);
518
+ }
519
+
520
+ .score.white {
521
+ background: rgba(59, 130, 246, 0.15);
522
+ color: #60a5fa;
523
+ border: 1px solid rgba(59, 130, 246, 0.3);
524
+ }
525
+
526
+ .score.black {
527
+ background: rgba(236, 72, 153, 0.15);
528
+ color: #f472b6;
529
+ border: 1px solid rgba(236, 72, 153, 0.3);
530
+ }
531
+
532
+ .score-value {
533
+ font-size: 1.8em;
534
+ font-weight: 800;
535
+ margin-top: 4px;
536
+ }
537
+
538
+ /* Toast Notification */
539
+ .toast-container {
540
+ position: fixed;
541
+ top: 24px;
542
+ right: 24px;
543
+ z-index: 2000;
544
+ display: flex;
545
+ flex-direction: column;
546
+ gap: 12px;
547
+ max-width: 350px;
548
+ }
549
+
550
+ .toast {
551
+ background: #1e293b;
552
+ color: #f1f5f9;
553
+ padding: 16px 20px;
554
+ border-radius: 12px;
555
+ border-left: 4px solid #10b981;
556
+ box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.3);
557
+ display: flex;
558
+ align-items: center;
559
+ gap: 12px;
560
+ transform: translateX(120%);
561
+ transition: all 0.3s cubic-bezier(0.16, 1, 0.3, 1);
562
+ font-weight: 500;
563
+ }
564
+
565
+ .toast.show {
566
+ transform: translateX(0);
567
+ }
568
+
569
+ .toast.info { border-left-color: #3b82f6; }
570
+ .toast.warning { border-left-color: #f59e0b; }
571
+ .toast.error { border-left-color: #ef4444; }
572
+
573
+ @media (max-width: 900px) {
574
+ .game-area {
575
+ flex-direction: column;
576
+ }
577
+
578
+ .board-container {
579
+ min-width: auto;
580
+ }
581
+
582
+ .cell {
583
+ font-size: 0.9em;
584
+ }
585
+
586
+ .piece {
587
+ font-size: 0.85em;
588
+ }
589
+ }
590
+
591
+ @media (max-width: 480px) {
592
+ body {
593
+ padding: 8px;
594
+ }
595
+ .header h1 {
596
+ font-size: 1.8em;
597
+ }
598
+ .game-area {
599
+ padding: 12px;
600
+ }
601
+ .controls {
602
+ padding: 16px;
603
+ }
604
+ .mode-selection {
605
+ grid-template-columns: 1fr;
606
+ }
607
+ }
608
+ </style>
609
+ </head>
610
+ <body>
611
+ <div class="container">
612
+ <div class="header">
613
+ <h1>🎲 數戰棋 🎲</h1>
614
+ <p>透過整除規則學習因數與倍數 - <span id="gameModeText">模式載入中</span></p>
615
+ </div>
616
+
617
+ <div class="game-area">
618
+ <div class="board-container">
619
+ <div class="score-board">
620
+ <div class="score white">
621
+ <div>藍方棋子 (玩家)</div>
622
+ <div class="score-value" id="whiteScore">10</div>
623
+ </div>
624
+ <div class="score black">
625
+ <div id="blackTitle">紅方棋子 (對手)</div>
626
+ <div class="score-value" id="blackScore">10</div>
627
+ </div>
628
+ </div>
629
+
630
+ <div class="board" id="gameBoard">
631
+ <!-- 棋盤格子會由JavaScript生成 -->
632
+ </div>
633
+
634
+ <div class="current-player" id="currentPlayer">
635
+ 藍方回合 - 選擇要移動的棋子
636
+ </div>
637
+ </div>
638
+
639
+ <div class="controls">
640
+ <div class="game-info">
641
+ <h3>🎯 遊戲目標</h3>
642
+ <p>將所有對手的棋子吃掉,或是讓對手無路可走即獲勝!</p>
643
+ </div>
644
+
645
+ <div class="instructions">
646
+ <h3>📋 遊戲規則簡介</h3>
647
+ <ul>
648
+ <li>🔵 藍方向下前進,🔴 紅方向上前進。</li>
649
+ <li>📐 普通棋子只能移動到能被「棋子自身數字」整除的相鄰列格子。</li>
650
+ <li>🍽️ 可以吃掉目標格子上的敵方棋子,<b>但不能重疊在自己同色棋子之上</b>。</li>
651
+ <li>⭐ 抵達對手底線領地升級為 <b>★ 棋子</b>,自此可任意往上或往下移動,且不受整除限制!</li>
652
+ </ul>
653
+ </div>
654
+
655
+ <button class="button" onclick="resetGame()">🔄 重新開始</button>
656
+ <button class="button secondary" onclick="switchSides()">🔀 交換執棋</button>
657
+ <button class="button secondary" onclick="showHint()">💡 顯示移動提示</button>
658
+ <button class="button secondary" onclick="showWelcomeModal()">⚙️ 切換遊戲模式</button>
659
+ </div>
660
+ </div>
661
+ </div>
662
+
663
+ <!-- 歡迎/規則模式選擇彈窗 -->
664
+ <div class="overlay" id="overlay"></div>
665
+
666
+ <div class="modal" id="welcomeModal">
667
+ <h2>🎲 歡迎來到「數戰棋」</h2>
668
+ <div class="modal-body">
669
+ <h4>💡 遊戲玩法大解析:</h4>
670
+ <p>1. <b>移動限制</b>:藍棋只能向下、紅棋只能向上(皆每次移動 1 列)。</p>
671
+ <p>2. <b>整除原理</b>:想前往的格子編號,必須要能變為你的棋子數字的「倍數」。例如:3 號棋子只能走 12、15、18 等格子。</p>
672
+ <p>3. <b>吃子限制</b>:若目標格有敵棋即可吃掉。<b>但請注意,您不能踩到自己人的棋子上喔!</b></p>
673
+ <p>4. <b>升級神將 (★)</b>:當棋子殺到對手底線時會升級,升級後突破禁忌,可自由前進或後退 1 列,並不再受整除限制!</p>
674
+ </div>
675
+
676
+ <!-- 第一階段:選擇主模式 -->
677
+ <div id="mainModeSelect">
678
+ <p style="margin-bottom: 16px; font-weight: bold; color: #cbd5e1;">請選擇您的遊玩模式:</p>
679
+ <div class="mode-selection" style="grid-template-columns: repeat(2, 1fr);">
680
+ <button class="mode-btn" onclick="selectMode('pvp')">
681
+ <span class="icon">👥</span>
682
+ <span>雙人本地對戰</span>
683
+ </button>
684
+ <button class="mode-btn" onclick="showAiDifficultySelect()">
685
+ <span class="icon">🤖</span>
686
+ <span>與 AI 對戰</span>
687
+ </button>
688
+ </div>
689
+ </div>
690
+
691
+ <!-- 第二階段:選擇 AI 對手與個性說明 -->
692
+ <div id="aiDifficultySelect" style="display: none;">
693
+ <p style="margin-bottom: 16px; font-weight: bold; color: #cbd5e1;">請點選要對抗的 AI 角色:</p>
694
+ <div class="ai-selection-list">
695
+ <!-- 簡單 AI 卡片 -->
696
+ <div class="ai-card easy" onclick="selectMode('ai_easy')">
697
+ <div class="ai-card-title">🟢 萌新嘟嘟 (簡單)</div>
698
+ <div class="ai-card-desc"><b>個性:</b>活潑好奇、粗心大意。剛學會九九乘法表,常常看錯整除方向或把棋子白白送給你吃,最喜歡盲目亂衝!</div>
699
+ <div class="ai-card-strategy"><b>策略:</b>60% 機率完全憑感覺隨機亂走;只有 40% 機率會稍微考慮往前或吃子,防守意識幾乎為零。</div>
700
+ </div>
701
+ <!-- 中等 AI 卡片 -->
702
+ <div class="ai-card medium" onclick="selectMode('ai_medium')">
703
+ <div class="ai-card-title">🟡 管家阿麥 (中等)</div>
704
+ <div class="ai-card-desc"><b>個性:</b>謹慎規矩、有條不紊。計算能力良好,知道要保護自己,但偶爾也會看漏眼犯點小迷糊。</div>
705
+ <div class="ai-card-strategy"><b>策略:</b>攻守平衡。會主動避開明顯的致命陷阱。思考時會加入些許隨機性,下棋風格非常接近一般人類玩家。</div>
706
+ </div>
707
+ <!-- 困難 AI 卡片 -->
708
+ <div class="ai-card hard" onclick="selectMode('ai_hard')">
709
+ <div class="ai-card-title">🔴 戰神諸葛墨 (困難)</div>
710
+ <div class="ai-card-desc"><b>個性:</b>冷靜沉著、算無遺策。擁有極致的數學思維與大局觀,會精準預判你的攻勢,壓迫感十足!</div>
711
+ <div class="ai-card-strategy"><b>策略:</b>精確獵殺與防守。絕不走入危險格子,一旦發現破綻便毫不留情吃子;升級後的「★」會主動展開極速獵殺與包夾。</div>
712
+ </div>
713
+ </div>
714
+ <button class="button secondary" onclick="backToMainMode()" style="width: auto; padding: 8px 16px; display: inline-flex; margin: 0 auto; gap: 4px;">⬅️ 回上一步</button>
715
+ </div>
716
+ </div>
717
+
718
+ <!-- 勝利宣告彈窗 -->
719
+ <div class="modal" id="winnerMessage">
720
+ <h2 id="winnerText"></h2>
721
+ <p style="font-size: 1.2em; margin-bottom: 24px; color: #cbd5e1;">恭喜獲勝!太厲害了 🎉</p>
722
+ <button class="button" onclick="hideWinnerMessage()">確認並繼續</button>
723
+ </div>
724
+
725
+ <!-- 自訂 Toast 提示區域 -->
726
+ <div id="toastContainer" class="toast-container"></div>
727
+
728
+ <script>
729
+ // 自訂提示元件 (代替 Alert)
730
+ function toast(message, type = 'info') {
731
+ const container = document.getElementById('toastContainer');
732
+ const toastEl = document.createElement('div');
733
+ toastEl.className = `toast ${type}`;
734
+
735
+ let emoji = 'ℹ️';
736
+ if (type === 'warning') emoji = '⚠️';
737
+ if (type === 'error') emoji = '❌';
738
+ if (type === 'success') emoji = '🎉';
739
+
740
+ toastEl.innerHTML = `<span>${emoji}</span><span>${message}</span>`;
741
+ container.appendChild(toastEl);
742
+
743
+ // 觸發進場動畫
744
+ setTimeout(() => {
745
+ toastEl.classList.add('show');
746
+ }, 50);
747
+
748
+ // 3秒後自動消失並刪除
749
+ setTimeout(() => {
750
+ toastEl.classList.remove('show');
751
+ setTimeout(() => {
752
+ toastEl.remove();
753
+ }, 300);
754
+ }, 3000);
755
+ }
756
+
757
+ class MathChessGame {
758
+ constructor() {
759
+ this.board = Array(100).fill(null);
760
+ this.currentPlayer = 'white'; // 'white' (藍) or 'black' (紅)
761
+ this.selectedPiece = null;
762
+ this.gameEnded = false;
763
+ this.whiteScore = 10;
764
+ this.blackScore = 10;
765
+ this.gameMode = 'pvp'; // 'pvp' or 'ai'
766
+ this.aiDifficulty = 'medium'; // 'easy' | 'medium' | 'hard'
767
+ this.isAiThinking = false;
768
+
769
+ this.initializeGame();
770
+ }
771
+
772
+ initializeGame() {
773
+ this.createBoard();
774
+ this.placePieces();
775
+ this.updateDisplay();
776
+ }
777
+
778
+ createBoard() {
779
+ const boardElement = document.getElementById('gameBoard');
780
+ boardElement.innerHTML = '';
781
+
782
+ for (let i = 0; i < 100; i++) {
783
+ const cell = document.createElement('div');
784
+ cell.className = 'cell';
785
+ cell.textContent = i + 1;
786
+ cell.addEventListener('click', () => this.handleCellClick(i));
787
+
788
+ // 標記領地
789
+ if (i < 10) {
790
+ cell.classList.add('white-territory');
791
+ } else if (i >= 90) {
792
+ cell.classList.add('black-territory');
793
+ }
794
+
795
+ boardElement.appendChild(cell);
796
+ }
797
+ }
798
+
799
+ placePieces() {
800
+ this.board = Array(100).fill(null);
801
+
802
+ // 放置藍方棋子(1-10位置)
803
+ for (let i = 0; i < 10; i++) {
804
+ this.board[i] = {
805
+ player: 'white',
806
+ number: i + 1,
807
+ upgraded: false
808
+ };
809
+ }
810
+
811
+ // 放置紅方棋子(91-100位置)
812
+ for (let i = 90; i < 100; i++) {
813
+ this.board[i] = {
814
+ player: 'black',
815
+ number: i - 89,
816
+ upgraded: false
817
+ };
818
+ }
819
+
820
+ this.renderPieces();
821
+ }
822
+
823
+ renderPieces() {
824
+ const cells = document.querySelectorAll('.cell');
825
+
826
+ cells.forEach((cell, index) => {
827
+ const existingPiece = cell.querySelector('.piece');
828
+ if (existingPiece) {
829
+ existingPiece.remove();
830
+ }
831
+
832
+ const piece = this.board[index];
833
+ if (piece) {
834
+ const pieceElement = document.createElement('div');
835
+ pieceElement.className = `piece ${piece.player}`;
836
+ if (piece.upgraded) {
837
+ pieceElement.classList.add('upgraded');
838
+ }
839
+ pieceElement.textContent = piece.upgraded ? '★' : piece.number;
840
+ pieceElement.addEventListener('click', (e) => {
841
+ e.stopPropagation();
842
+ this.handlePieceClick(index);
843
+ });
844
+ cell.appendChild(pieceElement);
845
+ }
846
+ });
847
+ }
848
+
849
+ handlePieceClick(position) {
850
+ if (this.gameEnded || this.isAiThinking) return;
851
+
852
+ // AI 模式下玩家不能操控 AI 的紅棋
853
+ if (this.gameMode === 'ai' && this.currentPlayer === 'black') {
854
+ return;
855
+ }
856
+
857
+ const piece = this.board[position];
858
+
859
+ // 如果已經選取了己方棋子,且點擊的是敵方(同色以外)棋子,則將其視為欲移動至該格進行「吃子」!
860
+ if (this.selectedPiece !== null && piece && piece.player !== this.currentPlayer) {
861
+ this.handleCellClick(position);
862
+ return;
863
+ }
864
+
865
+ if (!piece || piece.player !== this.currentPlayer) return;
866
+
867
+ this.clearSelection();
868
+
869
+ this.selectedPiece = position;
870
+ const pieceElement = document.querySelectorAll('.cell')[position].querySelector('.piece');
871
+ if (pieceElement) {
872
+ pieceElement.classList.add('selected');
873
+ }
874
+
875
+ this.showPossibleMoves(position);
876
+ this.updateCurrentPlayerDisplay('選擇移動目標');
877
+ }
878
+
879
+ handleCellClick(position) {
880
+ if (this.gameEnded || this.selectedPiece === null || this.isAiThinking) return;
881
+
882
+ if (this.isValidMove(this.selectedPiece, position)) {
883
+ this.makeMove(this.selectedPiece, position);
884
+ this.clearSelection();
885
+
886
+ if (this.checkGameEnd()) return;
887
+
888
+ this.switchPlayer();
889
+ } else {
890
+ toast('該位置不符合移動或整除規則,或已有己方棋子!', 'warning');
891
+ }
892
+ }
893
+
894
+ isValidMove(from, to) {
895
+ const piece = this.board[from];
896
+ if (!piece) return false;
897
+
898
+ // 檢查目標格是否已有己方(同色)棋子。如果有,則禁止移動!
899
+ const targetPiece = this.board[to];
900
+ if (targetPiece && targetPiece.player === piece.player) {
901
+ return false;
902
+ }
903
+
904
+ const fromRow = Math.floor(from / 10);
905
+ const toRow = Math.floor(to / 10);
906
+
907
+ // 1. 如果棋子已升級,可任意往上或往下移動一格 (列距為 1) 且不受整除限制
908
+ if (piece.upgraded) {
909
+ return Math.abs(toRow - fromRow) === 1;
910
+ }
911
+
912
+ // 2. 未升級棋子的前行方向檢查
913
+ if (piece.player === 'white') {
914
+ // 藍方向下
915
+ if (toRow !== fromRow + 1) return false;
916
+ } else {
917
+ // 紅方向上
918
+ if (toRow !== fromRow - 1) return false;
919
+ }
920
+
921
+ // 3. 未升級棋子的整除規則 (1-based index)
922
+ const targetNumber = to + 1;
923
+ return targetNumber % piece.number === 0;
924
+ }
925
+
926
+ showPossibleMoves(position) {
927
+ const piece = this.board[position];
928
+ if (!piece) return;
929
+
930
+ const currentRow = Math.floor(position / 10);
931
+
932
+ // 如果是已升級棋子,需要同時檢查上一列與下一列
933
+ if (piece.upgraded) {
934
+ const adjacentRows = [currentRow - 1, currentRow + 1];
935
+ adjacentRows.forEach(targetRow => {
936
+ if (targetRow >= 0 && targetRow < 10) {
937
+ for (let col = 0; col < 10; col++) {
938
+ const targetPosition = targetRow * 10 + col;
939
+ if (this.isValidMove(position, targetPosition)) {
940
+ const cell = document.querySelectorAll('.cell')[targetPosition];
941
+ cell.classList.add('possible-move');
942
+ }
943
+ }
944
+ }
945
+ });
946
+ return;
947
+ }
948
+
949
+ // 未升級棋子原本的邏輯
950
+ let targetRow = (piece.player === 'white') ? currentRow + 1 : currentRow - 1;
951
+ if (targetRow < 0 || targetRow >= 10) return;
952
+
953
+ for (let col = 0; col < 10; col++) {
954
+ const targetPosition = targetRow * 10 + col;
955
+ if (this.isValidMove(position, targetPosition)) {
956
+ const cell = document.querySelectorAll('.cell')[targetPosition];
957
+ cell.classList.add('possible-move');
958
+ }
959
+ }
960
+ }
961
+
962
+ makeMove(from, to) {
963
+ const piece = this.board[from];
964
+ const targetPiece = this.board[to];
965
+
966
+ // 如果目標位置有對方棋子,吃掉它
967
+ if (targetPiece && targetPiece.player !== piece.player) {
968
+ if (targetPiece.player === 'white') {
969
+ this.whiteScore--;
970
+ toast(`紅方吃掉了藍方的 ${targetPiece.upgraded ? '★' : targetPiece.number} 號棋子!`, 'error');
971
+ } else {
972
+ this.blackScore--;
973
+ toast(`藍方吃掉了紅方的 ${targetPiece.upgraded ? '★' : targetPiece.number} 號棋子!`, 'success');
974
+ }
975
+ }
976
+
977
+ // 移動棋子
978
+ this.board[to] = piece;
979
+ this.board[from] = null;
980
+
981
+ // 檢查是否升級成 ★
982
+ const targetRow = Math.floor(to / 10);
983
+ if (piece.player === 'white' && targetRow >= 9 && !piece.upgraded) {
984
+ piece.upgraded = true;
985
+ toast('藍方棋子成功抵達底線,升級為超級「★」將軍!', 'success');
986
+ } else if (piece.player === 'black' && targetRow <= 0 && !piece.upgraded) {
987
+ piece.upgraded = true;
988
+ toast('紅方棋子成功抵達頂線,升級為超級「★」將軍!', 'error');
989
+ }
990
+
991
+ this.renderPieces();
992
+ this.updateScoreDisplay();
993
+ }
994
+
995
+ clearSelection() {
996
+ this.selectedPiece = null;
997
+
998
+ document.querySelectorAll('.piece.selected').forEach(piece => {
999
+ piece.classList.remove('selected');
1000
+ });
1001
+
1002
+ document.querySelectorAll('.cell.possible-move').forEach(cell => {
1003
+ cell.classList.remove('possible-move');
1004
+ });
1005
+ }
1006
+
1007
+ switchPlayer() {
1008
+ this.currentPlayer = this.currentPlayer === 'white' ? 'black' : 'white';
1009
+ this.updateCurrentPlayerDisplay();
1010
+
1011
+ // 如果切換到紅方,且此時是 AI 模式,觸發 AI 計算與行動
1012
+ if (this.gameMode === 'ai' && this.currentPlayer === 'black' && !this.gameEnded) {
1013
+ this.triggerAiMove();
1014
+ }
1015
+ }
1016
+
1017
+ triggerAiMove() {
1018
+ this.isAiThinking = true;
1019
+ this.updateCurrentPlayerDisplay('AI 正在思考棋步...');
1020
+
1021
+ // 模擬 AI 思考時間 (800ms)
1022
+ setTimeout(() => {
1023
+ if (this.gameEnded) return;
1024
+
1025
+ const bestMove = this.calculateBestAiMove();
1026
+ if (bestMove) {
1027
+ this.makeMove(bestMove.from, bestMove.to);
1028
+ this.clearSelection();
1029
+
1030
+ if (this.checkGameEnd()) {
1031
+ this.isAiThinking = false;
1032
+ return;
1033
+ }
1034
+ } else {
1035
+ // AI 無路可走,判定玩家勝出
1036
+ this.endGame('藍方 (玩家)');
1037
+ this.isAiThinking = false;
1038
+ return;
1039
+ }
1040
+
1041
+ this.isAiThinking = false;
1042
+ this.switchPlayer();
1043
+ }, 800);
1044
+ }
1045
+
1046
+ // AI 智慧難度決策演算法
1047
+ calculateBestAiMove() {
1048
+ const possibleMoves = [];
1049
+
1050
+ // 1. 蒐集所有可能合法的紅方棋步
1051
+ for (let from = 0; from < 100; from++) {
1052
+ const piece = this.board[from];
1053
+ if (piece && piece.player === 'black') {
1054
+ for (let to = 0; to < 100; to++) {
1055
+ if (this.isValidMove(from, to)) {
1056
+ possibleMoves.push({ from, to, piece });
1057
+ }
1058
+ }
1059
+ }
1060
+ }
1061
+
1062
+ if (possibleMoves.length === 0) return null;
1063
+
1064
+ // 【重要修正:隨機洗牌機制】
1065
+ // 先隨機打亂所有合法的棋步,確保當多個棋步具有「相同最大估值」時,
1066
+ // 能隨機選出一個,完美解決 AI 單一棋子(如1號棋)重覆走到底的問題。
1067
+ for (let i = possibleMoves.length - 1; i > 0; i--) {
1068
+ const j = Math.floor(Math.random() * (i + 1));
1069
+ const temp = possibleMoves[i];
1070
+ possibleMoves[i] = possibleMoves[j];
1071
+ possibleMoves[j] = temp;
1072
+ }
1073
+
1074
+ // ==================== 簡單模式 (萌新嘟嘟) ====================
1075
+ if (this.aiDifficulty === 'easy') {
1076
+ // 60% 機率完全亂走隨機棋步(此處可以直接選洗牌後的第1個步子)
1077
+ if (Math.random() < 0.6) {
1078
+ return possibleMoves[0];
1079
+ }
1080
+ // 40% 機率執行只看「吃子」和「前進」的超基礎評估
1081
+ const scoredMoves = possibleMoves.map(move => {
1082
+ let score = 0;
1083
+ const targetPiece = this.board[move.to];
1084
+ if (targetPiece && targetPiece.player === 'white') {
1085
+ score += 100; // 單純有子吃就吃
1086
+ }
1087
+ const fromRow = Math.floor(move.from / 10);
1088
+ const toRow = Math.floor(move.to / 10);
1089
+ score += (fromRow - toRow) * 10; // 往前走加分
1090
+ return { ...move, score };
1091
+ });
1092
+ scoredMoves.sort((a, b) => b.score - a.score);
1093
+ return scoredMoves[0];
1094
+ }
1095
+
1096
+ // ==================== 中等模式 (管家阿麥) ====================
1097
+ if (this.aiDifficulty === 'medium') {
1098
+ const scoredMoves = possibleMoves.map(move => {
1099
+ let score = 0;
1100
+ const targetPiece = this.board[move.to];
1101
+
1102
+ // A. 吃子加分
1103
+ if (targetPiece && targetPiece.player === 'white') {
1104
+ score += 200;
1105
+ score += targetPiece.upgraded ? 100 : targetPiece.number * 5;
1106
+ }
1107
+
1108
+ // B. 達底線升級獎勵
1109
+ const toRow = Math.floor(move.to / 10);
1110
+ if (!move.piece.upgraded && toRow === 0) {
1111
+ score += 150;
1112
+ }
1113
+
1114
+ // C. 避險評估 (防守:走完是否會立刻被對方吃?)
1115
+ const tempOriginal = this.board[move.to];
1116
+ this.board[move.to] = move.piece;
1117
+ this.board[move.from] = null;
1118
+
1119
+ let isThreatened = false;
1120
+ for (let pFrom = 0; pFrom < 100; pFrom++) {
1121
+ const pPiece = this.board[pFrom];
1122
+ if (pPiece && pPiece.player === 'white') {
1123
+ if (this.isValidMove(pFrom, move.to)) {
1124
+ isThreatened = true;
1125
+ break;
1126
+ }
1127
+ }
1128
+ }
1129
+ // 復原
1130
+ this.board[move.from] = move.piece;
1131
+ this.board[move.to] = tempOriginal;
1132
+
1133
+ if (isThreatened) {
1134
+ score -= 80; // 扣分以避免危險
1135
+ }
1136
+
1137
+ // D. 前進與追逐
1138
+ if (!move.piece.upgraded) {
1139
+ const fromRow = Math.floor(move.from / 10);
1140
+ score += (fromRow - toRow) * 10;
1141
+ } else {
1142
+ // 升級後的棋子,縮短與最近敵棋的距離
1143
+ let minDistance = 100;
1144
+ for (let i = 0; i < 100; i++) {
1145
+ const p = this.board[i];
1146
+ if (p && p.player === 'white') {
1147
+ const dist = Math.abs(Math.floor(move.to / 10) - Math.floor(i / 10)) + Math.abs((move.to % 10) - (i % 10));
1148
+ if (dist < minDistance) minDistance = dist;
1149
+ }
1150
+ }
1151
+ score += (10 - minDistance) * 4;
1152
+ }
1153
+
1154
+ // E. 雜訊 (使 AI 有時會做非最優的選擇,顯得更自然)
1155
+ score += Math.random() * 20;
1156
+
1157
+ return { ...move, score };
1158
+ });
1159
+
1160
+ scoredMoves.sort((a, b) => b.score - a.score);
1161
+ return scoredMoves[0];
1162
+ }
1163
+
1164
+ // ==================== 困難模式 (戰神諸葛墨) ====================
1165
+ if (this.aiDifficulty === 'hard') {
1166
+ const scoredMoves = possibleMoves.map(move => {
1167
+ let score = 0;
1168
+ const targetPiece = this.board[move.to];
1169
+ const fromRow = Math.floor(move.from / 10);
1170
+ const toRow = Math.floor(move.to / 10);
1171
+
1172
+ // A. 極高權重的獵殺獎勵
1173
+ if (targetPiece && targetPiece.player === 'white') {
1174
+ score += 350; // 吃子基礎分
1175
+ score += targetPiece.upgraded ? 250 : targetPiece.number * 12; // 優先吃高價值棋子 (如 ★ 或 10 號)
1176
+ }
1177
+
1178
+ // B. 追求升級的高權重
1179
+ if (!move.piece.upgraded && toRow === 0) {
1180
+ score += 250;
1181
+ }
1182
+
1183
+ // C. 嚴格且深度的避險評估
1184
+ const tempOriginal = this.board[move.to];
1185
+ this.board[move.to] = move.piece;
1186
+ this.board[move.from] = null;
1187
+
1188
+ // 1. 走完之後新位置是否會被吃?
1189
+ let isThreatenedAfterMove = false;
1190
+ for (let pFrom = 0; pFrom < 100; pFrom++) {
1191
+ const pPiece = this.board[pFrom];
1192
+ if (pPiece && pPiece.player === 'white') {
1193
+ if (this.isValidMove(pFrom, move.to)) {
1194
+ isThreatenedAfterMove = true;
1195
+ break;
1196
+ }
1197
+ }
1198
+ }
1199
+
1200
+ // 2. 原來的位置是否本來就處於危險中?
1201
+ let isThreatenedBeforeMove = false;
1202
+ for (let pFrom = 0; pFrom < 100; pFrom++) {
1203
+ const pPiece = this.board[pFrom];
1204
+ if (pPiece && pPiece.player === 'white') {
1205
+ if (this.isValidMove(pFrom, move.from)) {
1206
+ isThreatenedBeforeMove = true;
1207
+ break;
1208
+ }
1209
+ }
1210
+ }
1211
+
1212
+ // 復原
1213
+ this.board[move.from] = move.piece;
1214
+ this.board[move.to] = tempOriginal;
1215
+
1216
+ // 懲罰:嚴厲懲罰將棋子暴露給敵方的走法(除非是以小吃大、高價值交換)
1217
+ if (isThreatenedAfterMove) {
1218
+ const myValue = move.piece.upgraded ? 300 : move.piece.number * 10;
1219
+ const targetValue = targetPiece ? (targetPiece.upgraded ? 400 : targetPiece.number * 15) : 0;
1220
+ score -= (myValue - targetValue + 350);
1221
+ }
1222
+
1223
+ // 逃跑獎勵:本來危險,走這步能逃到安全點
1224
+ if (isThreatenedBeforeMove && !isThreatenedAfterMove) {
1225
+ score += 150;
1226
+ }
1227
+
1228
+ // D. 最優路徑追逐
1229
+ if (!move.piece.upgraded) {
1230
+ score += (fromRow - toRow) * 15;
1231
+ } else {
1232
+ // 升級將軍 (★) 追殺玩家高價值棋子
1233
+ let bestTargetDist = 100;
1234
+ let bestTargetValue = 0;
1235
+ for (let i = 0; i < 100; i++) {
1236
+ const p = this.board[i];
1237
+ if (p && p.player === 'white') {
1238
+ const dist = Math.abs(toRow - Math.floor(i / 10)) + Math.abs((move.to % 10) - (i % 10));
1239
+ const val = p.upgraded ? 300 : p.number * 10;
1240
+ if (dist < bestTargetDist) {
1241
+ bestTargetDist = dist;
1242
+ bestTargetValue = val;
1243
+ }
1244
+ }
1245
+ }
1246
+ score += (10 - bestTargetDist) * 8 + (bestTargetValue * 0.1);
1247
+ }
1248
+
1249
+ // 零隨機雜訊,完全走數學最優解
1250
+ return { ...move, score };
1251
+ });
1252
+
1253
+ scoredMoves.sort((a, b) => b.score - a.score);
1254
+ return scoredMoves[0];
1255
+ }
1256
+ }
1257
+
1258
+ updateCurrentPlayerDisplay(customAction = null) {
1259
+ const playerDisplay = document.getElementById('currentPlayer');
1260
+ let playerName = this.currentPlayer === 'white' ? '藍方' : '紅方';
1261
+
1262
+ if (this.gameMode === 'ai' && this.currentPlayer === 'black') {
1263
+ let diffZh = '管家阿麥';
1264
+ if (this.aiDifficulty === 'easy') diffZh = '萌新嘟嘟';
1265
+ if (this.aiDifficulty === 'hard') diffZh = '戰神諸葛墨';
1266
+ playerName = `智慧對手【${diffZh}】`;
1267
+ }
1268
+
1269
+ if (customAction) {
1270
+ playerDisplay.textContent = customAction;
1271
+ } else {
1272
+ playerDisplay.textContent = `${playerName}回合 - 選擇要移動的棋子`;
1273
+ }
1274
+
1275
+ playerDisplay.className = `current-player ${this.currentPlayer}`;
1276
+ }
1277
+
1278
+ updateScoreDisplay() {
1279
+ document.getElementById('whiteScore').textContent = this.whiteScore;
1280
+ document.getElementById('blackScore').textContent = this.blackScore;
1281
+ }
1282
+
1283
+ updateDisplay() {
1284
+ this.updateCurrentPlayerDisplay();
1285
+ this.updateScoreDisplay();
1286
+
1287
+ // 更改標題及介面文字
1288
+ const modeText = document.getElementById('gameModeText');
1289
+ const blackTitle = document.getElementById('blackTitle');
1290
+ if (this.gameMode === 'ai') {
1291
+ let diffZh = '管家阿麥';
1292
+ if (this.aiDifficulty === 'easy') diffZh = '萌新嘟嘟';
1293
+ if (this.aiDifficulty === 'hard') diffZh = '戰神諸葛墨';
1294
+ modeText.textContent = `🤖 對戰【${diffZh}】`;
1295
+ blackTitle.textContent = `紅方棋子 (${diffZh})`;
1296
+ } else {
1297
+ modeText.textContent = '👥 雙人本地對戰';
1298
+ blackTitle.textContent = '紅方棋子 (玩家)';
1299
+ }
1300
+ }
1301
+
1302
+ checkGameEnd() {
1303
+ if (this.whiteScore === 0) {
1304
+ let winnerName = '紅方';
1305
+ if (this.gameMode === 'ai') {
1306
+ let diffZh = '管家阿麥';
1307
+ if (this.aiDifficulty === 'easy') diffZh = '萌新嘟嘟';
1308
+ if (this.aiDifficulty === 'hard') diffZh = '戰神諸葛墨';
1309
+ winnerName = `智慧對手【${diffZh}】`;
1310
+ }
1311
+ this.endGame(winnerName);
1312
+ return true;
1313
+ } else if (this.blackScore === 0) {
1314
+ this.endGame('藍方 (玩家)');
1315
+ return true;
1316
+ }
1317
+ return false;
1318
+ }
1319
+
1320
+ endGame(winner) {
1321
+ this.gameEnded = true;
1322
+ document.getElementById('winnerText').textContent = `${winner} 榮獲勝利!`;
1323
+ document.getElementById('overlay').classList.add('show');
1324
+ document.getElementById('winnerMessage').classList.add('show');
1325
+ }
1326
+
1327
+ reset() {
1328
+ this.gameEnded = false;
1329
+ this.currentPlayer = 'white';
1330
+ this.selectedPiece = null;
1331
+ this.whiteScore = 10;
1332
+ this.blackScore = 10;
1333
+ this.isAiThinking = false;
1334
+ this.clearSelection();
1335
+ this.placePieces();
1336
+ this.updateDisplay();
1337
+ toast('遊戲已重置,藍方先手!', 'info');
1338
+ }
1339
+
1340
+ switchSides() {
1341
+ if (this.isAiThinking) return;
1342
+
1343
+ // 交換所有棋子的位置與對應陣營
1344
+ const newBoard = Array(100).fill(null);
1345
+
1346
+ for (let i = 0; i < 100; i++) {
1347
+ const piece = this.board[i];
1348
+ if (piece) {
1349
+ const newPosition = 99 - i;
1350
+ newBoard[newPosition] = {
1351
+ player: piece.player === 'white' ? 'black' : 'white',
1352
+ number: piece.number,
1353
+ upgraded: piece.upgraded
1354
+ };
1355
+ }
1356
+ }
1357
+
1358
+ this.board = newBoard;
1359
+ // 交換分數
1360
+ const tempScore = this.whiteScore;
1361
+ this.whiteScore = this.blackScore;
1362
+ this.blackScore = tempScore;
1363
+
1364
+ this.currentPlayer = this.currentPlayer === 'white' ? 'black' : 'white';
1365
+ this.clearSelection();
1366
+ this.renderPieces();
1367
+ this.updateDisplay();
1368
+
1369
+ toast('雙方交換陣營!已重新整理戰局', 'success');
1370
+
1371
+ // 如果交換完輪到 AI
1372
+ if (this.gameMode === 'ai' && this.currentPlayer === 'black' && !this.gameEnded) {
1373
+ this.triggerAiMove();
1374
+ }
1375
+ }
1376
+ }
1377
+
1378
+ // 全局遊戲實例
1379
+ let game = new MathChessGame();
1380
+
1381
+ // 模式選擇與引導流動
1382
+ window.addEventListener('DOMContentLoaded', () => {
1383
+ showWelcomeModal();
1384
+ });
1385
+
1386
+ function showWelcomeModal() {
1387
+ document.getElementById('overlay').classList.add('show');
1388
+ document.getElementById('welcomeModal').classList.add('show');
1389
+ // 每次重新呼叫模式選擇時,都確保預設顯示第一階段 (主模式)
1390
+ document.getElementById('mainModeSelect').style.display = 'block';
1391
+ document.getElementById('aiDifficultySelect').style.display = 'none';
1392
+ }
1393
+
1394
+ function showAiDifficultySelect() {
1395
+ document.getElementById('mainModeSelect').style.display = 'none';
1396
+ document.getElementById('aiDifficultySelect').style.display = 'block';
1397
+ }
1398
+
1399
+ function backToMainMode() {
1400
+ document.getElementById('mainModeSelect').style.display = 'block';
1401
+ document.getElementById('aiDifficultySelect').style.display = 'none';
1402
+ }
1403
+
1404
+ function selectMode(mode) {
1405
+ if (mode === 'pvp') {
1406
+ game.gameMode = 'pvp';
1407
+ } else {
1408
+ game.gameMode = 'ai';
1409
+ if (mode === 'ai_easy') game.aiDifficulty = 'easy';
1410
+ if (mode === 'ai_medium') game.aiDifficulty = 'medium';
1411
+ if (mode === 'ai_hard') game.aiDifficulty = 'hard';
1412
+ }
1413
+ hideWelcomeModal();
1414
+ game.reset();
1415
+ }
1416
+
1417
+ function hideWelcomeModal() {
1418
+ document.getElementById('overlay').classList.remove('show');
1419
+ document.getElementById('welcomeModal').classList.remove('show');
1420
+ }
1421
+
1422
+ function resetGame() {
1423
+ game.reset();
1424
+ }
1425
+
1426
+ function switchSides() {
1427
+ game.switchSides();
1428
+ }
1429
+
1430
+ function showHint() {
1431
+ if (game.isAiThinking) return;
1432
+
1433
+ const piece = game.board[game.selectedPiece];
1434
+ if (!piece) {
1435
+ toast('請先在棋盤上選擇您的一個棋子!', 'warning');
1436
+ return;
1437
+ }
1438
+
1439
+ let hint = `您選擇的 ${piece.number} 號棋,可以移動到下方(目標格編號能被 ${piece.number} 整除)的格子。\n`;
1440
+ hint += `例如:${piece.number}、${piece.number * 2}、${piece.number * 3} ... 的位置。`;
1441
+
1442
+ if (piece.upgraded) {
1443
+ hint = '此棋已升級!可以無視整除限制,自由往「上」或「下」一列的任意位置移動!';
1444
+ }
1445
+
1446
+ toast(hint, 'info');
1447
+ }
1448
+
1449
+ function hideWinnerMessage() {
1450
+ document.getElementById('overlay').classList.remove('show');
1451
+ document.getElementById('winnerMessage').classList.remove('show');
1452
+ game.reset();
1453
+ }
1454
+ </script>
1455
+ </body>
1456
+ </html>