Last active
November 11, 2025 12:13
-
-
Save exah/026c5386a3a740bd964b56abf2b9a130 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import { useState } from "react"; | |
| const PLAYERS = ["O", "X"]; | |
| const NEXT_PLAYER = { | |
| [PLAYERS[0]]: PLAYERS[1], | |
| [PLAYERS[1]]: PLAYERS[0], | |
| }; | |
| function generateBoard(size) { | |
| return Array(Math.pow(size, 2)).fill(null); | |
| } | |
| function getWinner(board, size) { | |
| const indices = [...Array(size).keys()]; | |
| const getCell = (r, c) => board[r * size + c]; | |
| // Check rows | |
| for (const row of indices) { | |
| const player = getCell(row, 0); | |
| if (player && indices.every((column) => getCell(row, column) === player)) { | |
| return player; | |
| } | |
| } | |
| // Check columns | |
| for (const column of indices) { | |
| const player = getCell(0, column); | |
| if (player && indices.every((row) => getCell(row, column) === player)) { | |
| return player; | |
| } | |
| } | |
| // Check main diagonal | |
| const mainDiagPlayer = getCell(0, 0); | |
| if ( | |
| mainDiagPlayer && | |
| indices.every((index) => getCell(index, index) === mainDiagPlayer) | |
| ) { | |
| return mainDiagPlayer; | |
| } | |
| // Check anti-diagonal | |
| const antiDiagPlayer = getCell(0, size - 1); | |
| if ( | |
| antiDiagPlayer && | |
| indices.every((index) => getCell(index, size - 1 - index) === antiDiagPlayer) | |
| ) { | |
| return antiDiagPlayer; | |
| } | |
| return null; | |
| } | |
| export default function TicTacToe({ size = 4 }) { | |
| const [player, setPlayer] = useState(PLAYERS[0]); | |
| const [board, setBoard] = useState(() => generateBoard(size)); | |
| const winner = getWinner(board, size); | |
| const move = (cell) => { | |
| setBoard((board) => | |
| board.map((value, index) => | |
| cell === index && value === null ? player : value, | |
| ), | |
| ); | |
| setPlayer(NEXT_PLAYER[player]); | |
| }; | |
| return ( | |
| <div> | |
| <div | |
| style={{ | |
| display: "grid", | |
| gridTemplateColumns: `repeat(${size}, 1fr)`, | |
| aspectRatio: 1, | |
| }} | |
| > | |
| {board.map((value, index) => ( | |
| <button key={index} type="button" onClick={() => move(index)}> | |
| {value} | |
| </button> | |
| ))} | |
| </div> | |
| {winner && <p>Winner: {winner}</p>} | |
| </div> | |
| ); | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import { useState } from "react"; | |
| const GRID = Array(9).fill(null); | |
| const PLAYERS = ["O", "X"]; | |
| const NEXT_PLAYER = { | |
| [PLAYERS[0]]: PLAYERS[1], | |
| [PLAYERS[1]]: PLAYERS[0], | |
| }; | |
| const COMBOS = [ | |
| [0, 1, 2], | |
| [3, 4, 5], | |
| [6, 7, 8], | |
| [0, 3, 6], | |
| [1, 4, 7], | |
| [2, 5, 8], | |
| [0, 4, 8], | |
| [2, 4, 6], | |
| ]; | |
| function getWinner(board) { | |
| const combo = COMBOS.find( | |
| ([a, b, c]) => | |
| board[a] !== null && board[a] === board[b] && board[a] === board[c], | |
| ); | |
| return combo ? board[combo[0]] : null; | |
| } | |
| export default function TicTacToe() { | |
| const [player, setPlayer] = useState(PLAYERS[0]); | |
| const [board, setBoard] = useState(GRID); | |
| const winner = getWinner(board); | |
| const move = (cell) => { | |
| setBoard((board) => | |
| board.map((value, index) => | |
| cell === index && value === null ? player : value, | |
| ), | |
| ); | |
| setPlayer(NEXT_PLAYER[player]); | |
| }; | |
| return ( | |
| <div> | |
| <div | |
| style={{ | |
| display: "grid", | |
| gridTemplateColumns: "repeat(3, 1fr)", | |
| aspectRatio: 1, | |
| }} | |
| > | |
| {board.map((value, index) => ( | |
| <button key={index} type="button" onClick={() => move(index)}> | |
| {value} | |
| </button> | |
| ))} | |
| </div> | |
| {winner && <p>Winner: {winner}</p>} | |
| </div> | |
| ); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment