reactjs-tutorial-tictactoe/src/index.js

159 lines
4.4 KiB
JavaScript
Raw Normal View History

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
2022-03-13 17:27:06 +01:00
/*TODO
Display the location for each move in the format (col, row) in the move history list.
Bold the currently selected item in the move list.
Rewrite Board to use two loops to make the squares instead of hardcoding them.
Add a toggle button that lets you sort the moves in either ascending or descending order.
When someone wins, highlight the three squares that caused the win.
When no one wins, display a message about the result being a draw.
*/
2022-03-13 17:21:52 +01:00
function Square(props) {
return (
<button className="square" onClick={props.onClick}>
{props.value}
</button>
);
}
class Board extends React.Component {
renderSquare(i) {
2022-03-13 17:21:52 +01:00
return <Square
value={this.props.squares[i]}
onClick={() => this.props.handleClick(i)}
/>;
}
render() {
return (
<div>
<div className="board-row">
{this.renderSquare(0)}
{this.renderSquare(1)}
{this.renderSquare(2)}
</div>
<div className="board-row">
{this.renderSquare(3)}
{this.renderSquare(4)}
{this.renderSquare(5)}
</div>
<div className="board-row">
{this.renderSquare(6)}
{this.renderSquare(7)}
{this.renderSquare(8)}
</div>
</div>
);
}
}
class Game extends React.Component {
2022-03-13 17:21:52 +01:00
constructor(props) {
super(props);
this.state = {
history: [{
squares: Array(9).fill(null),
}],
xIsNext: true,
currentMoveIndex: 0,
}
}
playTurn(i) {
const history = this.state.history.slice(0, this.state.currentMoveIndex + 1);
const currentState = history[history.length - 1];
if (currentState.squares[i] || calculateWinner(currentState.squares)) {
return;
}
const newSquares = [...currentState.squares];
newSquares[i] = this.state.xIsNext ? 'X' : 'O';
this.setState({
history: [...history, {
squares: newSquares,
}],
xIsNext: !this.state.xIsNext,
currentMoveIndex: history.length,
});
}
jumpTo(moveIndex) {
this.setState({
currentMoveIndex: moveIndex,
xIsNext: moveIndex % 2 === 0,
});
}
render() {
2022-03-13 17:21:52 +01:00
const history = this.state.history;
const currentState = history[this.state.currentMoveIndex];
let status;
const winner = calculateWinner(currentState.squares);
if (winner) {
status = `Winner: ${winner}`;
} else {
const nextPlayer = this.state.xIsNext ? 'X' : 'O';
status = `Next player ${nextPlayer}`;
}
const moves = history.map((state, index) => {
const description = index === 0 ?
'Go to game start' :
`Go to move #${index}`;
return (
<li key={index}>
<button onClick={() => this.jumpTo(index)}>{description}</button>
</li>
);
});
return (
<div className="game">
<div className="game-board">
2022-03-13 17:21:52 +01:00
<Board
squares={currentState.squares}
handleClick={(i) => this.playTurn(i)}
xIsNext={this.state.xIsNext}
/>
</div>
<div className="game-info">
2022-03-13 17:21:52 +01:00
<div>{status}</div>
<ol>{moves}</ol>
</div>
</div>
);
}
}
2022-03-13 17:21:52 +01:00
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;
}
// ========================================
ReactDOM.render(
2022-03-13 17:21:52 +01:00
<Game/>,
document.getElementById('root')
);
2022-03-13 17:21:52 +01:00