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 />);
网友评论