diff --git a/src/state/game-state.js b/src/state/game-state.js index 303fe93..c17a6f6 100644 --- a/src/state/game-state.js +++ b/src/state/game-state.js @@ -63,7 +63,12 @@ class GameStateManager { })); // Restore saved state from LocalStorage if available - this.restoreProgress(); + const hasSavedTileOrder = this.restoreProgress(); + + // If fresh puzzle without saved order, scramble the board so target words are not formed! + if (!hasSavedTileOrder) { + this.scrambleBoard(puzzle.id || String(Date.now())); + } // Organize board tiles according to lock state this.reorganizeBoard(); @@ -71,6 +76,28 @@ class GameStateManager { this.notify(); } + // Seeded Fisher-Yates scramble for initial board dealing + scrambleBoard(seed = '') { + let h = 0x811c9dc5; + for (let i = 0; i < seed.length; i++) { + h ^= seed.charCodeAt(i); + h = Math.imul(h, 0x01000193); + } + let s = (h >>> 0) || 123456789; + const nextRandom = () => { + s = (Math.imul(1664525, s) + 1013904223) >>> 0; + return s / 4294967296; + }; + + const shuffled = [...this.boardTiles]; + for (let i = shuffled.length - 1; i > 0; i--) { + const j = Math.floor(nextRandom() * (i + 1)); + [shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]]; + } + this.boardTiles = shuffled; + this.saveProgress(); + } + // Get current date string in YYYY-MM-DD getTodayDateString() { const today = new Date(); @@ -99,7 +126,7 @@ class GameStateManager { // Restore puzzle progress restoreProgress() { - if (!this.currentPuzzle) return; + if (!this.currentPuzzle) return false; const saveKey = `quartiles_save_${this.currentPuzzle.id}`; try { const saved = localStorage.getItem(saveKey); @@ -115,10 +142,17 @@ class GameStateManager { // Restore tile order if saved if (Array.isArray(parsed.tileOrder) && parsed.tileOrder.length === 20) { + // Check if saved order was the trivial unscrambled [0..19] order + const isSequential = parsed.tileOrder.every((id, idx) => id === idx); + if (isSequential && this.foundWords.size === 0) { + return false; + } + const tileMap = new Map(this.boardTiles.map(t => [t.id, t])); const reordered = parsed.tileOrder.map(id => tileMap.get(id)).filter(Boolean); if (reordered.length === 20) { this.boardTiles = reordered; + return true; } } } @@ -126,6 +160,7 @@ class GameStateManager { } catch (err) { console.warn('Failed to restore progress:', err); } + return false; } // Check if a tile belongs to an already found Quartile