Skip to content
This repository was archived by the owner on Sep 13, 2022. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions react-fb-tictactoe/src/TicTacToe/TicTacToe.css
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,17 @@
.game-info {
margin-left: 20px;
}


.current-move {
font-weight: bold;
}


ul {
list-style: none;
}

.win {
background-color: PaleGreen;
}
172 changes: 138 additions & 34 deletions react-fb-tictactoe/src/TicTacToe/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,61 +9,165 @@ import './TicTacToe.css'
* with
* class Square extends Component
*/
class Square extends Component {
render() {
return (
<button className="square">
{/* TODO */}
</button>
);
function Square(props) {
let btnClass = 'square';
if(props.highlight) {
btnClass += ' win';
}
return (
<button className={btnClass} onClick={props.onClick}>
{props.value}
</button>
);
}

class Board extends Component {
renderSquare(i) {
return <Square />;
}

render() {
const status = 'Next player: X';
class Board extends React.Component {

renderSquare(i) {
const highlight = this.props.winner && this.props.winner.includes(i);
return (
<div>
<div className="status">{status}</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>
<Square
value={this.props.squares[i]}
onClick={() => this.props.onClick(i)}
highlight={highlight}
/>
);
}

render() {
let rows = [];
for(let i = 0; i < 3; i++) {
let columns = [];
for(let j = 0; j < 3; j++) {
columns.push(this.renderSquare(i * 3 + j))
}
rows.push(<div className="board-row">{columns}</div>)
}
return (<div>{rows}</div>);
}
}


class Game extends Component {
constructor() {
super();
this.state = {
history: [{
squares: Array(9).fill(null),
index: null,
}],
stepNumber: 0,
xIsNext: true,
reversedOrder: false,
};
}

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,
index: i,
}]),
stepNumber: history.length,
xIsNext: !this.state.xIsNext,
});
}

handleSort() {
this.setState({
reversedOrder: !this.state.reversedOrder,
})
}


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 ' + getCoordinates(step.index) :
'Game start';
const currentMoveClass = step == current ? 'current-move' : null;
return (
<li key={move} className={currentMoveClass}>
<a href="#" onClick={() => this.jumpTo(move)}>{desc}</a>
</li>
);
});


let status;
if (winner) {
status = 'Winner: ' + current.squares[winner[0]];
} else {
status = 'Next player: ' + (this.state.xIsNext ? 'X' : 'O');
}

return (
<div className="game">
<div className="game-board">
<Board />
<Board
squares={current.squares}
onClick={(i) => this.handleClick(i)}
winner={winner}
/>
</div>
<div className="game-info">
<div>{/* status */}</div>
<ol>{/* todo */}</ol>
<div>{status}</div>
<ul>
{this.state.reversedOrder ? moves.reverse() : moves}
</ul>
<button onClick={() => this.handleSort()}>Sort moves</button>
</div>
</div>
);
}
}

export default Game;


function getCoordinates(index) {
let x = index % 3;
let y = Math.floor(index / 3);
return `(${x}, ${y})`;
}


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 lines[i];
}
}
return null;
}