Skip to content

Instantly share code, notes, and snippets.

@leewc
Last active August 3, 2022 09:23
Show Gist options
  • Select an option

  • Save leewc/0f8331ddedb8cf1f86601a60b97fa11a to your computer and use it in GitHub Desktop.

Select an option

Save leewc/0f8331ddedb8cf1f86601a60b97fa11a to your computer and use it in GitHub Desktop.

Revisions

  1. leewc revised this gist Aug 3, 2022. 1 changed file with 0 additions and 10 deletions.
    10 changes: 0 additions & 10 deletions tictactoe-hooks.js
    Original file line number Diff line number Diff line change
    @@ -1,13 +1,3 @@
    // class Square extends React.Component {
    // render() {
    // return (
    // <button className="square" onClick={ () => {this.props.onClick()} }>
    // { this.props.value }
    // </button>
    // );
    // }
    // }

    function Square(props) {
    return (
    <button className="square" onClick={props.onClick}>
  2. leewc created this gist Aug 3, 2022.
    131 changes: 131 additions & 0 deletions tictactoe-hooks.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,131 @@
    // class Square extends React.Component {
    // render() {
    // return (
    // <button className="square" onClick={ () => {this.props.onClick()} }>
    // { this.props.value }
    // </button>
    // );
    // }
    // }

    function Square(props) {
    return (
    <button className="square" onClick={props.onClick}>
    {props.value}
    </button>
    )
    }

    function Board(props) {
    function renderSquare(i) {
    return <Square
    value={props.squares[i]}
    onClick={() => props.onClick(i)}
    />;
    }

    return (
    <div>
    <div className="board-row">
    {renderSquare(0)}
    {renderSquare(1)}
    {renderSquare(2)}
    </div>
    <div className="board-row">
    {renderSquare(3)}
    {renderSquare(4)}
    {renderSquare(5)}
    </div>
    <div className="board-row">
    {renderSquare(6)}
    {renderSquare(7)}
    {renderSquare(8)}
    </div>
    </div>
    );
    }

    // With learnings from https://github.com/codeSTACKr/react-tic-tac-toe-hooks/blob/master/src/components/Game.js
    function Game (props) {
    const [history, setHistory] = React.useState([Array(9).fill(null)]);
    const [stepNumber, setStepNumber] = React.useState(0);
    const [xIsNext, setXIsNext] = React.useState(true);

    //move these up here to avoid computation of winner 2x
    const current = history[stepNumber];
    const winner = calcWinner(current);

    function jumpTo(step) {
    setStepNumber(step);
    setXIsNext(step % 2 === 0);
    }

    function handleClick(i) {
    const historyPoint = history.slice(0, stepNumber + 1);
    const current = historyPoint[historyPoint.length - 1];
    // OR use the same: const current = historyPoint[stepNumber];
    const sq = current.slice();

    if (winner || sq[i]) {
    return;
    }
    sq[i] = xIsNext ? 'X' : 'O';
    // This breaks --> setHistory(historyPoint.concat(sq)); even if adding []
    setHistory([...historyPoint, sq]);

    //history.length is wrong, will go out of bounds
    setStepNumber(historyPoint.length);
    setXIsNext(!xIsNext);
    }

    const moves = history.map((step, move) => {
    const desc = move ? 'Go to move # ' + move
    : 'Go to game start';
    return (
    <li key={move}>
    <button onClick={ () => jumpTo(move) }>{desc} </button>
    </li>
    )
    })

    const status = 'Next player: ' + (xIsNext ? 'X' : 'O');

    return (
    <div className="game">
    <div className="game-board">
    <Board squares={current}
    onClick={(i) => handleClick(i)}/>
    </div>
    <div className="game-info">
    <div>{winner ? '!!! Winner:' + winner : status}</div>
    <ol>{moves}</ol>
    </div>
    </div>
    );
    }

    // ========================================

    const root = ReactDOM.createRoot(document.getElementById("root"));
    root.render(<Game />);


    function calcWinner(squares) {
    const winningLines = [
    [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 < winningLines.length; i++) {
    const [a,b,c] = winningLines[i];
    if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) {
    return squares[a];
    }
    }
    return null;
    }