import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
// 获胜判定
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],coordinate:[a,b,c]};
}
}
return null;
}
// 渲染格子
function Square(props) {
const {value,style} = props;
return (
<button
style={style}
className="square"
onClick={props.onClick}
>
{value}
</button>
);
}
// 渲染大棋盘,格子父组件,承担props
class Board extends React.Component {
renderSquare(i) {
const { squares, winnerList } = this.props;
const style = winnerList.includes(i) ? {backgroundColor: 'beige'} : {};
return <Square
key={i}
style={style}
value = {squares[i]}
onClick={() => {this.props.onClick(i)}}
/>;
}
renderBoard(row = 3,column = 3) {
return (
<div>{
Array(row).fill(null).map((itemM,m) => {
return (
<div className="board-row" key={m}>
{
Array(column).fill(null).map((itemN,n) => {
return this.renderSquare(m * 3 + n)
})
}
</div>
)
})
}</div>
)
}
render() {
return this.renderBoard();
}
}
class Game extends React.Component {
constructor(props) {
super(props);
this.state = {
squares: [],// 当前棋局布局
squaresList: [],// 记录每一步棋局布局
squareList: [],// 记录点击顺序,用于显示每一步坐标
winnerList: [],
xIsNext: true,
isAsc: true //是否升序
}
this.renderLi = this.renderLi.bind(this);
this.onClickButton = this.onClickButton.bind(this);
this.clickSquare = this.clickSquare.bind(this);
this.restartGame = this.restartGame.bind(this);
this.desc = this.desc.bind(this);
}
//desc
desc() {
const { isAsc } = this.state;
this.setState({
isAsc: !isAsc
})
}
// 重启游戏
restartGame() {
this.setState({
squares: [],
squareList: [],// 记录点击顺序
squaresList: [],
winnerList: [],
xIsNext:true
})
}
// 判断行列坐标
checkCoordinate(index) {
const x = Math.floor(index % 3);
const y = Math.floor(index / 3);
return {x,y}
}
// 点击列表按钮,跳转某一步
onClickButton(index) {
// 最后一步点击不再跳转
if(index + 1 == this.state.squaresList.length) return;
const squaresList = this.state.squaresList.slice(0, index + 1);
const length = squaresList.length;
this.setState({
squares: squaresList[index],
squaresList,
winnerList: [],
xIsNext: length % 2 === 0 // 奇数为true
})
}
// 渲染右侧li列表
renderLi() {
const { squaresList, squareList, isAsc } = this.state;
const length = squaresList.length - 1;
return (
squaresList.map((currentSquare,index) => {
const {x,y} = this.checkCoordinate(squareList[index]);
const status = `第${index+1}步`
const coordinate = `坐标:(x: ${x+1} y: ${y+1})`
const style = length === index ? {fontWeight: 'bold'} : {};
return (
<li key={index}>
<button
style = {style}
onClick={() => {this.onClickButton(index)}}
>
{status} {coordinate}
</button>
</li>
)
})
)
}
// 点击格子
clickSquare(index) {
const { xIsNext, squaresList, squareList } = this.state;
const squares = this.state.squares.slice();
const winner = calculateWinner(squares);
// 若获胜/格子存在 return
if (winner || squares[index]) return;
// 否则 1 更新squares 2 把squares加入squaresList
squares[index] = xIsNext ? 'X' : 'O';
this.setState({
squaresList: squaresList.concat([squares]),
squareList: squareList.concat([index]),
squares,
xIsNext: !xIsNext
},() => {
// 在回调中判断是否获胜,并添加获胜样式
const winner = calculateWinner(this.state.squares);
if (winner) {
this.setState({
winnerList: [...winner.coordinate]
})
}
});
}
render() {
const { squares, isAsc, winnerList, squaresList, xIsNext } = this.state;
const winner = calculateWinner(squares);
let status;
if (winner) {
status = `winner is ${winner.winner}`
} else if(squaresList.length == 9) {
status = `no winner`
} else{
status = `Next player: ${xIsNext ? 'X' : 'O'}`;
}
const ascButton = isAsc ? '降序' : '升序';
let liList = this.renderLi();
liList = isAsc ? liList : liList.reverse();
return (
<div className="game">
<div className="game-board">
<Board
squares={squares}
onClick={this.clickSquare}
winnerList={winnerList}
/>
</div>
<div className="game-info">
<button onClick={this.desc}>{ascButton}</button>
<div>{ status }</div>
<button onClick={this.restartGame}>go to start</button>
<ol>{liList}</ol>
</div>
</div>
);
}
}
// ========================================
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<Game />);
React 文档 井字格小游戏 实现
©著作权归作者所有,转载或内容合作请联系作者
- 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
- 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
- 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
推荐阅读更多精彩内容
- 本实例基于 React + ES6 + Webpack + Node 实现一个井字棋的小游戏,来进一步深刻理解 R...
- 上一期我们利用create-react-app搭建了好了一个react项目,这期我们通过跟随React官方教程--...
- 一、项目基本信息 操作系统:Windows 10 开发环境:VS2017 和 MFC 框架 项目基本信息:通过 V...
- 1. 开发环境 IDE: IntelliJ IDEA 2018.2 java环境 java 10.0.2 2018...
- 1项目介绍 1.1 开发介绍 操作系统:Windows 7 及以上版本系统 开发环境:VS2010 1.2 扫雷操...