ek15072809 commited on
Commit
58a896d
ยท
verified ยท
1 Parent(s): 7870a7c

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +366 -19
index.html CHANGED
@@ -1,19 +1,366 @@
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="ja">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Block Blast Solver</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <style>
9
+ .grid-cell {
10
+ aspect-ratio: 1 / 1;
11
+ transition: all 0.2s;
12
+ display: flex;
13
+ align-items: center;
14
+ justify-content: center;
15
+ font-weight: bold;
16
+ color: white;
17
+ font-size: 1.2rem;
18
+ text-shadow: 1px 1px 2px rgba(0,0,0,0.5);
19
+ }
20
+ .cell-empty { background-color: #e5e7eb; border: 1px solid #d1d5db; }
21
+ .cell-filled { background-color: #4b5563; border: 1px solid #374151; }
22
+ .cell-preview-1 { background-color: #fbbf24; border: 2px solid #d97706; }
23
+ .cell-preview-2 { background-color: #f59e0b; border: 2px solid #b45309; }
24
+ .cell-preview-3 { background-color: #d97706; border: 2px solid #92400e; }
25
+
26
+ .piece-editor-grid {
27
+ display: grid;
28
+ grid-template-columns: repeat(5, 1fr);
29
+ gap: 2px;
30
+ width: 120px;
31
+ background-color: #f3f4f6;
32
+ padding: 4px;
33
+ border-radius: 8px;
34
+ }
35
+ .mini-cell {
36
+ aspect-ratio: 1 / 1;
37
+ border-radius: 2px;
38
+ cursor: pointer;
39
+ }
40
+ .mini-empty { background-color: #ffffff; border: 1px solid #e5e7eb; }
41
+ .mini-filled { background-color: #6366f1; border: 1px solid #4338ca; }
42
+ </style>
43
+ </head>
44
+ <body class="bg-slate-100 min-h-screen p-4 md:p-8 font-sans">
45
+
46
+ <div class="max-w-6xl mx-auto bg-white rounded-2xl shadow-xl overflow-hidden">
47
+ <div class="bg-indigo-600 p-6 text-white text-center">
48
+ <h1 class="text-2xl font-bold italic uppercase tracking-wider">BLOCK BLAST SOLVER</h1>
49
+ </div>
50
+
51
+ <div class="p-6 grid grid-cols-1 lg:grid-cols-12 gap-8">
52
+ <div class="lg:col-span-7">
53
+ <h2 class="text-lg font-semibold mb-4 flex items-center">
54
+ <span class="bg-indigo-100 text-indigo-600 w-6 h-6 rounded-full flex items-center justify-center mr-2 text-sm">1</span>
55
+ ็พๅœจใฎ็›ค้ขใ‚’ๅ…ฅๅŠ›
56
+ </h2>
57
+ <div id="game-grid" class="grid grid-cols-8 gap-1 bg-gray-300 p-2 rounded-xl shadow-inner border-4 border-gray-400">
58
+ <!-- JS generates 64 cells -->
59
+ </div>
60
+ <div class="flex justify-between mt-4 items-center">
61
+ <button id="clear-grid" class="px-4 py-2 bg-white border border-gray-300 rounded-lg text-sm font-medium text-gray-600 hover:bg-gray-50">
62
+ ็›ค้ขใ‚’ใƒชใ‚ปใƒƒใƒˆ
63
+ </button>
64
+ </div>
65
+ </div>
66
+
67
+ <div class="lg:col-span-5 space-y-4">
68
+ <h2 class="text-lg font-semibold mb-2 flex items-center">
69
+ <span class="bg-indigo-100 text-indigo-600 w-6 h-6 rounded-full flex items-center justify-center mr-2 text-sm">2</span>
70
+ ๆŒใก้ง’ใ‚’ๅ…ฅๅŠ›
71
+ </h2>
72
+
73
+ <div class="grid grid-cols-3 lg:grid-cols-1 gap-4">
74
+ <div class="bg-slate-50 p-3 rounded-xl border border-slate-200 flex flex-col items-center">
75
+ <span class="text-[10px] font-bold text-slate-400 mb-1 uppercase">Piece A</span>
76
+ <div id="piece-editor-0" class="piece-editor-grid"></div>
77
+ <button onclick="clearPiece(0)" class="mt-1 text-[10px] text-indigo-500">CLEAR</button>
78
+ </div>
79
+ <div class="bg-slate-50 p-3 rounded-xl border border-slate-200 flex flex-col items-center">
80
+ <span class="text-[10px] font-bold text-slate-400 mb-1 uppercase">Piece B</span>
81
+ <div id="piece-editor-1" class="piece-editor-grid"></div>
82
+ <button onclick="clearPiece(1)" class="mt-1 text-[10px] text-indigo-500">CLEAR</button>
83
+ </div>
84
+ <div class="bg-slate-50 p-3 rounded-xl border border-slate-200 flex flex-col items-center">
85
+ <span class="text-[10px] font-bold text-slate-400 mb-1 uppercase">Piece C</span>
86
+ <div id="piece-editor-2" class="piece-editor-grid"></div>
87
+ <button onclick="clearPiece(2)" class="mt-1 text-[10px] text-indigo-500">CLEAR</button>
88
+ </div>
89
+ </div>
90
+
91
+ <div class="pt-4 border-t space-y-3">
92
+ <button id="solve-btn" class="w-full bg-indigo-600 hover:bg-indigo-700 text-white font-bold py-4 rounded-2xl shadow-lg transition-all transform active:scale-95 text-lg">
93
+ ๆœ€้ฉใƒซใƒผใƒˆใ‚’็ฎ—ๅ‡บ
94
+ </button>
95
+
96
+ <button id="apply-btn" disabled class="w-full bg-emerald-600 hover:bg-emerald-700 disabled:bg-gray-300 disabled:cursor-not-allowed text-white font-bold py-4 rounded-2xl shadow-lg transition-all transform active:scale-95 text-lg">
97
+ ้…็ฝฎใ‚’็ขบๅฎšใ—ใฆๆฌกใธ
98
+ </button>
99
+
100
+ <div id="status-message" class="p-4 rounded-xl text-center text-sm font-medium border min-h-[80px] flex items-center justify-center leading-relaxed">
101
+ ็›ค้ขใจๅฐ‘ใชใใจใ‚‚1ใคใฎ้ง’ใ‚’ๆใ„ใฆใใ ใ•ใ„
102
+ </div>
103
+ </div>
104
+ </div>
105
+ </div>
106
+ </div>
107
+
108
+ <script>
109
+ const GRID_SIZE = 8;
110
+ const MINI_SIZE = 5;
111
+ let grid = Array(GRID_SIZE).fill().map(() => Array(GRID_SIZE).fill(0));
112
+ let piecesRaw = Array(3).fill().map(() => Array(MINI_SIZE).fill().map(() => Array(MINI_SIZE).fill(0)));
113
+ let currentBestSequence = null;
114
+
115
+ // --- UI ---
116
+ const gridEl = document.getElementById('game-grid');
117
+ function initBoard() {
118
+ gridEl.innerHTML = '';
119
+ for (let r = 0; r < GRID_SIZE; r++) {
120
+ for (let c = 0; c < GRID_SIZE; c++) {
121
+ const cell = document.createElement('div');
122
+ cell.className = `grid-cell rounded cursor-pointer ${grid[r][c] ? 'cell-filled' : 'cell-empty'}`;
123
+ cell.dataset.r = r; cell.dataset.c = c;
124
+ cell.onclick = () => { grid[r][c] = grid[r][c] ? 0 : 1; renderBoard(); };
125
+ gridEl.appendChild(cell);
126
+ }
127
+ }
128
+ }
129
+
130
+ function renderBoard(previews = []) {
131
+ const cells = gridEl.children;
132
+ for (let i = 0; i < cells.length; i++) {
133
+ const r = parseInt(cells[i].dataset.r);
134
+ const c = parseInt(cells[i].dataset.c);
135
+ cells[i].className = 'grid-cell rounded cursor-pointer';
136
+ cells[i].innerText = '';
137
+
138
+ if (grid[r][c]) {
139
+ cells[i].classList.add('cell-filled');
140
+ } else {
141
+ let pIdx = previews.findIndex(p => p.coords.some(coord => coord[0] === r && coord[1] === c));
142
+ if (pIdx !== -1) {
143
+ cells[i].classList.add(`cell-preview-${pIdx + 1}`);
144
+ cells[i].innerText = (pIdx + 1);
145
+ } else {
146
+ cells[i].classList.add('cell-empty');
147
+ }
148
+ }
149
+ }
150
+ }
151
+
152
+ function initPieceEditors() {
153
+ for (let i = 0; i < 3; i++) {
154
+ const container = document.getElementById(`piece-editor-${i}`);
155
+ container.innerHTML = '';
156
+ for (let r = 0; r < MINI_SIZE; r++) {
157
+ for (let c = 0; c < MINI_SIZE; c++) {
158
+ const cell = document.createElement('div');
159
+ cell.className = `mini-cell ${piecesRaw[i][r][c] ? 'mini-filled' : 'mini-empty'}`;
160
+ cell.onclick = () => { piecesRaw[i][r][c] = piecesRaw[i][r][c] ? 0 : 1; renderPieceEditor(i); };
161
+ container.appendChild(cell);
162
+ }
163
+ }
164
+ }
165
+ }
166
+
167
+ function renderPieceEditor(index) {
168
+ const container = document.getElementById(`piece-editor-${index}`);
169
+ const cells = container.children;
170
+ for (let i = 0; i < 25; i++) {
171
+ const r = Math.floor(i / 5); const c = i % 5;
172
+ cells[i].className = `mini-cell ${piecesRaw[index][r][c] ? 'mini-filled' : 'mini-empty'}`;
173
+ }
174
+ }
175
+
176
+ function clearPiece(index) {
177
+ piecesRaw[index] = Array(MINI_SIZE).fill().map(() => Array(MINI_SIZE).fill(0));
178
+ renderPieceEditor(index);
179
+ }
180
+
181
+ function getPiecePoints(index) {
182
+ const pts = []; let minR = 5, minC = 5;
183
+ for (let r = 0; r < 5; r++) {
184
+ for (let c = 0; c < 5; c++) {
185
+ if (piecesRaw[index][r][c]) {
186
+ pts.push([r, c]); minR = Math.min(minR, r); minC = Math.min(minC, c);
187
+ }
188
+ }
189
+ }
190
+ if (pts.length === 0) return null;
191
+ return pts.map(p => [p[0] - minR, p[1] - minC]);
192
+ }
193
+
194
+ function canPlace(board, piece, r, c) {
195
+ for (let [pr, pc] of piece) {
196
+ const nr = r + pr, nc = c + pc;
197
+ if (nr < 0 || nr >= 8 || nc < 0 || nc >= 8 || board[nr][nc]) return false;
198
+ }
199
+ return true;
200
+ }
201
+
202
+ function applyPlacement(board, piece, r, c) {
203
+ const newBoard = board.map(row => [...row]);
204
+ piece.forEach(([pr, pc]) => newBoard[r + pr][c + pc] = 1);
205
+ let rows = [], cols = [];
206
+ for (let i = 0; i < 8; i++) {
207
+ if (newBoard[i].every(v => v === 1)) rows.push(i);
208
+ let fullCol = true;
209
+ for(let j=0; j<8; j++) if(newBoard[j][i] === 0) { fullCol = false; break; }
210
+ if (fullCol) cols.push(i);
211
+ }
212
+ rows.forEach(ri => newBoard[ri].fill(0));
213
+ cols.forEach(ci => { for(let i=0; i<8; i++) newBoard[i][ci] = 0; });
214
+ return { board: newBoard, lines: rows.length + cols.length };
215
+ }
216
+
217
+ function evaluate(board, linesCleared) {
218
+ let score = 0;
219
+ if (linesCleared > 0) {
220
+ score += linesCleared * 1000;
221
+ } else {
222
+ for (let i = 0; i < 8; i++) {
223
+ let rCount = 0, cCount = 0;
224
+ for (let j = 0; j < 8; j++) {
225
+ if (board[i][j]) rCount++;
226
+ if (board[j][i]) cCount++;
227
+ }
228
+ if (rCount === 7) score += 150;
229
+ if (cCount === 7) score += 150;
230
+ }
231
+ }
232
+ const giantPiece = [[0,0],[0,1],[0,2],[1,0],[1,1],[1,2],[2,0],[2,1],[2,2]];
233
+ let canFitGiantCenter = false;
234
+ for (let r=1; r<=4; r++) {
235
+ for (let c=1; c<=4; c++) {
236
+ if (canPlace(board, giantPiece, r, c)) { canFitGiantCenter = true; break; }
237
+ }
238
+ if (canFitGiantCenter) break;
239
+ }
240
+ if (canFitGiantCenter) score += 500; else score -= 2000;
241
+ for (let i=0; i<8; i++) {
242
+ if (board[0][i]) score += 5; if (board[7][i]) score += 5;
243
+ if (board[i][0]) score += 5; if (board[i][7]) score += 5;
244
+ }
245
+ let empty = 0;
246
+ board.forEach(row => row.forEach(v => { if(!v) empty++; }));
247
+ score += empty * 10;
248
+ return score;
249
+ }
250
+
251
+ // --- Solver Engine (Supports 1-3 pieces) ---
252
+ async function solve() {
253
+ const status = document.getElementById('status-message');
254
+ const applyBtn = document.getElementById('apply-btn');
255
+ applyBtn.disabled = true;
256
+ currentBestSequence = null;
257
+
258
+ const available = [];
259
+ for (let i=0; i<3; i++) {
260
+ const p = getPiecePoints(i);
261
+ if (p) available.push({ id: i, shape: p });
262
+ }
263
+
264
+ if (available.length === 0) {
265
+ status.innerText = "ๅฐ‘ใชใใจใ‚‚1ใคใฎ้ง’ใ‚’ๆใ„ใฆใใ ใ•ใ„ใ€‚";
266
+ status.className = "p-4 rounded-xl text-center text-sm font-medium border bg-yellow-50 text-yellow-700 border-yellow-200";
267
+ return;
268
+ }
269
+
270
+ status.innerText = "่จˆ็ฎ—ไธญ...";
271
+ await new Promise(r => setTimeout(r, 50));
272
+
273
+ let maxTotalScore = -Infinity;
274
+
275
+ // Generate all permutations of indices 0..n-1
276
+ function getPermutations(arr) {
277
+ if (arr.length <= 1) return [arr];
278
+ let perms = [];
279
+ for (let i = 0; i < arr.length; i++) {
280
+ let rest = getPermutations(arr.slice(0, i).concat(arr.slice(i + 1)));
281
+ for (let r of rest) perms.push([arr[i]].concat(r));
282
+ }
283
+ return perms;
284
+ }
285
+
286
+ const perms = getPermutations(available.map((_, i) => i));
287
+
288
+ // Recursive simulation for n pieces
289
+ function simulate(currentBoard, availableIdxs, currentPath, currentScore) {
290
+ if (availableIdxs.length === 0) {
291
+ if (currentScore > maxTotalScore) {
292
+ maxTotalScore = currentScore;
293
+ currentBestSequence = [...currentPath];
294
+ }
295
+ return;
296
+ }
297
+
298
+ const piece = available[availableIdxs[0]];
299
+ const nextIdxs = availableIdxs.slice(1);
300
+
301
+ for (let r = 0; r < 8; r++) {
302
+ for (let c = 0; c < 8; c++) {
303
+ if (canPlace(currentBoard, piece.shape, r, c)) {
304
+ const result = applyPlacement(currentBoard, piece.shape, r, c);
305
+ const stepScore = evaluate(result.board, result.lines);
306
+
307
+ currentPath.push({
308
+ shape: piece.shape,
309
+ r: r, c: c,
310
+ coords: piece.shape.map(pt => [r + pt[0], c + pt[1]])
311
+ });
312
+
313
+ simulate(result.board, nextIdxs, currentPath, currentScore + stepScore);
314
+
315
+ currentPath.pop();
316
+ }
317
+ }
318
+ }
319
+ }
320
+
321
+ for (let p of perms) {
322
+ simulate(grid, p, [], 0);
323
+ }
324
+
325
+ if (currentBestSequence) {
326
+ renderBoard(currentBestSequence);
327
+ applyBtn.disabled = false;
328
+ status.innerHTML = `<b>ๆœ€้ฉใƒซใƒผใƒˆ(${currentBestSequence.length}ๆ‰‹)ใ‚’็ฎ—ๅ‡บ๏ผ</b><br>็ขบๅฎšใƒœใ‚ฟใƒณใง็›ค้ขใ‚’ๆ›ดๆ–ฐใ—ใพใ™ใ€‚`;
329
+ status.className = "p-4 rounded-xl text-center text-sm font-medium border bg-green-50 text-green-700 border-green-200";
330
+ } else {
331
+ status.innerText = "ๆŒ‡ๅฎšใ•ใ‚ŒใŸ้ง’ใ‚’ใ™ในใฆ็ฝฎใ‘ใ‚‹ใƒซใƒผใƒˆใŒ่ฆ‹ใคใ‹ใ‚Šใพใ›ใ‚“ใงใ—ใŸใ€‚";
332
+ status.className = "p-4 rounded-xl text-center text-sm font-medium border bg-red-50 text-red-700 border-red-200";
333
+ }
334
+ }
335
+
336
+ function applyBestSequence() {
337
+ if (!currentBestSequence) return;
338
+ let tempBoard = grid;
339
+ for (const step of currentBestSequence) {
340
+ const res = applyPlacement(tempBoard, step.shape, step.r, step.c);
341
+ tempBoard = res.board;
342
+ }
343
+ grid = tempBoard;
344
+ currentBestSequence = null;
345
+ renderBoard();
346
+ for (let i=0; i<3; i++) clearPiece(i);
347
+ document.getElementById('apply-btn').disabled = true;
348
+ document.getElementById('status-message').innerText = "้…็ฝฎใ‚’้ฉ็”จใ—ใพใ—ใŸใ€‚";
349
+ document.getElementById('status-message').className = "p-4 rounded-xl text-center text-sm font-medium border bg-indigo-50 text-indigo-700 border-indigo-200";
350
+ }
351
+
352
+ document.getElementById('solve-btn').onclick = solve;
353
+ document.getElementById('apply-btn').onclick = applyBestSequence;
354
+ document.getElementById('clear-grid').onclick = () => {
355
+ grid = Array(GRID_SIZE).fill().map(() => Array(GRID_SIZE).fill(0));
356
+ currentBestSequence = null;
357
+ document.getElementById('apply-btn').disabled = true;
358
+ renderBoard();
359
+ document.getElementById('status-message').innerText = "็›ค้ขใ‚’ใƒชใ‚ปใƒƒใƒˆใ—ใพใ—ใŸ";
360
+ };
361
+
362
+ initBoard();
363
+ initPieceEditors();
364
+ </script>
365
+ </body>
366
+ </html>