47 - Tic-Tac-Toe Game

Description

Build a two-player Tic-Tac-Toe game with X and O turns and win detection.

  • Display a 3x3 grid of buttons representing squares.

  • Players take turns clicking squares to mark them with X or O.

  • Detect horizontal, vertical, or diagonal wins for either player.

  • Announce the winner or draw when the game ends.

  • Optionally, reset the game for another round.

Algorithm

Components:

  • GameBoard: Renders the 9 squares grid and handles user clicks.

  • Square: Represents an individual square and its state (empty, X, O).

Data:

  • Maintain a grid of 9 states (initially empty) representing the squares.

  • Track the current player turn (X or O).

Logic:

  • On square click, update the corresponding grid state with the current player's mark.

  • After each click, check for win conditions by analyzing rows, columns, and diagonals.

  • If a win is detected, update the state to reflect the winner.

  • Otherwise, check if all squares are marked, resulting in a draw.

  • After the game ends, provide options to reset the board or start a new game.

Code

import React, { useState } from 'react';
import Square from './Square';

function GameBoard() {
  const [squares, setSquares] = useState(Array(9).fill(''));
  const [currentPlayer, setCurrentPlayer] = useState('X');
  const [winner, setWinner] = useState(null);

  const handleClick = (squareIndex) => {
    if (winner || squares[squareIndex]) return; // If game is over or square is already filled

    const newSquares = squares.slice();
    newSquares[squareIndex] = currentPlayer;
    setSquares(newSquares);

    const hasWinner = checkWinner(newSquares);
    if (hasWinner) {
      setWinner(currentPlayer);
      return;
    }

    if (newSquares.every(square => square)) {
      setWinner('draw');
      return;
    }

    setCurrentPlayer(currentPlayer === 'X' ? 'O' : 'X');
  };

  const checkWinner = (squares) => {
    const winningConditions = [
      [0, 1, 2],
      [3, 4, 5],
      [6, 7, 8],
      [0, 3, 6],
      [1, 4, 7],
      [2, 5, 8],
      [0, 4, 8],
      [2, 4, 6],
    ];

    for (const condition of winningConditions) {
      const [a, b, c] = condition;
      if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) {
        return true;
      }
    }

    return false;
  };

  const resetGame = () => {
    setSquares(Array(9).fill(''));
    setCurrentPlayer('X');
    setWinner(null);
  };

  return (
    <div className="game-board">
      <div className="game-info">
        {winner ? (
          <h2>Winner: {winner}</h2>
        ) : (
          <h2>Next player: {currentPlayer}</h2>
        )}
        {winner && <button onClick={resetGame}>Play Again</button>}
      </div>
      <div className="board-row">
        {squares.slice(0, 3).map((square, index) => (
          <Square key={index} value={square} onClick={() => handleClick(index)} />
        ))}
      </div>
      <div className="board-row">
        {squares.slice(3, 6).map((square, index) => (
          <Square key={index + 3} value={square} onClick={() => handleClick(index + 3)} />
        ))}
      </div>
      <div className="board-row">
        {squares.slice(6, 9).map((square, index) => (
          <Square key={index + 6} value={square} onClick={() => handleClick(index + 6)} />
        ))}
      </div>
    </div>
  );
}

export default GameBoard;
import React from 'react';

function Square({ value, onClick }) {
  return (
    <button className="square" onClick={onClick}>
      {value}
    </button>
  );
}

export default Square;

Explanation

  • GameBoard manages the game state (squares and current player).

  • handleClick updates the squares and switches player turns.

  • checkWin (not shown) evaluates winning conditions based on square markings.

  • Square simply renders the current state (empty, X, or O) of each square.

Additional Notes

  • Consider adding visual cues for the current player and highlight winning lines.

  • Implement a simple AI opponent for single-player mode (optional).

  • Add animations or sound effects for a more engaging experience.

Last updated