import React from 'react'; import ReactDOM from 'react-dom'; import './index.css'; function Square(props) { const classNames = ['square']; if (props.isInWinLine) { classNames.push('in-win-line'); } return ( ); } function Board(props) { const rows = []; for (let y = 0; y < 3; y++) { const squares = []; for (let x = 0; x < 3; x++) { const index = y * 3 + x; squares.push( props.handleClick(index)} isInWinLine={props.winLine?.indexOf(index) >= 0} /> ); } rows.push(
{squares}
); } return (
{rows}
); } class Game extends React.Component { constructor(props) { super(props); this.state = { history: [{ squares: Array(9).fill(null), }], xIsNext: true, currentMoveIndex: 0, reverseHistoryOrder: false, } } playTurn(i) { const history = this.state.history.slice(0, this.state.currentMoveIndex + 1); const currentState = history[history.length - 1]; if (currentState.squares[i] || calculateWinState(currentState.squares)) { return; } const newSquares = [...currentState.squares]; newSquares[i] = this.state.xIsNext ? 'X' : 'O'; const playPosition = squareIndexToPosition(i); this.setState({ history: [...history, { squares: newSquares, playX: playPosition[0], playY: playPosition[1], }], xIsNext: !this.state.xIsNext, currentMoveIndex: history.length, }); } jumpTo(moveIndex) { this.setState({ currentMoveIndex: moveIndex, xIsNext: moveIndex % 2 === 0, }); } toggleReverseHistoryOrder() { this.setState({ reverseHistoryOrder: !this.state.reverseHistoryOrder, }); } render() { const history = this.state.history; const currentState = history[this.state.currentMoveIndex]; let status; const winState = calculateWinState(currentState.squares); if (winState) { status = `Winner: ${winState.winner}`; } else { const nextPlayer = this.state.xIsNext ? 'X' : 'O'; status = `Next player ${nextPlayer}`; } let moves = history.map((state, index) => { const description = index === 0 ? 'Go to game start' : `Go to move #${index} [${state.playX}, ${state.playY}]`; return (
  • ); }); if (this.state.reverseHistoryOrder) { moves = moves.reverse(); } return (
    this.playTurn(i)} xIsNext={this.state.xIsNext} winLine={winState?.line} />
    {status}
      {moves}
    ); } } function calculateWinState(squares) { const lines = [ [0, 1, 2], [3, 4, 5], [6, 7, 8], [0, 3, 6], [1, 4, 7], [2, 5, 8], [0, 4, 8], [2, 4, 6], ]; for (let i = 0; i < lines.length; i++) { const [a, b, c] = lines[i]; if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) { return {winner: squares[a], line: lines[i]}; } } if (squares.every(square => !!square)) { return {winner: 'Draw :/', line: []}; } return null; } function squareIndexToPosition(index) { return [ index % 3, Math.floor(index / 3), ]; } // ======================================== ReactDOM.render( , document.getElementById('root') );