React井字棋
来源:互联网 发布:神州网络兼职平台是真的吗 编辑:程序博客网 时间:2024/06/06 03:40
井字棋
React官方文档示例WebApp
三个组件
- Square:棋盘的一小格
- Board:棋盘
- Game:游戏信息的显示和过程的监控
其中Square、Board是展示组件不负责数据交互,Game是容器组件,负责数据交互。
实现功能
- 轮流下子
- 判断胜负
- 历史纪录
- 历史纪录升降序转换
- 高亮显示获胜行
代码
index.js
import React from 'react'; import ReactDOM from 'react-dom'; import './index.css'; function Square(props) { if (props.highlight) { return ( <button className="square" onClick={() => props.onClick()} style={{color: "red"}}> {props.value} </button> ); }else { return ( <button className="square" onClick={() => props.onClick()}> {props.value} </button> ); } }
Square组件:对其属性highligt进行判断,来决定颜色是否为红色。按钮的值是他的value属性。同时还有一个onclick方法继承自父组件。
class Board extends React.Component { renderSquare(i) { return ( <Square value={this.props.squares[i]} onClick={() => this.props.onClick(i)} highlight={this.props.line.includes(i)} /> ); } render() { var rows = []; for (var i = 0; i < 3; i++) { var row = []; for (var j = 3 * i; j < 3 * i + 3; j++) { row.push(this.renderSquare(j)); } rows.push(<div className='board-row'>{row}</div>) } return ( <div> {rows} </div> ); } }
Board组件:使用renderSquare(i)方法来创建Square组件,其value值是Board组件square[i],onclick是继承自Board组件的方法,highlight是判断Board组件的line中是否有i,render方法中用两个for循环来渲染出九宫格。
class Game extends React.Component { constructor(props) { super(props); this.state = { history: [ { squares: Array(9).fill(null), lastPos:'Get Game Start' } ], stepNumber: 0, xIsNext: true, sort:true }; } handleClick(i) { const history = this.state.history.slice(0, this.state.stepNumber + 1); const current = history[history.length - 1]; const squares = current.squares.slice(); const posX = Math.ceil((i+1) / 3); const posY = (i + 1) % 3 ? (i + 1) % 3 : 3; const position = '(' + posX + ', ' + posY + ')'; if (calculateWinner(squares).winner || squares[i]) { return; } squares[i] = this.state.xIsNext ? "X" : "O"; this.setState({ history: history.concat([ { squares: squares, lastPos:squares[i] + ' To ' + position } ]), stepNumber: history.length, xIsNext: !this.state.xIsNext, }); } jumpTo(step) { this.setState({ stepNumber: step, xIsNext: (step % 2) === 0 }); } toggleSort() { this.setState({ sort:!this.state.sort, }) } render() { let history = this.state.history; const current = history[this.state.stepNumber]; const winner = calculateWinner(current.squares).winner; const line = calculateWinner(current.squares).line; if (!this.state.sort){ history = this.state.history.slice(); history.reverse(); } const moves = history.map((step, move) => { const desc = step.lastPos; if (this.state.stepNumber == move) { return ( <li key={move}> <button onClick={() => this.jumpTo(move)}><strong>{desc}</strong></button> </li> ); } else { return ( <li key={move}> <button onClick={() => this.jumpTo(move)}>{desc}</button> </li> ); } }); let status; if (winner) { status = "Winner: " + winner; } else { status = "Next player: " + (this.state.xIsNext ? "X" : "O"); } return ( <div className="game"> <div className="game-board"> <Board squares={current.squares} onClick={i => this.handleClick(i)} line={line} /> </div> <div className="game-info"> <button onClick={() => this.toggleSort()}>Sort</button> <div>{status}</div> <ol>{moves}</ol> </div> </div> ); } }
Game组件:首先看他的状态(state),一个是history数组,其中每个元素是一个对象,对象里有一个记录着棋盘形态的数组和这一步走的位置;stepNumber,记录走的步数;xIsNext判断轮到谁下子;sort判断升降序。
handleClick()方法:是最终传入Square的方法,它获得了历史纪录和这步没走之前棋局,如果已经获胜或这格已经落子,就直接返回,没有的话就计算他的位置并更新history,stepNumber,和xIsNext
render()中获取历史纪录和当前的棋局,计算胜者和获胜的棋子,判断是否需要升降序,moves对数组history进行map,如果stepNumber与索引相等,就返回加粗显示的列表,否则返回普通列表(这里注意列表项要有key值)。jumpTo()方法接受步数,并将stepNumber设置为参数,并更新xIsNext。下面通过status来显示游戏状态,最终渲染Board组件,升降序按钮,状态显示,历史记录列表。
// ======================================== 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 {winner:squares[a], line:[a, b, c]}; } } return {winner:null, line:[]}; }
总结
初次使用React开发,感觉难度是有的,一些细节了解的也不是很清楚,但是组件化开发显而易见的好处就是思路清晰,各组件联系紧密又各司其职。代码逻辑性很强也有利于后期维护和功能的升级。
- React井字棋
- React
- react
- React
- REACT
- React
- react
- react
- React
- react
- react
- React
- React
- react
- React
- react
- react
- React
- Android 自定义加载进度框
- 软件设计中的状态机
- Linux 内核里的数据结构——位数组(bitmap)
- 首次登陆系统强制修改密码
- Detective Scripts of STEGA(Version0.0)
- React井字棋
- 点击图片放大全屏加载,再次点击图片/文档回到原来位置
- 程序员的自我修养——编译和链接
- 状态机思路在程序设计中的应用
- 数据结构实验之查找七:线性之哈希表
- Linux 内核里的数据结构——双向链表(dlist)
- Android【垂直滚动广告条】仿淘宝头条1号店京东—垂直滚动广告条
- GalleryByReact
- project euler 24 Lexicographic permutations