diff --git a/react-fb-tictactoe/package-lock.json b/react-fb-tictactoe/package-lock.json index 41c89eee..fae4befb 100644 --- a/react-fb-tictactoe/package-lock.json +++ b/react-fb-tictactoe/package-lock.json @@ -4028,13 +4028,6 @@ } } }, - "string_decoder": { - "version": "1.0.1", - "bundled": true, - "requires": { - "safe-buffer": "5.0.1" - } - }, "string-width": { "version": "1.0.2", "bundled": true, @@ -4044,6 +4037,13 @@ "strip-ansi": "3.0.1" } }, + "string_decoder": { + "version": "1.0.1", + "bundled": true, + "requires": { + "safe-buffer": "5.0.1" + } + }, "stringstream": { "version": "0.0.5", "bundled": true, @@ -8754,14 +8754,6 @@ "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=" }, - "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", - "requires": { - "safe-buffer": "5.1.1" - } - }, "string-length": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/string-length/-/string-length-1.0.1.tgz", @@ -8794,6 +8786,14 @@ } } }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "requires": { + "safe-buffer": "5.1.1" + } + }, "stringstream": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", diff --git a/react-fb-tictactoe/package.json b/react-fb-tictactoe/package.json index 8927e3a5..e03acde1 100644 --- a/react-fb-tictactoe/package.json +++ b/react-fb-tictactoe/package.json @@ -13,4 +13,4 @@ "test": "react-scripts test --env=jsdom", "eject": "react-scripts eject" } -} \ No newline at end of file +} diff --git a/react-fb-tictactoe/src/TicTacToe/index.js b/react-fb-tictactoe/src/TicTacToe/index.js index 56944d57..b9307b80 100644 --- a/react-fb-tictactoe/src/TicTacToe/index.js +++ b/react-fb-tictactoe/src/TicTacToe/index.js @@ -1,35 +1,28 @@ import React, { Component } from 'react'; import './TicTacToe.css' - -/* - * Changes from original tutorial - * - Here we import Component, so we can replace - * class Square extends React.Component - * with - * class Square extends Component - */ -class Square extends Component { - render() { - return ( - - ); - } +function Square(props) { + return ( + + ); } + class Board extends Component { renderSquare(i) { - return ; + return ( + this.props.onClick(i)} + /> + ); } render() { - const status = 'Next player: X'; - return (
-
{status}
{this.renderSquare(0)} {this.renderSquare(1)} @@ -50,16 +43,79 @@ class Board extends Component { } } + class Game extends Component { + constructor() { + super(); + this.state = { + history: [{ + squares: Array(9).fill(null) + }], + stepNumber: 0, + xIsNext: true + }; + } + + handleClick(i) { + const history = this.state.history.slice(0, this.state.stepNumber + 1); + const current = history[history.length - 1]; + const squares = current.squares.slice(); + if (calculateWinner(squares) || squares[i]) { + return; + } + squares[i] = this.state.xIsNext ? "X" : "O"; + this.setState({ + history: history.concat([ + { + squares: squares + } + ]), + stepNumber: history.length, + xIsNext: !this.state.xIsNext + }); + } + + jumpTo(step) { + this.setState({ + stepNumber: step, + xIsNext: (step % 2) === 0 + }); + } + render() { + const history = this.state.history; + const current = history[this.state.stepNumber]; + const winner = calculateWinner(current.squares); + + const moves = history.map((step, move) => { + const desc = move ? "Move #" + move : "Game start"; + + return ( +
  • + this.jumpTo(move)}>{desc} +
  • + ); + }); + + let status; + if (winner) { + status = 'Winner: ' + winner; + } else { + status = 'Next player: ' + (this.state.xIsNext ? 'X' : 'O'); + } + return (
    - + this.handleClick(i)} + /> +
    -
    {/* status */}
    -
      {/* todo */}
    +
    {status}
    +
      {moves}
    ); @@ -67,3 +123,23 @@ class Game extends Component { } export default Game; + +function calculateWinner(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 squares[a]; + } + } + return null; +}