1
1
import { useState } from 'react' ;
2
- export default function Board ( ) {
2
+
3
+ export default function Game ( )
4
+ {
5
+ const [ history , setHistory ] = useState ( [ Array ( 9 ) . fill ( null ) ] ) ;
6
+ const [ currentMove , setCurrentMove ] = useState ( 0 )
7
+ const currentSquares = history [ currentMove ] ;
8
+ const xIsNext = currentMove % 2 === 0 ;
9
+
10
+ function handlePlay ( nextSquares )
11
+ {
12
+ const nextHistory = [ ...history . slice ( 0 , currentMove + 1 ) , nextSquares ] ;
13
+ setHistory ( nextHistory ) ;
14
+ setCurrentMove ( nextHistory . length - 1 ) ;
15
+ }
16
+ function jumpTo ( nextMove )
17
+ {
18
+ setCurrentMove ( nextMove ) ;
19
+ }
20
+ const moves = history . map ( ( squares , move ) => {
21
+ let description ;
22
+ if ( move > 0 ) {
23
+ description = 'Go to move #' + move ;
24
+ } else {
25
+ description = 'Go to game start' ;
26
+ }
27
+ return (
28
+ < li key = { move } >
29
+ < button onClick = { ( ) => jumpTo ( move ) } > { description } </ button >
30
+ </ li >
31
+ ) ;
32
+ } ) ;
33
+ return (
34
+ < div className = "game" >
35
+ < div className = "game-board" >
36
+ < Board xIsNext = { xIsNext } squares = { currentSquares } onPlay = { handlePlay } />
37
+ </ div >
38
+ < div className = "game-info" >
39
+ < ol > { moves } </ ol >
40
+ </ div >
41
+ </ div >
42
+ ) ;
43
+ }
44
+
45
+ function Board ( { xIsNext, squares, onPlay } ) {
46
+
47
+ function handleClick ( i )
48
+ {
49
+ if ( squares [ i ] || calculateWinner ( squares ) )
50
+ {
51
+ return ;
52
+ }
53
+ const nextSquares = squares . slice ( ) ;
54
+ if ( xIsNext )
55
+ nextSquares [ i ] = "X" ;
56
+ else
57
+ nextSquares [ i ] = "O" ;
58
+ onPlay ( nextSquares ) ;
59
+ }
60
+ const winner = calculateWinner ( squares ) ;
61
+ let status ;
62
+ if ( winner )
63
+ {
64
+ status = "Winner: " + winner ;
65
+ }
66
+ else
67
+ {
68
+ status = "Next player: " + ( xIsNext ? "X" : "O" ) ;
69
+ }
3
70
return (
4
71
< >
72
+ < div className = "status" > { status } </ div >
5
73
< div className = "board-row" >
6
- < Square />
7
- < Square />
8
- < Square />
74
+ < Square value = { squares [ 0 ] } onSquareClick = { ( ) => handleClick ( 0 ) } />
75
+ < Square value = { squares [ 1 ] } onSquareClick = { ( ) => handleClick ( 1 ) } />
76
+ < Square value = { squares [ 2 ] } onSquareClick = { ( ) => handleClick ( 2 ) } />
9
77
</ div >
10
78
< div className = "board-row" >
11
- < Square />
12
- < Square />
13
- < Square />
79
+ < Square value = { squares [ 3 ] } onSquareClick = { ( ) => handleClick ( 3 ) } />
80
+ < Square value = { squares [ 4 ] } onSquareClick = { ( ) => handleClick ( 4 ) } />
81
+ < Square value = { squares [ 5 ] } onSquareClick = { ( ) => handleClick ( 5 ) } />
14
82
</ div >
15
83
< div className = "board-row" >
16
- < Square />
17
- < Square />
18
- < Square />
84
+ < Square value = { squares [ 6 ] } onSquareClick = { ( ) => handleClick ( 6 ) } />
85
+ < Square value = { squares [ 7 ] } onSquareClick = { ( ) => handleClick ( 7 ) } />
86
+ < Square value = { squares [ 8 ] } onSquareClick = { ( ) => handleClick ( 8 ) } />
19
87
</ div >
20
88
</ >
21
89
) ;
22
90
}
23
91
24
- function Square ( )
92
+ function Square ( { value , onSquareClick } )
25
93
{
26
- const [ value , setValue ] = useState ( null ) ;
27
- function handleClick ( ) { setValue ( 'X' ) }
28
- return < button className = "square" onClick = { handleClick } > { value } </ button > ;
29
- }
94
+ return < button className = "square" onClick = { onSquareClick } > { value } </ button > ;
95
+ }
96
+
97
+ function calculateWinner ( squares )
98
+ {
99
+ const lines = [
100
+ [ 0 , 1 , 2 ] ,
101
+ [ 3 , 4 , 5 ] ,
102
+ [ 6 , 7 , 8 ] ,
103
+ [ 0 , 3 , 6 ] ,
104
+ [ 1 , 4 , 7 ] ,
105
+ [ 2 , 5 , 8 ] ,
106
+ [ 0 , 4 , 8 ] ,
107
+ [ 2 , 4 , 6 ]
108
+ ] ;
109
+ for ( let i = 0 ; i < lines . length ; i ++ )
110
+ {
111
+ const [ a , b , c ] = lines [ i ] ;
112
+ if ( squares [ a ] && squares [ a ] === squares [ b ] && squares [ a ] === squares [ c ] )
113
+ {
114
+ return squares [ a ] ;
115
+ }
116
+ }
117
+ return null ;
118
+ }
0 commit comments