1
- import { useReducer , useState } from 'react'
1
+ import { useReducer , useState , useCallback , useEffect } from 'react'
2
2
import './App.css'
3
3
import CanvasComponent from './components/CanvasComponent'
4
4
import ControlPanel from './components/ControlPanel'
5
5
import CodePanel from './components/CodePanel'
6
6
import { useAnimation } from './hooks/useAnimation'
7
- import { animationReducer , AnimationState } from './state/animationSlice'
7
+ import { animationReducer , AnimationState , INITIALIZE , AnimationTimeline } from './state/animationSlice'
8
8
import GitHubCorner from './components/GitHubCorner'
9
9
import BackToHot100 from './components/BackToHot100'
10
+ import MatrixFastPower from './components/MatrixFastPower'
11
+ import FormulaVisualizer from './components/FormulaVisualizer'
12
+ import SimpleDPVisualizer from './components/dp/SimpleDPVisualizer'
10
13
11
14
// 初始状态
12
15
const initialState : AnimationState = {
@@ -18,7 +21,10 @@ const initialState: AnimationState = {
18
21
matrix : [ ] ,
19
22
formula : '' ,
20
23
timeline : [ ] ,
21
- playbackSpeed : 1.0
24
+ playbackSpeed : 1.0 ,
25
+ stepStatuses : [ ] ,
26
+ values : [ ] ,
27
+ animationInProgress : false
22
28
} ;
23
29
24
30
function App ( ) {
@@ -28,6 +34,9 @@ function App() {
28
34
// 楼梯阶数配置
29
35
const [ stairsCount , setStairsCount ] = useState ( 6 ) ;
30
36
37
+ // 当前算法的时间线
38
+ const [ currentTimeline , setCurrentTimeline ] = useState < AnimationTimeline | null > ( null ) ;
39
+
31
40
// 使用动画钩子
32
41
const { restartAnimation } = useAnimation ( state , dispatch , stairsCount ) ;
33
42
@@ -41,13 +50,140 @@ function App() {
41
50
}
42
51
} ;
43
52
53
+ // 处理生成解决方案
54
+ const handleGenerateSolution = useCallback ( ( solution : {
55
+ result : number ;
56
+ timeline : AnimationTimeline [ ] ;
57
+ stepsData ?: {
58
+ stepStatuses : ( 'uncalculated' | 'calculating' | 'calculated' ) [ ] ;
59
+ values : number [ ] ;
60
+ } ;
61
+ } ) => {
62
+ console . log ( "App 收到生成的解决方案:" , {
63
+ hasResult : ! ! solution . result ,
64
+ timelineLength : solution . timeline ?. length || 0 ,
65
+ stepsDataValues : solution . stepsData ?. values ?. length || 0 ,
66
+ stepsDataStatuses : solution . stepsData ?. stepStatuses ?. length || 0
67
+ } ) ;
68
+
69
+ // 验证接收到的数据
70
+ if ( ! solution . timeline || solution . timeline . length === 0 ) {
71
+ console . error ( "警告: 接收到的解决方案没有时间线数据!" ) ;
72
+ return ;
73
+ }
74
+
75
+ // 构建有效的payload,包含合理的默认值
76
+ const payload = {
77
+ totalSteps : solution . timeline . length ,
78
+ values : solution . stepsData ?. values || [ ] ,
79
+ stepStatuses : solution . stepsData ?. stepStatuses || [ ] ,
80
+ timeline : solution . timeline
81
+ } ;
82
+
83
+ console . log ( "初始化动画状态,payload信息:" , {
84
+ totalSteps : payload . totalSteps ,
85
+ valuesLength : payload . values . length ,
86
+ statusesLength : payload . stepStatuses . length ,
87
+ timelineLength : payload . timeline . length
88
+ } ) ;
89
+
90
+ dispatch ( { type : INITIALIZE , payload } ) ;
91
+ } , [ dispatch ] ) ;
92
+
93
+ // 选择算法类型
94
+ const handleSelectAlgorithm = ( algorithm : 'dp' | 'matrix' | 'formula' ) => {
95
+ dispatch ( { type : 'animation/setCurrentAlgorithm' , payload : algorithm } ) ;
96
+ dispatch ( { type : 'animation/resetAnimation' } ) ;
97
+ setTimeout ( restartAnimation , 0 ) ;
98
+ } ;
99
+
100
+ // 更新当前时间线
101
+ useEffect ( ( ) => {
102
+ if ( state . timeline && state . timeline . length > 0 && state . currentStep < state . timeline . length ) {
103
+ setCurrentTimeline ( state . timeline [ state . currentStep ] ) ;
104
+ } else {
105
+ setCurrentTimeline ( null ) ;
106
+ }
107
+ } , [ state . timeline , state . currentStep ] ) ;
108
+
109
+ const renderVisualization = ( ) => {
110
+ switch ( state . currentAlgorithm ) {
111
+ case 'dp' :
112
+ return (
113
+ < SimpleDPVisualizer
114
+ n = { stairsCount }
115
+ state = { state }
116
+ onGenerateSolution = { handleGenerateSolution }
117
+ dispatch = { dispatch }
118
+ />
119
+ ) ;
120
+ case 'matrix' :
121
+ return (
122
+ < MatrixFastPower
123
+ n = { stairsCount }
124
+ state = { state }
125
+ currentTimeline = { currentTimeline }
126
+ />
127
+ ) ;
128
+ case 'formula' :
129
+ return (
130
+ < FormulaVisualizer
131
+ n = { stairsCount }
132
+ state = { state }
133
+ currentTimeline = { currentTimeline }
134
+ />
135
+ ) ;
136
+ default :
137
+ // 对于其他算法,暂时保留原始的可视化方式
138
+ return (
139
+ < >
140
+ < CanvasComponent
141
+ state = { state }
142
+ width = { window . innerWidth * 0.65 }
143
+ height = { window . innerHeight * 0.7 }
144
+ />
145
+ < ControlPanel state = { state } dispatch = { dispatch } />
146
+ </ >
147
+ ) ;
148
+ }
149
+ } ;
150
+
151
+ // 渲染算法选择器
152
+ const renderAlgorithmSelector = ( ) => {
153
+ const algorithms = [
154
+ { id : 'dp' , name : '动态规划' , color : '#4CAF50' } ,
155
+ { id : 'matrix' , name : '矩阵快速幂' , color : '#7E57C2' } ,
156
+ { id : 'formula' , name : '通项公式' , color : '#FFC107' }
157
+ ] ;
158
+
159
+ return (
160
+ < div className = "algorithm-selector" >
161
+ { algorithms . map ( algo => (
162
+ < button
163
+ key = { algo . id }
164
+ className = { `algorithm-button ${ state . currentAlgorithm === algo . id ? 'active' : '' } ` }
165
+ style = { {
166
+ borderColor : algo . color ,
167
+ backgroundColor : state . currentAlgorithm === algo . id ? algo . color : 'transparent' ,
168
+ color : state . currentAlgorithm === algo . id ? 'white' : algo . color
169
+ } }
170
+ onClick = { ( ) => handleSelectAlgorithm ( algo . id as 'dp' | 'matrix' | 'formula' ) }
171
+ >
172
+ { algo . name }
173
+ </ button >
174
+ ) ) }
175
+ </ div >
176
+ ) ;
177
+ } ;
178
+
44
179
return (
45
180
< div className = "app-container" >
46
181
< BackToHot100 />
47
182
< GitHubCorner />
48
183
< header className = "app-header" >
49
184
< h1 > 爬楼梯问题算法可视化</ h1 >
50
185
< div className = "stairs-config" >
186
+ { renderAlgorithmSelector ( ) }
51
187
< label >
52
188
楼梯阶数:
53
189
< input
@@ -115,12 +251,25 @@ function App() {
115
251
</ div >
116
252
117
253
< div className = "center-panel" >
118
- < CanvasComponent
119
- state = { state }
120
- width = { window . innerWidth * 0.65 }
121
- height = { window . innerHeight * 0.7 }
122
- />
123
- < ControlPanel state = { state } dispatch = { dispatch } />
254
+ { /* 标题 */ }
255
+ < h2 style = { {
256
+ textAlign : 'center' ,
257
+ color : state . currentAlgorithm === 'dp' ? '#2196F3' :
258
+ state . currentAlgorithm === 'matrix' ? '#7E57C2' :
259
+ '#FF6F00' ,
260
+ margin : '0 0 20px 0' ,
261
+ padding : '10px' ,
262
+ backgroundColor : 'white' ,
263
+ borderRadius : '8px' ,
264
+ boxShadow : '0 2px 8px rgba(0,0,0,0.1)'
265
+ } } >
266
+ { state . currentAlgorithm === 'dp' ? '动态规划解法' :
267
+ state . currentAlgorithm === 'matrix' ? '矩阵快速幂解法' :
268
+ '通项公式解法' } - 爬楼梯问题
269
+ </ h2 >
270
+
271
+ { /* 渲染具体算法可视化 */ }
272
+ { renderVisualization ( ) }
124
273
</ div >
125
274
</ main >
126
275
</ div >
0 commit comments