Skip to content

Ash-siv4/TicTacToe-ReactApp

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

23 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Tic-Tac-Toe Game Built with React

This is a simple Tic-Tac-Toe (noughts and crosses) game built using React. Follow the instructions below to set up and run the project on your local machine.

Prerequisites

Before you begin, make sure you have the following installed on your system:

  • Node.js: Download and install from Node.js.
  • npm: This is included with Node.js, so it should be installed automatically.

Installation

  1. Clone this repository.

  2. Install the dependencies:

    npm install
  3. Start the local server:

    npm start

    Follow the prompts to view the code running in a browser. This will typically open a new browser window with the game running at http://localhost:3000.

Project Structure

Files

  • App.js:

    • This file creates the main component of the application. In React, a component is a piece of reusable code that represents a part of a user interface. Components are used to render, manage, and update the UI elements in your application.
  • styles.css:

    • This file defines the styles for your React app. The first two CSS selectors (* and body) define the style of large parts of your app while the .square selector defines the style of any component where the className property is set to square. In your code, that would match the button from your Square component.
  • index.js:

    • This file serves as the bridge between the component you created in App.js and the web browser.
    import { StrictMode } from "react";
    import { createRoot } from "react-dom/client";
    import "./styles.css";
    
    import App from "./App";
    • Lines 1-5 bring all the necessary pieces together: React, React’s library to talk to web browsers (React DOM), the styles for your components, and the component you created in App.js.
    • The remainder of the file brings all the pieces together and injects the final product into index.html in the public folder.

Final Result Code Compilation

Here is a detailed look at the main parts of the code:

import { useState } from "react";

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

function Board({ xIsNext, squares, onPlay }) {
  function handleClick(i) {
    if (calculateWinner(squares) || squares[i]) {
      return;
    }
    const nextSquares = squares.slice();
    if (xIsNext) {
      nextSquares[i] = "X";
    } else {
      nextSquares[i] = "O";
    }
    onPlay(nextSquares);
  }

  const winner = calculateWinner(squares);
  let status;
  if (winner) {
    status = "Winner: " + winner;
  } else {
    status = "Next player: " + (xIsNext ? "X" : "O");
  }

  return (
    <>
      <div className="status">{status}</div>
      <div className="board-row">
        <Square value={squares[0]} onSquareClick={() => handleClick(0)} />
        <Square value={squares[1]} onSquareClick={() => handleClick(1)} />
        <Square value={squares[2]} onSquareClick={() => handleClick(2)} />
      </div>
      <div className="board-row">
        <Square value={squares[3]} onSquareClick={() => handleClick(3)} />
        <Square value={squares[4]} onSquareClick={() => handleClick(4)} />
        <Square value={squares[5]} onSquareClick={() => handleClick(5)} />
      </div>
      <div className="board-row">
        <Square value={squares[6]} onSquareClick={() => handleClick(6)} />
        <Square value={squares[7]} onSquareClick={() => handleClick(7)} />
        <Square value={squares[8]} onSquareClick={() => handleClick(8)} />
      </div>
    </>
  );
}

export default function Game() {
  const [history, setHistory] = useState([Array(9).fill(null)]);
  const [currentMove, setCurrentMove] = useState(0);
  const xIsNext = currentMove % 2 === 0;
  const currentSquares = history[currentMove];

  function handlePlay(nextSquares) {
    const nextHistory = [...history.slice(0, currentMove + 1), nextSquares];
    setHistory(nextHistory);
    setCurrentMove(nextHistory.length - 1);
  }

  function jumpTo(nextMove) {
    setCurrentMove(nextMove);
  }

  const moves = history.map((squares, move) => {
    let description;
    if (move > 0) {
      description = "Go to move #" + move;
    } else {
      description = "Go to game start";
    }
    return (
      <li key={move}>
        <button onClick={() => jumpTo(move)}>{description}</button>
      </li>
    );
  });

  return (
    <div className="game">
      <div className="game-board">
        <Board xIsNext={xIsNext} squares={currentSquares} onPlay={handlePlay} />
      </div>
      <div className="game-info">
        <ol>{moves}</ol>
      </div>
    </div>
  );
}

function calculateWinner(squares) {
  const lines = [
    [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 (let i = 0; i < lines.length; i++) {
    const [a, b, c] = lines[i];
    if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) {
      return squares[a];
    }
  }
  return null;
}

Future Improvements

Here are some ideas for improving the Tic-Tac-Toe game, listed in order of increasing difficulty:

  1. Current Move Indicator: For the current move only, show “You are at move #…” instead of a button.
  2. Dynamic Board Creation: Rewrite the Board component to use loops to create the squares instead of hardcoding them.
  3. Move Sorting: Add a toggle button that lets you sort the moves in either ascending or descending order.
  4. Winning Highlight: When someone wins, highlight the three squares that caused the win (and when no one wins, display a message about the result being a draw).
  5. Move Location: Display the location for each move in the format (row, col) in the move history list.

Reference

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published