1const gameContainer = document.getElementById('gameContainer'); 2const startButton = document.getElementById('startButton'); 3const playAgainButton = document.getElementById('playAgainButton'); 4const timerDisplay = document.getElementById('timer'); 5const defaultImage = document.getElementById('defaultImage'); 6 7let pieces = []; 8let selectedIndex = null; 9let startTime; 10let timerInterval; 11 12const img = new Image(); 13 14// --- Null check for defaultImage before accessing .src --- 15if (defaultImage && defaultImage.src) { 16 img.src = defaultImage.src; 17 img.onload = function () { 18 createPuzzle(img, false); // show solved puzzle initially 19 }; 20} else { 21 console.warn('defaultImage element not found or has no src; puzzle will not initialize.'); 22} 23 24// --- Safely add event listeners only if the buttons exist --- 25if (startButton) { 26 startButton.addEventListener('click', () => { 27 shuffleArray(pieces); 28 renderPuzzle(); 29 startTime = new Date(); 30 startButton.style.display = 'none'; 31 startTimer(); 32 }); 33} else { 34 console.warn('startButton element not found.'); 35} 36 37if (playAgainButton) { 38 playAgainButton.addEventListener('click', () => { 39 shuffleArray(pieces); 40 renderPuzzle(); 41 startTime = new Date(); 42 startButton.style.display = 'none'; 43 startTimer(); 44 }); 45} else { 46 console.warn('playAgainButton element not found.'); 47} 48 49function createPuzzle(img, shuffle = true) { 50 pieces = []; 51 gameContainer.innerHTML = ''; 52 53 const canvas = document.createElement('canvas'); 54 const ctx = canvas.getContext('2d'); 55 canvas.width = 260; 56 canvas.height = 260; 57 ctx.drawImage(img, 0, 0, 260, 260); 58 59 for (let y = 0; y < 4; y++) { 60 for (let x = 0; x < 4; x++) { 61 const pieceCanvas = document.createElement('canvas'); 62 pieceCanvas.width = 65; 63 pieceCanvas.height = 65; 64 const pieceCtx = pieceCanvas.getContext('2d'); 65 pieceCtx.drawImage(canvas, x * 65, y * 65, 65, 65, 0, 0, 65, 65); 66 pieces.push({ 67 correctIndex: y * 4 + x, 68 canvas: pieceCanvas 69 }); 70 } 71 } 72 73 if (shuffle) shuffleArray(pieces); 74 renderPuzzle(); 75} 76 77function renderPuzzle() { 78 gameContainer.innerHTML = ''; 79 pieces.forEach((piece, index) => { 80 const div = document.createElement('div'); 81 div.classList.add('piece'); 82 div.appendChild(piece.canvas); 83 if (index === selectedIndex) { 84 div.classList.add('selected'); 85 } 86 div.addEventListener('click', () => handlePieceClick(index)); 87 gameContainer.appendChild(div); 88 }); 89} 90 91function handlePieceClick(index) { 92 if (!startButton || startButton.style.display !== 'none') return; // prevent interaction before start 93 if (selectedIndex === null) { 94 selectedIndex = index; 95 } else { 96 [pieces[selectedIndex], pieces[index]] = [pieces[index], pieces[selectedIndex]]; 97 selectedIndex = null; 98 renderPuzzle(); 99 checkWin(); 100 } 101 renderPuzzle(); 102} 103 104function checkWin() { 105 const isSolved = pieces.every((piece, index) => piece.correctIndex === index); 106 if (isSolved) { 107 clearInterval(timerInterval); 108 const endTime = new Date(); 109 const timeTakenSec = Math.floor((endTime - startTime) / 1000); 110 const minutes = Math.floor(timeTakenSec / 60); 111 const seconds = timeTakenSec % 60; 112 const formattedTime = `${minutes}:${seconds}`; 113 114 document.getElementById('winModalTime').textContent = `${formattedTime}`; 115 116 const winModal = new bootstrap.Modal(document.getElementById('winModal')); 117 winModal.show(); 118 119 // show share button 120 document.getElementById("shareBtn").style.display = "inline-flex"; 121 } 122} 123 124function startTimer() { 125 timerInterval = setInterval(() => { 126 const now = new Date(); 127 const timeTakenSec = Math.floor((now - startTime) / 1000); 128 const minutes = Math.floor(timeTakenSec / 60); 129 const seconds = timeTakenSec % 60; 130 timerDisplay.textContent = `${minutes}:${seconds.toString().padStart(2, '0')}`; 131 }, 1000); 132} 133 134function shuffleArray(array) { 135 for (let i = array.length - 1; i > 0; i--) { 136 const j = Math.floor(Math.random() * (i + 1)); 137 [array[i], array[j]] = [array[j], array[i]]; 138 } 139}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.