PageSourceSearch

https://codinginpublic.dev/projects/tic-tac-toe/app.js

js codinginpublic.dev collected 2026-09-25 21:05:01 UTC 2,747 bytes, 103 lines download raw bytes

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.