Created
March 22, 2019 01:12
-
-
Save hereismari/578f38235fc3f6e984d3445a2fe27202 to your computer and use it in GitHub Desktop.
Solution for exercises proposed at https://reactjs.org/tutorial/tutorial.html
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
function Square(props) { | |
return ( | |
<button className="square" onClick={props.onClick} style={ props.highlight ? { background: 'green' } : { background: 'white' } }> | |
{props.value} | |
</button> | |
); | |
} | |
class Board extends React.Component { | |
renderSquare(i) { | |
return ( | |
<Square | |
value={this.props.squares[i]} | |
highlight={this.props.isWinnerSquares[i]} | |
onClick={() => this.props.onClick(i)} | |
/> | |
); | |
} | |
render() { | |
return ( | |
<div> | |
{ | |
[...Array(3)].map((_, i) => ( | |
<div key={i} className="board-row"> | |
{ | |
[...Array(3)].map((_, j) => this.renderSquare(3 * i + j)) | |
} | |
</div> | |
)) | |
} | |
</div> | |
); | |
} | |
} | |
class Game extends React.Component { | |
constructor(props) { | |
super(props); | |
this.state = { | |
history: [ | |
{ | |
squares: Array(9).fill(null), | |
isWinnerSquares: Array(9).fill(false), | |
moveColumn: null, | |
moveRow: null, | |
} | |
], | |
stepNumber: 0, | |
toogle: "asc", | |
xIsNext: true | |
}; | |
} | |
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], | |
positions: [a, b, c] | |
}; | |
} | |
} | |
return null; | |
} | |
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 (this.calculateWinner(squares) || squares[i]) { | |
return; | |
} | |
squares[i] = this.state.xIsNext ? "X" : "O"; | |
const winner = this.calculateWinner(squares); | |
let isWinnerSquares = Array(9).fill(false); | |
if (winner) { | |
isWinnerSquares[winner.positions[0]] = isWinnerSquares[winner.positions[1]] = isWinnerSquares[winner.positions[2]] = true; | |
} | |
this.setState({ | |
history: history.concat([ | |
{ | |
squares: squares, | |
isWinnerSquares: isWinnerSquares, | |
moveColumn: i % 3 + 1, | |
moveRow: Math.floor(i / 3) + 1, | |
} | |
]), | |
stepNumber: history.length, | |
xIsNext: !this.state.xIsNext | |
}); | |
} | |
jumpTo(step) { | |
this.setState({ | |
stepNumber: step, | |
xIsNext: (step % 2) === 0 | |
}); | |
} | |
toogle() { | |
if(this.state.toogle == "asc") { | |
this.setState({toogle: "desc"}); | |
} else { | |
this.setState({toogle: "asc"}); | |
} | |
} | |
render() { | |
const history = this.state.history; | |
const current = history[this.state.stepNumber]; | |
const winner = this.calculateWinner(current.squares); | |
const moves = history.map((step, move) => { | |
if (this.state.toogle == "desc") { | |
move = history.length - move - 1; | |
} | |
const desc = move ? | |
'Go to move #' + move + " : (" + history[move].moveRow + ", " + history[move].moveColumn + ")": | |
'Go to game start'; | |
return ( | |
<li key={move}> | |
<button onClick={() => this.jumpTo(move)} style={ this.state.stepNumber == move ? { fontWeight: 'bold' } : { fontWeight: 'normal' } }>{desc}</button> | |
</li> | |
); | |
}); | |
let status; | |
if (winner) { | |
status = "Winner: " + winner.player; | |
} else { | |
status = "Next player: " + (this.state.xIsNext ? "X" : "O"); | |
} | |
const toogleMessage = "toogle " + this.state.toogle; | |
return ( | |
<div className="game"> | |
<div className="game-board"> | |
<Board | |
squares={current.squares} | |
isWinnerSquares={current.isWinnerSquares} | |
onClick={i => this.handleClick(i)} | |
/> | |
</div> | |
<div className="game-info"> | |
<button onClick={() => this.toogle()}>{toogleMessage}</button> | |
<div>{status}</div> | |
<ol>{moves}</ol> | |
</div> | |
</div> | |
); | |
} | |
} | |
// ======================================== | |
ReactDOM.render(<Game />, document.getElementById("root")); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment