From 9315be37a6a87903df6583ab1a85f0b9be116497 Mon Sep 17 00:00:00 2001 From: sltan29 Date: Mon, 15 Dec 2025 18:45:24 +0200 Subject: [PATCH 1/2] created useeffect for time,winner message, play again button and calculate winner --- package-lock.json | 12 ++++++++ src/components/Game.tsx | 61 +++++++++++++++++++++++++++++++++++++---- 2 files changed, 67 insertions(+), 6 deletions(-) diff --git a/package-lock.json b/package-lock.json index 2fec462..88e255c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -57,6 +57,7 @@ "integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.5", @@ -1389,6 +1390,7 @@ "integrity": "sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "undici-types": "~7.16.0" } @@ -1399,6 +1401,7 @@ "integrity": "sha512-MWtvHrGZLFttgeEj28VXHxpmwYbor/ATPYbBfSFZEIRK0ecCFLl2Qo55z52Hss+UV9CRN7trSeq1zbgx7YDWWg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "csstype": "^3.2.2" } @@ -1458,6 +1461,7 @@ "integrity": "sha512-N9lBGA9o9aqb1hVMc9hzySbhKibHmB+N3IpoShyV6HyQYRGIhlrO5rQgttypi+yEeKsKI4idxC8Jw6gXKD4THA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "8.49.0", "@typescript-eslint/types": "8.49.0", @@ -1709,6 +1713,7 @@ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, "license": "MIT", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -1814,6 +1819,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", @@ -2035,6 +2041,7 @@ "integrity": "sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", @@ -2721,6 +2728,7 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=12" }, @@ -2782,6 +2790,7 @@ "resolved": "https://registry.npmjs.org/react/-/react-19.2.1.tgz", "integrity": "sha512-DGrYcCWK7tvYMnWh79yrPHt+vdx9tY+1gPZa7nJQtO/p8bLTDaHp4dzwEhQB7pZ4Xe3ok4XKuEPrVuc+wlpkmw==", "license": "MIT", + "peer": true, "engines": { "node": ">=0.10.0" } @@ -2984,6 +2993,7 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -3070,6 +3080,7 @@ "integrity": "sha512-ITcnkFeR3+fI8P1wMgItjGrR10170d8auB4EpMLPqmx6uxElH3a/hHGQabSHKdqd4FXWO1nFIp9rRn7JQ34ACQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.5.0", @@ -3191,6 +3202,7 @@ "integrity": "sha512-AvvthqfqrAhNH9dnfmrfKzX5upOdjUVJYFqNSlkmGf64gRaTzlPwz99IHYnVs28qYAybvAlBV+H7pn0saFY4Ig==", "dev": true, "license": "MIT", + "peer": true, "funding": { "url": "https://github.com/sponsors/colinhacks" } diff --git a/src/components/Game.tsx b/src/components/Game.tsx index 80be18b..20d0fc7 100644 --- a/src/components/Game.tsx +++ b/src/components/Game.tsx @@ -1,24 +1,73 @@ -import { useState } from "react"; +import { useEffect, useState } from "react"; import Board from "./Board"; export default function Game() { const [squares, setSquares] = useState<(string | null)[]>( Array(9).fill(null) ); + const [time, setTime] = useState(10); const [isXNext, setIsXNext] = useState(true); + const winnerCombination = [ + [0,1,2], + [3,4,5], + [6,7,8], + [0,4,8], + [6,4,2], + [0,3,6], + [2,5,8], + [1,4,7] + ] + + useEffect(()=>{ + if (time === 0){ + setIsXNext((prev)=>!prev); + setTime(10); + return; + } + + const timer = setInterval(()=>{ + setTime((prev)=>prev - 1) + },1000) + + return () => clearInterval(timer); + + },[time,squares]) + function handleSquareClick(index: number) { - // Temporary: no gameplay logic yet - console.log("Clicked square:", index); + if(calculateWinner()) + return; + + squares[index] = isXNext ? "X" : "O"; + setSquares([...squares]); + setIsXNext(!isXNext); + setTime(10); + + } + + function calculateWinner(){ + for (let i = 0; i < winnerCombination.length; i++){ + const [a,b,c] = winnerCombination[i]; + if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) + return squares[a]; + } + return null; + } + + function playAgain(){ + setSquares(Array(9).fill(null)); + setIsXNext(true); + setTime(10); } return (

Tic Tac Toe

- +

Turn timer: {time}

Next Player: {isXNext ? "X" : "O"}

- + {calculateWinner() &&

Winner: {calculateWinner()}

} +
); -} +} \ No newline at end of file From 379252fd0b5c2cebcad4f12fc465cb38f6f78cd1 Mon Sep 17 00:00:00 2001 From: sltan29 Date: Fri, 19 Dec 2025 22:46:57 +0200 Subject: [PATCH 2/2] moved the winner combinations outside the component, checking if a square is occupied --- src/components/Game.tsx | 55 ++++++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 26 deletions(-) diff --git a/src/components/Game.tsx b/src/components/Game.tsx index 20d0fc7..3e74c6d 100644 --- a/src/components/Game.tsx +++ b/src/components/Game.tsx @@ -1,60 +1,63 @@ import { useEffect, useState } from "react"; import Board from "./Board"; +const winnerCombination = [ + [0, 1, 2], + [3, 4, 5], + [6, 7, 8], + [0, 4, 8], + [6, 4, 2], + [0, 3, 6], + [2, 5, 8], + [1, 4, 7] + ] + export default function Game() { const [squares, setSquares] = useState<(string | null)[]>( Array(9).fill(null) ); const [time, setTime] = useState(10); const [isXNext, setIsXNext] = useState(true); - const winnerCombination = [ - [0,1,2], - [3,4,5], - [6,7,8], - [0,4,8], - [6,4,2], - [0,3,6], - [2,5,8], - [1,4,7] - ] + - useEffect(()=>{ - if (time === 0){ - setIsXNext((prev)=>!prev); + useEffect(() => { + if (time === 0) { + setIsXNext((prev) => !prev); setTime(10); return; } - const timer = setInterval(()=>{ - setTime((prev)=>prev - 1) - },1000) + const timer = setInterval(() => { + setTime((prev) => prev - 1) + }, 1000) return () => clearInterval(timer); - - },[time,squares]) + + }, [time, squares]) function handleSquareClick(index: number) { - if(calculateWinner()) + if (calculateWinner() || squares[index] != null) return; - squares[index] = isXNext ? "X" : "O"; - setSquares([...squares]); + const nextSquares = [...squares]; + nextSquares[index] = isXNext ? "X" : "O"; + setSquares(nextSquares); setIsXNext(!isXNext); setTime(10); - + } - function calculateWinner(){ - for (let i = 0; i < winnerCombination.length; i++){ - const [a,b,c] = winnerCombination[i]; + function calculateWinner() { + for (let i = 0; i < winnerCombination.length; i++) { + const [a, b, c] = winnerCombination[i]; if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) return squares[a]; } return null; } - function playAgain(){ + function playAgain() { setSquares(Array(9).fill(null)); setIsXNext(true); setTime(10);