版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/b954960630/article/details/86710048
一、展示:
功能:轮番下棋,能判断谁输谁赢,记录每一步棋并跳转到该步
组件:Game、Board、Square
二、源码:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Hello World</title>
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/[email protected]/babel.min.js"></script>
<link rel="stylesheet" type="text/css" href="./src/css/index.css">
</head>
<body>
<div id="root"></div>
<script type="text/babel">
//*********************************************** Square ***********************************************
function Square(props) {
let {handleClickSquare, index} = {...props};
return (
<div
className='square'
onClick={handleClickSquare}
>
{props.value}
</div>
);
}
//*********************************************** Board ***********************************************
function Board(props) {
let squares = Array(9).fill(null).map((item, index) => {
return (
<Square
key={index}
value={props.squares[index]}
handleClickSquare={() => props.handleClickSquare(index)}
/>
);
});
return (
<div className='game-board'>
{squares}
</div>
);
}
//*********************************************** Game ***********************************************
class Game extends React.Component {
constructor(props) {
super(props);
this.state = {
history:[{squares: Array(9).fill(null)}],
stepNumber: 0,
nextPlayer:true,
};
}
handleClickSquare(index) {
let {history, nextPlayer, stepNumber} = {...this.state},
squares = history[stepNumber].squares.slice(0),
historySlice = history.slice(0, stepNumber + 1);
if(squares[index] || calculateWinner(history[history.length - 1].squares)) {
return null;
}
squares[index] = nextPlayer ? 'X' : 'O';
this.setState({
history: historySlice.concat([{squares: squares}]),
stepNumber: historySlice.length,
nextPlayer: !nextPlayer,
});
}
jumpTo(step) {
this.setState({
stepNumber: step,
nextPlayer: (step % 2) === 0,
});
}
render() {
let {history, nextPlayer, stepNumber} = {...this.state},
winner = calculateWinner(history[history.length - 1].squares),
state,
moves;
moves = history.map((item,index) => {
let desc = index ? 'Go to move # ' + index : 'start move';
return (
<li key={index}>
<button onClick={() => this.jumpTo(index)}>{desc}</button>
</li>
);
});
if(winner) {
state = 'winner is : ' + winner;
}else {
state = 'Next is : ' + (nextPlayer ? 'X' : 'O');
}
return (
<div className='game'>
<Board
squares={history[stepNumber].squares}
handleClickSquare={(index) => this.handleClickSquare(index)}
/>
<div className='game-info'>
<div>{state}</div>
<ol>{moves}</ol>
</div>
</div>
);
}
}
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 squares[a];
}
}
return null;
}
</script>
</body>
</html>
./src/css/index.css:
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.game {
display: flex;
flex-direction: row;
margin: 20px;
}
.game-board,
.game-info {
display: inline-block;
}
.game-board {
width: 102px;
height: 102px;
}
.game-info {
margin-left: 40px;
}
.square{
width: 34px;
height: 34px;
line-height: 34px;
text-align: center;
font-size: 20px;
border: 1px solid #999;
float: left;
}