diff --git a/src/components/Board.tsx b/src/components/Board.tsx
index 3989a44..cefaa4c 100644
--- a/src/components/Board.tsx
+++ b/src/components/Board.tsx
@@ -5,18 +5,12 @@ interface BoardProps {
onSquareClick: (index: number) => void;
}
-export default function Board(props: BoardProps) {
+export default function Board({ squares, onSquareClick }: BoardProps) {
return (
- props.onSquareClick(0)} />
- props.onSquareClick(1)} />
- props.onSquareClick(2)} />
- props.onSquareClick(3)} />
- props.onSquareClick(4)} />
- props.onSquareClick(5)} />
- props.onSquareClick(6)} />
- props.onSquareClick(7)} />
- props.onSquareClick(8)} />
+ {squares.map((sqr, index) => (
+ onSquareClick(index)} />
+ ))}
);
}
diff --git a/src/components/Game.tsx b/src/components/Game.tsx
index 80be18b..29de6d5 100644
--- a/src/components/Game.tsx
+++ b/src/components/Game.tsx
@@ -1,24 +1,105 @@
-import { useState } from "react";
+import { useState, useEffect } from "react";
import Board from "./Board";
export default function Game() {
- const [squares, setSquares] = useState<(string | null)[]>(
- Array(9).fill(null)
- );
- const [isXNext, setIsXNext] = useState(true);
-
- function handleSquareClick(index: number) {
- // Temporary: no gameplay logic yet
- console.log("Clicked square:", index);
+ const [squares, setSquares] = useState<(string | null)[]>(
+ Array(9).fill(null)
+ );
+
+ const timeLimit = 10;
+
+ const [isXNext, setIsXNext] = useState(true);
+ const [winner, setWinner] = useState(null);
+ const [time, setTime] = useState(timeLimit);
+ const [timeRunning, setTimeRunning] = useState(false);
+
+ useEffect(() => {
+ if (!timeRunning || winner) return;
+
+ const timerId = window.setInterval(() => {
+ setTime((currTime) => Math.max(currTime - 1, 0));
+ }, 1000);
+
+ return () => window.clearInterval(timerId);
+ }, [timeRunning, winner]);
+
+ useEffect(() => {
+ if (!timeRunning || winner) return;
+
+ if (time === 0) {
+ setIsXNext((currPlayer) => !currPlayer);
+ setTime(timeLimit);
+ }
+ }, [time, timeRunning, winner, timeLimit]);
+
+ function handleGameRestart() {
+ setSquares(Array(9).fill(null));
+ setIsXNext(true);
+ setWinner(null);
+ setTime(timeLimit);
+ setTimeRunning(false);
+ }
+
+ function handleSquareClick(index: number) {
+ if (squares[index] !== null || winner) return;
+
+ if (!timeRunning) setTimeRunning(true);
+
+ const nextSquares = [...squares];
+ nextSquares[index] = isXNext ? "X" : "O";
+ setSquares(nextSquares);
+
+ const winningPlayer = calculateWinner(nextSquares);
+ if (winningPlayer) return;
+
+ setIsXNext((p) => !p);
+ setTime(timeLimit);
+ }
+
+ function calculateWinner(boardArr: (string | null)[]) {
+ 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],
+ ] as const;
+
+ for (const [a, b, c] of lines) {
+ if (
+ boardArr[a] &&
+ boardArr[a] === boardArr[b] &&
+ boardArr[a] === boardArr[c]
+ ) {
+ setWinner(boardArr[a]);
+ setTimeRunning(false);
+ return boardArr[a];
+ }
}
+ return null;
+ }
+
+ return (
+
+
Asaf's Basic React Tic Tac Toe
+
+
Play timer: {time}
- return (
-
-
Tic Tac Toe
+
+
{winner == null ? null : "Winner: " + winner}
-
-
Next Player: {isXNext ? "X" : "O"}
+
+ {winner == null
+ ? isXNext
+ ? "Next Player: X"
+ : "Next Player: O"
+ : null}
+
-
- );
+
+
+ );
}
diff --git a/src/components/Square.tsx b/src/components/Square.tsx
index 3e9f11a..dfe8976 100644
--- a/src/components/Square.tsx
+++ b/src/components/Square.tsx
@@ -1,12 +1,14 @@
interface SquareProps {
- value: string | null;
- onClick: () => void;
+ value: string | null;
+ onClickFunction: () => void;
}
-export default function Square(props: SquareProps) {
- return (
-
- );
-}
+export const Square = ({ value, onClickFunction }: SquareProps) => {
+ return (
+
+ );
+};
+
+export default Square;