Build a Tic-Tac-Toe Game - Build a Tic-Tac-Toe Game

Tell us what’s happening:

Test 9, 10, and 11 failed but, the game plays correctly. The massage changes and the button don’t update their text after the game is over. Any help would be greet.

Your code so far

<!-- file: index.html -->
<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8" />
    <title>Tic-Tac-Toe</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.3.1/umd/react.development.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.3.1/umd/react-dom.development.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/7.26.5/babel.min.js"></script>
    <script
      data-plugins="transform-modules-umd"
      type="text/babel"
      src="index.jsx"
    ></script>
    <link rel="stylesheet" href="styles.css" />
</head>

<body>
    <div id="root"></div>
    <script
      data-plugins="transform-modules-umd"
      type="text/babel"
      data-presets="react"
      data-type="module"
    >
      import { Board } from './index.jsx';
      ReactDOM.createRoot(document.getElementById('root')).render(<Board />);
    </script>
</body>

</html>
/* file: styles.css */
body {
  text-align: center;
  display: flex;
  justify-content: center;
}

.board {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 10px;
  max-width: 100px;
  margin-left: 5px
}

.square {
  height: 50px;
  width: 50px;
  padding: 20px;
  cursor: pointer;
}

.resetBtn {
  margin-top: 20px;
}
/* file: index.jsx */
const { useState, useEffect, useCallback } = React;

export function Board() {

  const [ player, setPlayer ] = useState("X");
  const [ introText, setIntroText ] = useState(
      `Next Player: ${player}`
    );
  const [ isDone, setIsDone ] = useState(false);
  const [ count, setCount ] = useState(0);
  
  const [ btnArr, setBtnArr ] = useState(
    [
    {id: 1, char: ""},
    {id: 2, char: ""},
    {id: 3, char: ""},
    {id: 4, char: ""},
    {id: 5, char: ""},
    {id: 6, char: ""},
    {id: 7, char: ""},
    {id: 8, char: ""},
    {id: 9, char: ""},
  ]);

  const handleBtn = useCallback((index) => {
    if (btnArr[index].char !== "" || isDone) return;

    const updated = [...btnArr];
    updated[index] = { ...updated[index], char: player };
    setBtnArr(updated);

    setCount((prev) => prev + 1);
    setPlayer((prev) => (prev === "X" ? "O" : "X"));
    
  }, [btnArr, player, isDone]);

  useEffect(() => {
    hasWon();
    if (!isDone) {
      setIntroText(`Next Player: ${player}`);
    }
  }, [handleBtn]);

  const handleReset = () => {
    setPlayer("X");
    setIntroText(`Next Player: ${player}`);
    setIsDone(false);
    setCount(0);
    setBtnArr([
      {id: 1, char: ""},
      {id: 2, char: ""},
      {id: 3, char: ""},
      {id: 4, char: ""},
      {id: 5, char: ""},
      {id: 6, char: ""},
      {id: 7, char: ""},
      {id: 8, char: ""},
      {id: 9, char: ""},
    ]);
  };

  const winCombos = [
    "123", "456", "789",
    "147", "258", "369",
    "159", "357" 
  ];

  const hasWon = () => {
    let xWon = false;
    let oWon = false;
    winCombos.forEach((num) => {
      const str = num.split('').map((letter) => {
        return btnArr[letter - 1].char;
      }).join("");
      if (str.includes("X") && 
           !str.includes("O") &&
           str.length == 3
         ) {
        xWon = true;
      }
      if (str.includes("O") && 
           !str.includes("X") &&
           str.length == 3
         ) {
        oWon = true;
      }
      if (xWon) {
        setPlayer("X");
        setIntroText(`Winner: ${player}`);
        setIsDone(true);
      }
      if (oWon) {
        setPlayer("O");
        setIntroText(`Winner: ${player}`);
        setIsDone(true);
      }
    });
    if (
        xWon === false && 
        oWon === false &&
        count === 9
      ) {
        setPlayer("");
        setIntroText("Draw");
        setIsDone(true);
      }
  };


  return (
    <div>
      <h1>Tic-Tack-Toe</h1>
      <p>{introText}</p>
      <div className="board">
        {btnArr.map((btn, index) => {
          return (
            <button 
              key={btn.id}
              onClick={() => {
  if (!isDone) handleBtn(index);}}
              className="square"
            >
              {btn.char}
            </button>
          )
        })}
        
      </div>
      <button 
        onClick={handleReset}
        id="reset"
        className="resetBtn"
      >
        Reset Game
      </button>
    </div>
  );
}

Your browser information:

User Agent is: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36

Challenge Information:

Build a Tic-Tac-Toe Game - Build a Tic-Tac-Toe Game

https://www.freecodecamp.org/learn/full-stack-developer/lab-tic-tac-toe/build-a-tic-tac-toe-game

you are correct test cases are seems to be all covered as mentioned, there was a similar experience from another camper with this and resolved after trying on anogther browser or disabling a dark theme kind of extension from browser Build a Tic-Tac-Toe Game - Build a Tic-Tac-Toe Game - #3 by bappyasif

you might want to try same and see if that resolves for you as well, happy coding :slight_smile:

I tried disabling and uninstalling themes and using crome and edge browsers. Doesn’t work sadly.

issue might be causing due its use of hooks and their dependency array, found another topic from forum where they were discussing about similar situations, give it a look and see if that is useful, happy coding :slight_smile: Build a Tic-Tac-Toe Game - Build a Tic-Tac-Toe Game