Created
February 9, 2017 15:58
-
-
Save quanfoo/d1589710b3c444dfcf08cd21cd261fa8 to your computer and use it in GitHub Desktop.
Revisions
-
quanfoo created this gist
Feb 9, 2017 .There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,173 @@ function Square({ value, style, onClick }) { return ( <button className="square" onClick={onClick} style={{background: style}}> {value} </button> ); } function Board({ squares, winner, onClick }) { function renderSquare(i) { let style; if (winner && winner.line.includes(i)) { style = 'red'; } return <Square value={squares[i]} key={i} onClick={() => onClick(i)} style={style}/>; } return ( <div> <div className="status">{status}</div> { Array(3).fill(null).map((val, i) => { return ( <div className="board-row" key={i}> { Array(3).fill(null).map((val, j) => { return renderSquare(i * 3 + j); }) } </div> ); }) } </div> ); } class Game extends React.Component { constructor() { super(); this.state = { history: [{ squares: Array(9).fill(null), clickIdx: 0, winnerLine: [] }], xIsNext: true, stepNumber: 0, moveOrderAsc: true, }; this.handleClick = this.handleClick.bind(this); this.jumpTo = this.jumpTo.bind(this); this.toggleOrder = this.toggleOrder.bind(this); } 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, clickIdx: i, }]), xIsNext: !this.state.xIsNext, stepNumber: this.state.stepNumber + 1, }); } jumpTo(step) { this.setState({ stepNumber: step, xIsNext: step % 2 === 1, }); } toggleOrder() { this.setState({ moveOrderAsc: !this.state.moveOrderAsc }); } render() { const { history, stepNumber, xIsNext, moveOrderAsc } = this.state; const squares = history[stepNumber].squares; const moves = history.map((step, move) => { const desc = move ? 'Move ' + getPosition(step.clickIdx) : 'Game start'; return ( <li key={move} style={{fontWeight: move === stepNumber ? 'bold' : 'normal'}}> <a href="#" onClick={() => this.jumpTo(move)}>{desc}</a> </li> ); }); if (!moveOrderAsc) moves.reverse(); const winner = calculateWinner(squares); let status; if (winner) { status = `Winner: ${winner.name}`; } else { status = `Next player: ${xIsNext ? 'X' : 'O'}`; } return ( <div> <div className="game"> <div className="game-board"> <Board squares={squares} winner={winner} onClick={(i) => this.handleClick(i)} /> </div> <div className="game-info"> <div>{status}</div> <ol>{moves}</ol> </div> </div> <button onClick={this.toggleOrder} style={{marginTop: '10px'}}> {moveOrderAsc ? 'Descending' : 'Ascending'} </button> </div> ); } } // ======================================== ReactDOM.render( <Game />, document.getElementById('container') ); 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 { name: squares[a], line: lines[i], }; } } return null; } function getPosition(index) { var row = Math.floor(index / 3) + 1; var col = index % 3 + 1; return `(${row}, ${col})`; }