@@ -65,6 +65,125 @@ export default function App() {
65
65
- 获胜规则
66
66
- 时间旅行,历史记录
67
67
68
+ ``` js
69
+ import { useState } from ' react' ;
70
+
71
+ function Square ({ value, onSquareClick }) {
72
+ return (
73
+ < button className= " square" onClick= {onSquareClick}>
74
+ {value}
75
+ < / button>
76
+ );
77
+ }
78
+
79
+ function Board ({ xIsNext, squares, onPlay }) {
80
+ function handleClick (i ) {
81
+ if (calculateWinner (squares) || squares[i]) {
82
+ return ;
83
+ }
84
+ const nextSquares = squares .slice ();
85
+ if (xIsNext) {
86
+ nextSquares[i] = ' X' ;
87
+ } else {
88
+ nextSquares[i] = ' O' ;
89
+ }
90
+ onPlay (nextSquares);
91
+ }
92
+
93
+ const winner = calculateWinner (squares);
94
+ let status;
95
+ if (winner) {
96
+ status = ' Winner: ' + winner;
97
+ } else {
98
+ status = ' Next player: ' + (xIsNext ? ' X' : ' O' );
99
+ }
100
+
101
+ return (
102
+ <>
103
+ < div className= " status" > {status}< / div>
104
+ < div className= " board-row" >
105
+ < Square value= {squares[0 ]} onSquareClick= {() => handleClick (0 )} / >
106
+ < Square value= {squares[1 ]} onSquareClick= {() => handleClick (1 )} / >
107
+ < Square value= {squares[2 ]} onSquareClick= {() => handleClick (2 )} / >
108
+ < / div>
109
+ < div className= " board-row" >
110
+ < Square value= {squares[3 ]} onSquareClick= {() => handleClick (3 )} / >
111
+ < Square value= {squares[4 ]} onSquareClick= {() => handleClick (4 )} / >
112
+ < Square value= {squares[5 ]} onSquareClick= {() => handleClick (5 )} / >
113
+ < / div>
114
+ < div className= " board-row" >
115
+ < Square value= {squares[6 ]} onSquareClick= {() => handleClick (6 )} / >
116
+ < Square value= {squares[7 ]} onSquareClick= {() => handleClick (7 )} / >
117
+ < Square value= {squares[8 ]} onSquareClick= {() => handleClick (8 )} / >
118
+ < / div>
119
+ < / >
120
+ );
121
+ }
122
+
123
+ export default function Game () {
124
+ const [history , setHistory ] = useState ([Array (9 ).fill (null )]);
125
+ const [currentMove , setCurrentMove ] = useState (0 );
126
+ const xIsNext = currentMove % 2 === 0 ;
127
+ const currentSquares = history[currentMove];
128
+
129
+ function handlePlay (nextSquares ) {
130
+ const nextHistory = [... history .slice (0 , currentMove + 1 ), nextSquares];
131
+ setHistory (nextHistory);
132
+ setCurrentMove (nextHistory .length - 1 );
133
+ }
134
+
135
+ function jumpTo (nextMove ) {
136
+ setCurrentMove (nextMove);
137
+ }
138
+
139
+ const moves = history .map ((squares , move ) => {
140
+ let description;
141
+ if (move > 0 ) {
142
+ description = ' Go to move #' + move;
143
+ } else {
144
+ description = ' Go to game start' ;
145
+ }
146
+ return (
147
+ < li key= {move}>
148
+ < button onClick= {() => jumpTo (move)}> {description}< / button>
149
+ < / li>
150
+ );
151
+ });
152
+
153
+ return (
154
+ < div className= " game" >
155
+ < div className= " game-board" >
156
+ < Board xIsNext= {xIsNext} squares= {currentSquares} onPlay= {handlePlay} / >
157
+ < / div>
158
+ < div className= " game-info" >
159
+ < ol> {moves}< / ol>
160
+ < / div>
161
+ < / div>
162
+ );
163
+ }
164
+
165
+ function calculateWinner (squares ) {
166
+ const lines = [
167
+ [0 , 1 , 2 ],
168
+ [3 , 4 , 5 ],
169
+ [6 , 7 , 8 ],
170
+ [0 , 3 , 6 ],
171
+ [1 , 4 , 7 ],
172
+ [2 , 5 , 8 ],
173
+ [0 , 4 , 8 ],
174
+ [2 , 4 , 6 ],
175
+ ];
176
+ for (let i = 0 ; i < lines .length ; i++ ) {
177
+ const [a , b , c ] = lines[i];
178
+ if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) {
179
+ return squares[a];
180
+ }
181
+ }
182
+ return null ;
183
+ }
184
+
185
+ ```
186
+
68
187
### 相关的链接
69
188
70
189
next.js 是 react 的框架, 自带路由、认证等功能;
0 commit comments