diff --git a/src/App.css b/src/App.css
index 74b5e05..52df60a 100644
--- a/src/App.css
+++ b/src/App.css
@@ -24,6 +24,16 @@
color: white;
}
+.App-body {
+ background-color: #282c34;
+ min-height: 100vh;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ color: white;
+}
+
.App-link {
color: #61dafb;
}
diff --git a/src/App.tsx b/src/App.tsx
index a53698a..0a4760b 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -1,26 +1,16 @@
import React from 'react';
-import logo from './logo.svg';
import './App.css';
+import TicTacToe from './TicTacToe/Root';
+
function App() {
- return (
-
- );
+ return (
+
+ );
}
export default App;
diff --git a/src/TicTacToe/Root.tsx b/src/TicTacToe/Root.tsx
new file mode 100644
index 0000000..d565e6e
--- /dev/null
+++ b/src/TicTacToe/Root.tsx
@@ -0,0 +1,159 @@
+import React from 'react';
+import { useState } from 'react';
+import './style.css';
+
+function TicTacToe() {
+ const [gridState, setGridState] = useState(Array(9).fill(0));
+ const [playerState, setPlayerState] = useState(false);
+ const [winState, setWinState] = useState(0);
+ let localWinState = winState;
+
+ function updateGridState(index : number, state : number) {
+ gridState[index] = state;
+ setGridState(gridState);
+ }
+
+ function playTurn(index : number) {
+ if (gridState[index]) return;
+ if (winState) return;
+
+ const newState = playerState ? 2 : 1;
+ updateGridState(index, newState);
+
+ const winner = checkWinCondition()
+ if (winner) {
+ localWinState = winner;
+ setWinState(winner);
+ return;
+ }
+
+ setPlayerState(!playerState);
+ }
+
+ function checkWinCondition() : number {
+
+ function getWinningValue(
+ a : number,
+ b : number,
+ c : number
+ ) {
+ if ((a === b) && (b === c) && (a === c)) {
+ return a;
+ }
+ return 0
+ }
+ /*
+ * Diagonals
+ */
+ {
+ const a = gridState[3 * 0 + 0];
+ const b = gridState[3 * 1 + 1];
+ const c = gridState[3 * 2 + 2];
+ const winner = getWinningValue(a, b, c);
+ if (winner) return winner;
+ }
+ {
+ const a = gridState[3 * 0 + 2];
+ const b = gridState[3 * 1 + 1];
+ const c = gridState[3 * 2 + 0];
+ const winner = getWinningValue(a, b, c);
+ if (winner) return winner;
+ }
+ /*
+ * Rows and Columns
+ */
+ for (let row = 0; row < 3; row++) {
+ const a = gridState[3 * row + 0];
+ const b = gridState[3 * row + 1];
+ const c = gridState[3 * row + 2];
+ const winner = getWinningValue(a, b, c);
+ if (winner) return winner;
+ }
+
+ for (let column = 0; column < 3; column++) {
+ const a = gridState[3 * 0 + column];
+ const b = gridState[3 * 1 + column];
+ const c = gridState[3 * 2 + column];
+ const winner = getWinningValue(a, b, c);
+ if (winner) return winner;
+ }
+
+ const isDrawState = () => {
+ for (let i in gridState) {
+ if (!gridState[i]) return false;
+ };
+ return true;
+ }
+ if (isDrawState()) return 3;
+
+ return 0;
+ }
+
+ let stateString = "";
+ if (localWinState === 3) {
+ stateString = `Game draw.`
+ }
+ else if (localWinState) {
+ stateString = `Player ${getStateChar(localWinState)} wins.`;
+ }
+ else {
+ stateString = `Player ${getStateChar(playerState ? 2 : 1)} turn.`
+ }
+
+ return (
+
+
{stateString}
+
+ {
+ gridState.map((item, index) => {
+ const getState = () => { return gridState[index] };
+ const callback = () => { playTurn(index) };
+ return ();
+ })
+ }
+
+
+ );
+}
+
+interface CellProps {
+ getState: () => number;
+ callback: () => void;
+}
+
+function TicTacToeCell({ getState, callback }: CellProps) {
+
+ function handleClick() {
+ callback()
+ }
+
+ return (
+
+
{getStateChar(getState())}
+
+ );
+}
+
+function getStateChar(state : number) {
+ switch (state) {
+ case 1:
+ return "O";
+ case 2:
+ return "X";
+ default:
+ return "";
+ }
+}
+
+function getStateClass(state : number) {
+ switch (state) {
+ case 1:
+ return "CellRed";
+ case 2:
+ return "CellBlue";
+ default:
+ return "";
+ }
+}
+
+export default TicTacToe;
diff --git a/src/TicTacToe/style.css b/src/TicTacToe/style.css
new file mode 100644
index 0000000..12841da
--- /dev/null
+++ b/src/TicTacToe/style.css
@@ -0,0 +1,40 @@
+.TicTacToe {
+ background-color: #3B3E49;
+ color: #B9B8D6;
+}
+
+.TicTacToeGrid {
+ display: grid;
+ width: 50vh;
+ height: 50vh;
+ grid-template-columns: auto auto auto;
+}
+
+.TicTacToeCell {
+ min-width: 33.33%;
+ min-height: 33.33%;
+ background-color: #4d4f5d;
+ text-align: center;
+ position: relative;
+}
+
+.TicTacToeCell:hover {
+ opacity: 0.9;
+}
+
+.TicTacToeCell > p {
+ margin: 0;
+ padding: 0;
+ position: absolute;
+ left: 50%;
+ top: 50%;
+ transform: translate(-50%, -50%);
+}
+
+.CellRed {
+ color: #D6B8B8;
+}
+
+.CellBlue {
+ color: #B8C7D6;
+}