diff --git a/index.html b/index.html
index 0068160..0c589ec 100644
--- a/index.html
+++ b/index.html
@@ -4,7 +4,7 @@
-
Tic Tac Toe Bolt
+ Vite + React
diff --git a/src/App.css b/src/App.css
index 3bfd7ec..b9d355d 100644
--- a/src/App.css
+++ b/src/App.css
@@ -5,44 +5,38 @@
text-align: center;
}
-.board {
- display: flex;
- flex-direction: column;
- gap: 10px;
- margin-top: 1em;
+.logo {
+ height: 6em;
+ padding: 1.5em;
+ will-change: filter;
+ transition: filter 300ms;
}
-.messages {
- line-height: 1em;
+.logo:hover {
+ filter: drop-shadow(0 0 2em #646cffaa);
}
-.board-row {
- display: flex;
- flex-direction: row;
- gap: 10px;
+.logo.react:hover {
+ filter: drop-shadow(0 0 2em #61dafbaa);
}
-.board-cell {
- width: 100px;
- height: 100px;
- border: 1px solid black;
- display: flex;
- justify-content: center;
- align-items: center;
- font-size: 24px;
- cursor: pointer;
+@keyframes logo-spin {
+ from {
+ transform: rotate(0deg);
+ }
+ to {
+ transform: rotate(360deg);
+ }
}
-.game-set .board-cell {
- cursor: not-allowed;
+@media (prefers-reduced-motion: no-preference) {
+ a:nth-of-type(2) .logo {
+ animation: logo-spin infinite 20s linear;
+ }
}
-.game-set .board-cell:hover {
- background-color: unset;
+.card {
+ padding: 2em;
}
-.board-cell:hover {
- background-color: #f0f0f0;
+.read-the-docs {
+ color: #888;
}
-
-.board-cell.fading {
- color: red;
-}
\ No newline at end of file
diff --git a/src/App.tsx b/src/App.tsx
index ff66e0b..f67355a 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -1,188 +1,33 @@
-import React, { useEffect, useState } from 'react'
+import { useState } from 'react'
+import reactLogo from './assets/react.svg'
+import viteLogo from '/vite.svg'
import './App.css'
-type Symbol = 'X' | 'O';
-
-type CellState = {
- symbol?: Symbol;
- isFading?: boolean;
-};
-
-type RowState = CellState[];
-type BoardState = RowState[];
-
-type CellClickHandler = (row: number, col: number) => void;
-type CellProps = CellState & { rowIndex: number, columnIndex: number, onClick?: CellClickHandler };
-
-function Cell({ rowIndex, columnIndex, symbol, isFading, onClick }: CellProps) {
- return onClick && onClick(rowIndex, columnIndex)}>{symbol}
;
-}
-
-type RowProps = {
- index: number,
- state: RowState
- onCellClick: CellClickHandler;
-};
-
-function Row({ state, index, onCellClick }: RowProps) {
- return (
-
- {state.map((cellState: CellState, i) => )}
- |
- )
-}
-
-type BoardProps = {
- state: BoardState;
- hasWinner?: boolean;
- onCellClick: CellClickHandler;
-}
-
-function Board({ state, hasWinner, onCellClick }: BoardProps) {
- return (
-
- {state.map((row, i) => )}
-
- )
-}
-
-function hasWin(board: BoardState, size: number, row: number, column: number): boolean {
- const targetCell = board[row]?.[column];
- if (!targetCell) { return false; }
-
- let win = true;
- for (let r = 0; r < size; r++) {
- if (board[r]?.[column]?.symbol !== targetCell.symbol) {
- win = false;
- break;
- }
- }
- if (win) {
- return true;
- }
-
- win = true;
- for (let c = 0; c < size; c++) {
- if (board[row]?.[c]?.symbol !== targetCell.symbol) {
- win = false;
- break;
- }
- }
- if (win) {
- return true;
- }
- if (row !== column) {
- return false;
- }
-
-
- win = true;
- for (let i = 0; i < size; i++) {
- if (board[i]?.[i]?.symbol !== targetCell.symbol) {
- win = false;
- break;
- }
- }
-
- return win;
-}
-
-type MoveRecord = {
- row: number;
- col: number;
- player: Symbol;
-};
-
-type GameState = {
- board: BoardState;
- latestMoves:MoveRecord[];
- currentPlayer: Symbol;
- winner?: Symbol;
-}
-
-function useBoardState(size: number = 3): [GameState, { reset: ()=> void; playOn: (row: number, col: number) => boolean } ] {
- const [state, updateState] = useState({
- board: Array(size).fill(Array(size).fill({})),
- latestMoves: [],
- currentPlayer: 'O',
- });
-
- return [
- state,
- {
- reset: () => updateState({
- board: Array(size).fill(Array(size).fill({})),
- latestMoves: [],
- currentPlayer: 'O',
- }),
-
- playOn: (row: number, col: number) => {
- if (state.winner) {
- return false;
- }
-
- const targetCell = state.board[row]?.[col];
- if (!targetCell || targetCell.symbol) {
- return false;
- }
-
- const cellToFading = state.latestMoves.length >= (2*size-1) ? state.latestMoves[0] : undefined;
- const fadingRow = cellToFading?.row;
- const fadingCol = cellToFading?.col;
-
- const nextState: GameState = {
- board: state.board.map((oldRow, r) => oldRow.map((oldCell, c)=> {
- return {
- ...(oldCell.isFading ? {} : oldCell),
- ...(r===row && c===col ? { symbol: state.currentPlayer } : undefined),
- ...(r===fadingRow && c===fadingCol ? { isFading: true} : undefined),
- };
- })),
-
- latestMoves: [
- ...state.latestMoves,
- {
- row,
- col,
- player: state.currentPlayer,
- }
- ].slice(-2*size+1),
-
- currentPlayer: state.currentPlayer === 'X' ? 'O' : 'X' as Symbol,
- };
-
- if (hasWin(nextState.board, size, row, col)) {
- nextState.winner = state.currentPlayer;
- }
- updateState(nextState);
-
- return true;
- },
- },
- ];
-}
function App() {
- const [state, { playOn, reset: resetGame }] = useBoardState(5);
-
- const nextPlayer = state.currentPlayer;
- const latestCells = state.latestMoves;
- const winner = state.winner;
+ const [count, setCount] = useState(0)
return (
<>
-
-
+
+
Vite + React
+
+
setCount((count) => count + 1)}>
+ count is {count}
+
- {winner ? `Winner is ${winner}` : (<>Next player is {nextPlayer} >)}
- {latestCells.length === 0 && ("Click any cell to start")}
- {winner && Click to restart }
+ Edit src/App.jsx
and save to test HMR
+
+ Click on the Vite and React logos to learn more
+
>
)
}