Last active
June 8, 2024 03:19
-
-
Save thiskevinwang/7b4d3aae2c40119493f61cf9531f600d to your computer and use it in GitHub Desktop.
Solution to Task #6 (ALL TASKS)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| .square--winning { | |
| background-color: yellow; | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import React from "react"; | |
| import ReactDOM from "react-dom"; | |
| import "./index.css"; | |
| function Square(props) { | |
| return ( | |
| <button | |
| className={"square " + (props.isWinning ? "square--winning" : null)} | |
| onClick={props.onClick} | |
| > | |
| {props.value} | |
| </button> | |
| ); | |
| } | |
| class Board extends React.Component { | |
| renderSquare(i) { | |
| return ( | |
| <Square | |
| isWinning={this.props.winningSquares.includes(i)} | |
| key={"square " + i} | |
| value={this.props.squares[i]} | |
| onClick={() => this.props.onClick(i)} | |
| /> | |
| ); | |
| } | |
| renderSquares(n) { | |
| let squares = []; | |
| for (let i = n; i < n + 3; i++) { | |
| squares.push(this.renderSquare(i)); | |
| } | |
| return squares; | |
| } | |
| renderRows(i) { | |
| return <div className="board-row">{this.renderSquares(i)}</div>; | |
| } | |
| render() { | |
| return ( | |
| <div> | |
| {this.renderRows(0)} | |
| {this.renderRows(3)} | |
| {this.renderRows(6)} | |
| </div> | |
| ); | |
| } | |
| } | |
| class Game extends React.Component { | |
| constructor(props) { | |
| super(props); | |
| this.state = { | |
| history: [ | |
| { | |
| squares: Array(9).fill(null) | |
| } | |
| ], | |
| stepNumber: 0, | |
| xIsNext: true, | |
| isDescending: true | |
| }; | |
| } | |
| handleClick(i) { | |
| const locations = [ | |
| [1, 1], | |
| [2, 1], | |
| [3, 1], | |
| [1, 2], | |
| [2, 2], | |
| [3, 2], | |
| [1, 3], | |
| [2, 3], | |
| [3, 3] | |
| ]; | |
| 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, | |
| location: locations[i] | |
| } | |
| ]), | |
| stepNumber: history.length, | |
| xIsNext: !this.state.xIsNext | |
| }); | |
| } | |
| jumpTo(step) { | |
| this.setState({ | |
| stepNumber: step, | |
| xIsNext: step % 2 === 0 | |
| }); | |
| } | |
| sortHistory() { | |
| this.setState({ | |
| isDescending: !this.state.isDescending | |
| }); | |
| } | |
| 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 | |
| ? "Go to move #" + move + " @ " + history[move].location | |
| : "Go to game start"; | |
| return ( | |
| <li key={move}> | |
| <button onClick={() => this.jumpTo(move)}> | |
| {move == this.state.stepNumber ? <b>{desc}</b> : desc} | |
| </button> | |
| </li> | |
| ); | |
| }); | |
| let status; | |
| if (winner) { | |
| status = "Winner: " + winner.player + " @ " + winner.line; | |
| } else if (!current.squares.includes(null)) { | |
| status = "draw"; | |
| } else { | |
| status = "Next player: " + (this.state.xIsNext ? "X" : "O"); | |
| } | |
| return ( | |
| <div className="game"> | |
| <div className="game-board"> | |
| <Board | |
| winningSquares={winner ? winner.line : []} | |
| squares={current.squares} | |
| onClick={i => this.handleClick(i)} | |
| /> | |
| </div> | |
| <div className="game-info"> | |
| <div>{status}</div> | |
| <ol>{this.state.isDescending ? moves : moves.reverse()}</ol> | |
| <button onClick={() => this.sortHistory()}> | |
| Sort by: {this.state.isDescending ? "Descending" : "Asending"} | |
| </button> | |
| </div> | |
| </div> | |
| ); | |
| } | |
| } | |
| // ======================================== | |
| ReactDOM.render(<Game />, document.getElementById("root")); | |
| 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 { player: squares[a], line: [a, b, c] }; | |
| } | |
| } | |
| return null; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thank you!