Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 10 additions & 10 deletions src/components/Board.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,18 @@ interface BoardProps {
onSquareClick: (index: number) => void;
}

export default function Board(props: BoardProps) {
export default function Board({ squares, onSquareClick }: BoardProps) {
return (
<div className="board">
<Square value={props.squares[0]} onClick={() => props.onSquareClick(0)} />
<Square value={props.squares[1]} onClick={() => props.onSquareClick(1)} />
<Square value={props.squares[2]} onClick={() => props.onSquareClick(2)} />
<Square value={props.squares[3]} onClick={() => props.onSquareClick(3)} />
<Square value={props.squares[4]} onClick={() => props.onSquareClick(4)} />
<Square value={props.squares[5]} onClick={() => props.onSquareClick(5)} />
<Square value={props.squares[6]} onClick={() => props.onSquareClick(6)} />
<Square value={props.squares[7]} onClick={() => props.onSquareClick(7)} />
<Square value={props.squares[8]} onClick={() => props.onSquareClick(8)} />
{squares.map((square, index) => {
return (
<Square
key={index}
value={square}
onClick={() => onSquareClick(index)}
/>
);
})}
</div>
);
}
114 changes: 99 additions & 15 deletions src/components/Game.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,108 @@
import { useState } from "react";
import { useEffect, useState } from "react";
import Board from "./Board";

const WINNING_LINES: number[][] = [
[0, 1, 2],
[3, 4, 5],
[6, 7, 8],
[0, 3, 6],
[1, 4, 7],
[2, 5, 8],
[0, 4, 8],
[2, 4, 6],
];

//check for winner
function calculateWinner(squares: (string | null)[]): string | null {
for (const line of WINNING_LINES) {
const [a, b, c] = line;
if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) {
return squares[a];
}
}
return null;
}
const resetTime = 10;
const PLAYER_X = "X";
const PLAYER_O = "O";

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 [isXNext, setIsXNext] = useState(true);
const [time, setTime] = useState(resetTime);

const winner = calculateWinner(squares);
const isDraw = !winner && squares.every((square) => square !== null);
const nextPlayer = isXNext ? PLAYER_X : PLAYER_O;
const gameOver = Boolean(winner) || isDraw;

//resetGame function
const resetGame = () => {
setSquares(Array(9).fill(null));
setIsXNext(true);
setTime(resetTime);
};

useEffect(() => {
if (gameOver) return;

const timerId = setInterval(() => {
setTime((prev) => prev - 1);
}, 1000);

return () => clearInterval(timerId);
}, [gameOver]);

useEffect(() => {
if (gameOver) return;

if (time < 0) return;

if (time === 0) {
setIsXNext((turn) => !turn);
setTime(10);
}
}, [time, gameOver]);

return (
<div className="game-container">
<h1>Tic Tac Toe</h1>
function handleSquareClick(index: number) {
if (gameOver || squares[index]) {
return;
}

const currentPlayer = isXNext ? PLAYER_X : PLAYER_O;

<Board squares={squares} onSquareClick={handleSquareClick} />
<p>Next Player: {isXNext ? "X" : "O"}</p>
setSquares((oldSquares) => {
const newSquares = [...oldSquares];
newSquares[index] = currentPlayer;
return newSquares;
});

//end turn
setIsXNext((prevIsXNext) => !prevIsXNext);
setTime(resetTime);
}

return (
<div className="game-container">
<h1>Tic Tac Toe</h1>
<Board squares={squares} onSquareClick={handleSquareClick} />
<p>Next Player: {nextPlayer}</p>
<p>Time left:{time}</p>
{winner && (
<div>
<p>the winner is: {winner}</p>
<button onClick={resetGame}>restart</button>
</div>
)}
{isDraw && (
<div>
<p>It's a draw!</p>
<button onClick={resetGame}>Play Again</button>
</div>
);
)}
</div>
);
}
20 changes: 11 additions & 9 deletions src/components/Square.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
interface SquareProps {
value: string | null;
onClick: () => void;
value: string | null;
onClick: () => void;
}

export default function Square(props: SquareProps) {
return (
<button className="square" onClick={props.onClick}>
{props.value}
</button>
);
}
export const Square = ({ value, onClick }: SquareProps) => {
return (
<button className="square" onClick={onClick}>
{value}
</button>
);
};

export default Square;