1// selectors 2const gameBoard = document.querySelector("#board"); 3const info = document.querySelector("#info"); 4let turn; 5const winningCombos = [ 6 [0, 1, 2], // top row 7 [3, 4, 5], // middle row 8 [6, 7, 8], // bottom row 9 [0, 3, 6], // left col 10 [1, 4, 7], // middle col 11 [2, 5, 8], // right col 12 [0, 4, 8], // diag l-to-r 13 [2, 4, 6], // diag r-to-l 14]; 15 16// create the gameboard 17function createGameboard() { 18 const emptyTiles = " ".repeat(9).split(""); 19 const tileGrid = emptyTiles 20 .map((t) => `<button class="tile"></button>`) 21 .join(""); 22 gameBoard.innerHTML = tileGrid; 23 turn = "X"; 24 document.documentElement.style.setProperty("--hue", 10); 25 info.textContent = `${turn}âs turn`; 26 gameBoard.addEventListener("click", handleGameboardClick); 27 const allTiles = gameBoard.querySelectorAll(".tile"); 28 allTiles.forEach((t) => { 29 t.addEventListener("mouseenter", handleMouseEnter); 30 t.addEventListener("mouseleave", handleMouseLeave); 31 }); 32 gameBoard.removeAttribute("inert"); 33} 34createGameboard(); 35 36function updateTurn() { 37 turn = turn === "X" ? "O" : "X"; 38 info.textContent = `${turn}âs turn`; 39 document.documentElement.style.setProperty("--hue", turn === "X" ? 10 : 200); 40} 41 42function restartGame() { 43 let seconds = 3; 44 const timer = setInterval(() => { 45 info.textContent = `Restarting in ${seconds}â¦`; 46 seconds--; 47 if (seconds < 0) { 48 // clear the interval 49 clearInterval(timer); 50 // restart game 51 createGameboard(); 52 } 53 }, 1000); 54} 55 56function showCongrats() { 57 info.textContent = `${turn} wins!`; 58 gameBoard.removeEventListener("click", handleGameboardClick); 59 gameBoard.setAttribute("inert", true); 60 const jsConfetti = new JSConfetti(); 61 jsConfetti.addConfetti({ 62 emojis: ["ð¥³", "ð", "ð", "ð"], 63 }); 64 setTimeout(restartGame, 1000); 65} 66 67function checkScore() { 68 const allTiles = [...document.querySelectorAll(".tile")]; 69 const tileValues = allTiles.map((t) => t.dataset.value); 70 const isWinner = winningCombos.some((combo) => { 71 const [a, b, c] = combo; 72 return ( 73 tileValues[a] && 74 tileValues[a] === tileValues[b] && 75 tileValues[a] === tileValues[c] 76 ); 77 }); 78 if (isWinner) { 79 return showCongrats(); 80 } 81 updateTurn(); 82} 83 84function handleGameboardClick(e) { 85 const valueExists = e.target.dataset.value; 86 if (!valueExists) { 87 e.target.dataset.value = turn; 88 e.target.style.setProperty("--hue", turn === "X" ? 10 : 200); 89 checkScore(); 90 } 91} 92 93function handleMouseEnter(e) { 94 const valueExists = e.target.dataset.value; 95 if (!valueExists) { 96 e.target.dataset.hover = turn; 97 e.target.style.setProperty("--hue", turn === "X" ? 10 : 200); 98 } 99} 100 101function handleMouseLeave(e) { 102 e.target.dataset.hover = ""; 103}
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.