Compare commits
5 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
c71152d6d1 | 5 months ago |
|
|
de6b1a125a | 5 months ago |
|
|
34dd9eb883 | 5 months ago |
|
|
33dae519ed | 5 months ago |
|
|
d7b3076e61 | 5 months ago |
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,19 @@
|
|||||||
|
1. 78 / 96 - 22
|
||||||
|
|
||||||
|
2. 15 - 17 * (49 / 15)
|
||||||
|
|
||||||
|
3. 66 + 28 / 8 + (1 / 25)
|
||||||
|
|
||||||
|
4. 16 * 2
|
||||||
|
|
||||||
|
5. 26 * (98 * 90)
|
||||||
|
|
||||||
|
6. 4 + 89 * (70 / 3)
|
||||||
|
|
||||||
|
7. 41 + 36 + 55 + 9
|
||||||
|
|
||||||
|
8. 79 * 72 - 19 * 32
|
||||||
|
|
||||||
|
9. 2 - 2
|
||||||
|
|
||||||
|
10. (32 - 82) + 16
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
1. 70^2 / 64
|
||||||
|
|
||||||
|
2. 11^2 + 31 + 85^2 - 61
|
||||||
|
|
||||||
|
3. √95 - 73^2 + 54^2
|
||||||
|
|
||||||
|
4. 53 - (√44 / 53 / 5^2) * 10^2
|
||||||
|
|
||||||
|
5. 5^2 * 75^2 / √24 - √20 + 74^2
|
||||||
|
|
||||||
|
6. √74 / 82
|
||||||
|
|
||||||
|
7. 31 * 5 * √42 / 53^2 + √19
|
||||||
|
|
||||||
|
8. 48 + 24^2 / 12^2 - 87
|
||||||
|
|
||||||
|
9. (37 * 38^2 + √82 / 27) + 32
|
||||||
|
|
||||||
|
10. 95 - √72
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
1. 47 * sin(70) * 75 - cos(16)
|
||||||
|
|
||||||
|
2. sin(65) * 38 - 16 / 68
|
||||||
|
|
||||||
|
3. 78 * sin(50) / cos(70) * tan(52)
|
||||||
|
|
||||||
|
4. (cos(70) + sin(12) + 85) - cos(46)
|
||||||
|
|
||||||
|
5. cos(60) / tan(4)
|
||||||
|
|
||||||
|
6. 70 * sin(28) * sin(7)
|
||||||
|
|
||||||
|
7. tan(74) - cos(55) - cos(42) + tan(38)
|
||||||
|
|
||||||
|
8. tan(62) + 45
|
||||||
|
|
||||||
|
9. 52 + sin(33)
|
||||||
|
|
||||||
|
10. sin(40) * 29
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
1. 5 - 41
|
||||||
|
|
||||||
|
2. 12 / (22 / 21 + 5) + 60
|
||||||
|
|
||||||
|
3. 88 * (22 * 75)
|
||||||
|
|
||||||
|
4. 5 - 23
|
||||||
|
|
||||||
|
5. 72 * 61 / 59 + 40
|
||||||
|
|
||||||
|
6. 2 * 50
|
||||||
|
|
||||||
|
7. (37 * 99) - 92 * 43
|
||||||
|
|
||||||
|
8. 85 * 88
|
||||||
|
|
||||||
|
9. 38 / 98 - 75 - 71 / 74
|
||||||
|
|
||||||
|
10. 63 / (44 - 25)
|
||||||
@ -0,0 +1,59 @@
|
|||||||
|
1. 6 + 63 - 75 - 63 / 89
|
||||||
|
|
||||||
|
2. 38 - (63 * 76) + 41
|
||||||
|
|
||||||
|
3. 31 * 90 - 8 + 28 + 19
|
||||||
|
|
||||||
|
4. 21 - 94
|
||||||
|
|
||||||
|
5. 66 + (49 / 9)
|
||||||
|
|
||||||
|
6. 36 * 30 * 74
|
||||||
|
|
||||||
|
7. 63 / 1 / 57 - (12 - 60)
|
||||||
|
|
||||||
|
8. (91 - 68 + 66) * 7 * 83
|
||||||
|
|
||||||
|
9. 68 - 47 / 15 / 84
|
||||||
|
|
||||||
|
10. 38 - 47 * 19
|
||||||
|
|
||||||
|
11. 4 * 19
|
||||||
|
|
||||||
|
12. 48 / 38 - 62
|
||||||
|
|
||||||
|
13. 27 - 13
|
||||||
|
|
||||||
|
14. 32 * 61 / 25 + 11
|
||||||
|
|
||||||
|
15. 10 - 71
|
||||||
|
|
||||||
|
16. 92 - (27 + 99 - 57)
|
||||||
|
|
||||||
|
17. 9 / (79 - 59)
|
||||||
|
|
||||||
|
18. 76 - (68 + 73 + 20)
|
||||||
|
|
||||||
|
19. 97 - 1
|
||||||
|
|
||||||
|
20. 66 - 43 * 19 / 2 / 2
|
||||||
|
|
||||||
|
21. 78 / 35 / 94 + 12 - 16
|
||||||
|
|
||||||
|
22. 54 + 96
|
||||||
|
|
||||||
|
23. 34 - 5
|
||||||
|
|
||||||
|
24. 4 - 39
|
||||||
|
|
||||||
|
25. 58 / 17 / 45 * 51
|
||||||
|
|
||||||
|
26. 3 + (71 - 43)
|
||||||
|
|
||||||
|
27. 21 - (93 - 83)
|
||||||
|
|
||||||
|
28. 46 / 10 / 20 + 42
|
||||||
|
|
||||||
|
29. 35 + (37 - 90)
|
||||||
|
|
||||||
|
30. 83 * 82 - 11
|
||||||
@ -0,0 +1,59 @@
|
|||||||
|
1. (58 + 75) / 19
|
||||||
|
|
||||||
|
2. 99 * 13 / 10
|
||||||
|
|
||||||
|
3. 97 + 77
|
||||||
|
|
||||||
|
4. (93 + 10) - 26
|
||||||
|
|
||||||
|
5. 21 + 77 - 78 / (56 - 28)
|
||||||
|
|
||||||
|
6. 97 + 19
|
||||||
|
|
||||||
|
7. 97 * (31 + 25 * 33 * 68)
|
||||||
|
|
||||||
|
8. 90 / 18 - 80 - 51
|
||||||
|
|
||||||
|
9. 53 / 28 - 39 + 21
|
||||||
|
|
||||||
|
10. 58 - 94
|
||||||
|
|
||||||
|
11. 10 - 85
|
||||||
|
|
||||||
|
12. 100 - 42 * 9 - 66 - 49
|
||||||
|
|
||||||
|
13. 22 / (19 + 65 / 17)
|
||||||
|
|
||||||
|
14. 48 + (5 + 2) - 25
|
||||||
|
|
||||||
|
15. 91 * 9 * (26 + 70) / 93
|
||||||
|
|
||||||
|
16. 20 + 3 / 42
|
||||||
|
|
||||||
|
17. 24 / 39 * 69
|
||||||
|
|
||||||
|
18. (88 + 55) + 14 * 42
|
||||||
|
|
||||||
|
19. 90 / 16 / 9 * 75
|
||||||
|
|
||||||
|
20. 84 * 65 / (84 - 70)
|
||||||
|
|
||||||
|
21. 30 * (85 / 83)
|
||||||
|
|
||||||
|
22. 89 / 15 - 55 - 60 + 37
|
||||||
|
|
||||||
|
23. (12 * 66) / 82
|
||||||
|
|
||||||
|
24. (27 + 47) / 85
|
||||||
|
|
||||||
|
25. 12 * 80 + 27 * 86 * 80
|
||||||
|
|
||||||
|
26. 47 + 88 + (45 * 29)
|
||||||
|
|
||||||
|
27. 93 + 7 + 28 + 85 / 92
|
||||||
|
|
||||||
|
28. 9 * 4 + (62 / 31)
|
||||||
|
|
||||||
|
29. 6 - 26
|
||||||
|
|
||||||
|
30. (58 * 70) + 55
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
1. 14 * 25 * (59 * 79)
|
||||||
|
|
||||||
|
2. 21 / 91 / 4 - (87 * 16)
|
||||||
|
|
||||||
|
3. 46 / 20 + 87 * 59
|
||||||
|
|
||||||
|
4. 86 / (7 * 59)
|
||||||
|
|
||||||
|
5. 85 / 35 * 30
|
||||||
|
|
||||||
|
6. 9 - 88
|
||||||
|
|
||||||
|
7. 27 + 10
|
||||||
|
|
||||||
|
8. 94 - 76 / 59
|
||||||
|
|
||||||
|
9. 37 / (5 / 89)
|
||||||
|
|
||||||
|
10. 25 * 46 + 28
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
1. (39 + 54^2 * 23) / 1 * 50
|
||||||
|
|
||||||
|
2. 69^2 - 82
|
||||||
|
|
||||||
|
3. √36 + 49
|
||||||
|
|
||||||
|
4. √44 + 45 * 95
|
||||||
|
|
||||||
|
5. 10 - 76^2 - 70^2
|
||||||
|
|
||||||
|
6. √72 * √98 * 16
|
||||||
|
|
||||||
|
7. (27^2 / 48) / 10
|
||||||
|
|
||||||
|
8. 9 + √40 - 25 / √69 / 13^2
|
||||||
|
|
||||||
|
9. 73 * (8^2 / 61 - 96)
|
||||||
|
|
||||||
|
10. √34 / (√64 * 79)
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
1. 57 / cos(76)
|
||||||
|
|
||||||
|
2. sin(5) - sin(22)
|
||||||
|
|
||||||
|
3. sin(90) + sin(66) * 79
|
||||||
|
|
||||||
|
4. (sin(42) + tan(30)) - cos(68)
|
||||||
|
|
||||||
|
5. tan(96) - tan(54) / tan(30)
|
||||||
|
|
||||||
|
6. tan(24) / 73
|
||||||
|
|
||||||
|
7. 76 + sin(86) - sin(98) * 25
|
||||||
|
|
||||||
|
8. 16 / cos(84) * 22
|
||||||
|
|
||||||
|
9. cos(77) + sin(21) * 14
|
||||||
|
|
||||||
|
10. sin(19) * cos(53) / 28
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
1. 40 * 27 + 23 - 30
|
||||||
|
|
||||||
|
2. 27 / 53
|
||||||
|
|
||||||
|
3. 55 + 18 / 51 + 70 * 20
|
||||||
|
|
||||||
|
4. 66 - 81
|
||||||
|
|
||||||
|
5. 68 + (87 / 23)
|
||||||
|
|
||||||
|
6. 48 / 62
|
||||||
|
|
||||||
|
7. (79 + 74 * 6) + 99
|
||||||
|
|
||||||
|
8. 66 * 67
|
||||||
|
|
||||||
|
9. 20 + 5 - 43 * 28 * 16
|
||||||
|
|
||||||
|
10. (46 + 78) + 1
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
1. 81 / 75 - 19
|
||||||
|
|
||||||
|
2. 95 + 44
|
||||||
|
|
||||||
|
3. 6 + 8 / 22 + (57 / 34)
|
||||||
|
|
||||||
|
4. 22 + 85 / 59
|
||||||
|
|
||||||
|
5. 60 + (30 * 8)
|
||||||
|
|
||||||
|
6. 63 - (38 / 14 * 93)
|
||||||
|
|
||||||
|
7. 64 / 88 * 54
|
||||||
|
|
||||||
|
8. 79 * (34 + 5) - 47
|
||||||
|
|
||||||
|
9. 73 - 84 * 29 + 26 - 44
|
||||||
|
|
||||||
|
10. 9 * 75 - 38 / 25 * 95
|
||||||
@ -0,0 +1,59 @@
|
|||||||
|
1. 52 + 30 + 60 - 7 / 65
|
||||||
|
|
||||||
|
2. 23 / 47 - 30
|
||||||
|
|
||||||
|
3. 36 / 9
|
||||||
|
|
||||||
|
4. 95 + 60 - 100 - 96
|
||||||
|
|
||||||
|
5. 19 * 7
|
||||||
|
|
||||||
|
6. 99 / 90 - 100 * 63 + 21
|
||||||
|
|
||||||
|
7. 63 / (85 - 71)
|
||||||
|
|
||||||
|
8. 74 * (38 * 43 * 87) / 91
|
||||||
|
|
||||||
|
9. 66 * 9
|
||||||
|
|
||||||
|
10. (93 / 61) / 62 + 45 + 72
|
||||||
|
|
||||||
|
11. 92 * 27 - 23 * 75 / 90
|
||||||
|
|
||||||
|
12. 14 / 53 + 93 * 62
|
||||||
|
|
||||||
|
13. 54 * 43 / (39 - 87 + 57)
|
||||||
|
|
||||||
|
14. 15 * 35 * 2 * 87
|
||||||
|
|
||||||
|
15. 1 / 70 + (26 * 63)
|
||||||
|
|
||||||
|
16. 74 / (1 / 42 / 83) - 21
|
||||||
|
|
||||||
|
17. 79 - 26 - 36 + (85 + 4)
|
||||||
|
|
||||||
|
18. 61 + (57 / 14 - 47) * 47
|
||||||
|
|
||||||
|
19. 3 + 96
|
||||||
|
|
||||||
|
20. 13 / 71 + 82 / (78 + 34)
|
||||||
|
|
||||||
|
21. 82 - 18
|
||||||
|
|
||||||
|
22. 77 / 93 * 8 * 8
|
||||||
|
|
||||||
|
23. 30 + 16 - 32 + 22 + 50
|
||||||
|
|
||||||
|
24. 34 * (7 - 14 - 44)
|
||||||
|
|
||||||
|
25. 9 - 23 / (37 * 28)
|
||||||
|
|
||||||
|
26. 8 / 78
|
||||||
|
|
||||||
|
27. 81 + 18 / (34 + 28)
|
||||||
|
|
||||||
|
28. 60 + 76 * 10 - 27
|
||||||
|
|
||||||
|
29. 51 - (62 / 92 * 12)
|
||||||
|
|
||||||
|
30. 53 * 88
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
1. √27 / 1^2
|
||||||
|
|
||||||
|
2. 68 / √67
|
||||||
|
|
||||||
|
3. √52 / 59^2 / √95 + 37
|
||||||
|
|
||||||
|
4. 49 * (√15 + 5^2)
|
||||||
|
|
||||||
|
5. √61 + 84^2
|
||||||
|
|
||||||
|
6. √32 - 39^2 * 63^2 * 92^2 / √38
|
||||||
|
|
||||||
|
7. √92 + 24^2 + 91
|
||||||
|
|
||||||
|
8. √57 * 82^2 - 18 - 4^2 * √88
|
||||||
|
|
||||||
|
9. 20 - 76 + 29 * √88 * 85
|
||||||
|
|
||||||
|
10. √95 + 3^2
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
1. tan(19) - sin(59) + cos(77)
|
||||||
|
|
||||||
|
2. cos(36) / tan(52) + tan(21)
|
||||||
|
|
||||||
|
3. (1 - 17 * 45 - cos(30)) + 68
|
||||||
|
|
||||||
|
4. 30 + cos(93) - 94
|
||||||
|
|
||||||
|
5. 26 * (sin(13) / cos(33)) - sin(28)
|
||||||
|
|
||||||
|
6. tan(82) - 7 - 33 * cos(86)
|
||||||
|
|
||||||
|
7. sin(99) * 97
|
||||||
|
|
||||||
|
8. 41 + tan(8) + tan(96) + 23 / sin(37)
|
||||||
|
|
||||||
|
9. 21 + cos(59)
|
||||||
|
|
||||||
|
10. tan(56) * 36 * sin(37) + 77
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
1. 31 * (35 + 41)
|
||||||
|
|
||||||
|
2. 20 + 42 / 41 / (83 + 75)
|
||||||
|
|
||||||
|
3. 50 - 89
|
||||||
|
|
||||||
|
4. 42 * 55
|
||||||
|
|
||||||
|
5. 93 / 14 + 6 / 28
|
||||||
|
|
||||||
|
6. (14 / 64) + 94
|
||||||
|
|
||||||
|
7. 99 * 38 - 33 / 57 * 84
|
||||||
|
|
||||||
|
8. 46 - 23 / 94 - (28 - 45)
|
||||||
|
|
||||||
|
9. 49 + 23
|
||||||
|
|
||||||
|
10. 78 + (94 / 21 / 65)
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
1. ( 18 / 41 ) + 99
|
||||||
|
|
||||||
|
2. 90 + 68 - ( 36 / 50 + 47 )
|
||||||
|
|
||||||
|
3. 98 - ( 87 + 3 / 44 )
|
||||||
|
|
||||||
|
4. 76 * 44 - 23 * 81 / 33
|
||||||
|
|
||||||
|
5. 69 * 4 * 73 + 47 - 47
|
||||||
|
|
||||||
|
6. 94 + 59
|
||||||
|
|
||||||
|
7. 62 - 62 + 22
|
||||||
|
|
||||||
|
8. 42 * 38 * 77 + 10
|
||||||
|
|
||||||
|
9. 3 - ( 3 / 49 ) / 10
|
||||||
|
|
||||||
|
10. 80 + 9 / 13 + 90
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
1. 37 - 37
|
||||||
|
|
||||||
|
2. 48 - 8 + 15 + 99 + 48
|
||||||
|
|
||||||
|
3. 55 * 64 * 67 + 11 + 11
|
||||||
|
|
||||||
|
4. 88 * 44
|
||||||
|
|
||||||
|
5. 44 - 44
|
||||||
|
|
||||||
|
6. ( 71 - 16 ) / 64
|
||||||
|
|
||||||
|
7. 27 - 27
|
||||||
|
|
||||||
|
8. ( 33 / 51 ) * 83
|
||||||
|
|
||||||
|
9. 93 / 58
|
||||||
|
|
||||||
|
10. 99 * 52
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
1. 77 * ( 87 / 13 + 74 )
|
||||||
|
|
||||||
|
2. 95 - 4 * 16
|
||||||
|
|
||||||
|
3. 28 / ( 51 + 88 )
|
||||||
|
|
||||||
|
4. 56 * 30
|
||||||
|
|
||||||
|
5. 67 + ( 53 - 53 )
|
||||||
|
|
||||||
|
6. ( 67 / 78 + 92 ) / 24 * 5
|
||||||
|
|
||||||
|
7. 10 + 60 / 96
|
||||||
|
|
||||||
|
8. 87 + 48 / 85
|
||||||
|
|
||||||
|
9. 55 / 79 + 72
|
||||||
|
|
||||||
|
10. ( 88 + 48 ) - 48
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
1. √42 + √99
|
||||||
|
|
||||||
|
2. √85 - 9^2 / 4 * 89 * 49^2
|
||||||
|
|
||||||
|
3. 7^2 - 7^2 / (17^2 / √96)
|
||||||
|
|
||||||
|
4. √32 / 92 - √37 + 20
|
||||||
|
|
||||||
|
5. 75 * √93
|
||||||
|
|
||||||
|
6. 29 / (24^2 + 46 / 89)
|
||||||
|
|
||||||
|
7. √56 * 17^2 + √80
|
||||||
|
|
||||||
|
8. 95^2 - 43 - √77 * 13 * √60
|
||||||
|
|
||||||
|
9. 1^2 + 9^2
|
||||||
|
|
||||||
|
10. (56^2 - 24) * 71^2
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
Manifest-Version: 1.0
|
||||||
|
Main-Class: ui.MathLearningApp
|
||||||
|
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
package model;
|
||||||
|
|
||||||
|
public enum Grade {
|
||||||
|
primary,
|
||||||
|
middle,
|
||||||
|
high
|
||||||
|
}
|
||||||
@ -0,0 +1,61 @@
|
|||||||
|
package model;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public abstract class Student {
|
||||||
|
protected String name;
|
||||||
|
protected String password;
|
||||||
|
protected String path;
|
||||||
|
protected Random random;
|
||||||
|
|
||||||
|
public Student(String name, String password, String path) {
|
||||||
|
this.name = name;
|
||||||
|
this.password = password;
|
||||||
|
this.path = path;
|
||||||
|
this.random = new Random();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成有效的括号位置
|
||||||
|
* 确保括号不会包围整个表达式
|
||||||
|
*
|
||||||
|
* @param operands 操作数数量
|
||||||
|
* @return 包含起始和结束位置的数组 [parenStart, parenEnd]
|
||||||
|
*/
|
||||||
|
protected int[] bracketMaker(int operands) {
|
||||||
|
boolean useParen = operands > 2 && random.nextBoolean();
|
||||||
|
int parenStart = 0;
|
||||||
|
int parenEnd = operands - 1;
|
||||||
|
|
||||||
|
while (parenStart == 0 && parenEnd == operands - 1) {
|
||||||
|
parenStart = useParen ? random.nextInt(operands - 1) : -2;
|
||||||
|
parenEnd = useParen ? random.nextInt(operands - 1 - parenStart) + parenStart + 1 : -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new int[]{parenStart, parenEnd};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 随机选择特殊操作符的位置
|
||||||
|
*
|
||||||
|
* @param operands 操作数数量
|
||||||
|
* @return 标记特殊操作符位置的布尔数组
|
||||||
|
*/
|
||||||
|
protected boolean[] randomMaker(int operands) {
|
||||||
|
int specialNumber = Math.min(operands, random.nextInt(operands) + 1);
|
||||||
|
boolean[] specialOpFlags = new boolean[operands];
|
||||||
|
|
||||||
|
for (int i = 0; i < specialNumber; i++) {
|
||||||
|
int pos;
|
||||||
|
do {
|
||||||
|
pos = random.nextInt(operands);
|
||||||
|
} while (specialOpFlags[pos]);
|
||||||
|
specialOpFlags[pos] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return specialOpFlags;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract String makeOneQuestion();
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,159 @@
|
|||||||
|
package ui;
|
||||||
|
|
||||||
|
import model.UserManager;
|
||||||
|
import javax.swing.BorderFactory;
|
||||||
|
import javax.swing.JButton;
|
||||||
|
import javax.swing.JDialog;
|
||||||
|
import javax.swing.JLabel;
|
||||||
|
import javax.swing.JOptionPane;
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
import javax.swing.JPasswordField;
|
||||||
|
import java.awt.Dimension;
|
||||||
|
import java.awt.Font;
|
||||||
|
import java.awt.Frame;
|
||||||
|
import java.awt.GridBagConstraints;
|
||||||
|
import java.awt.GridBagLayout;
|
||||||
|
import java.awt.Insets;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改密码对话框
|
||||||
|
* 用户在登录状态下可以修改密码
|
||||||
|
*/
|
||||||
|
public class ChangePasswordDialog extends JDialog {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
private static final Pattern PASSWORD_PATTERN =
|
||||||
|
Pattern.compile("^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)[a-zA-Z0-9]{6,10}$");
|
||||||
|
|
||||||
|
private final JPasswordField oldPasswordField;
|
||||||
|
private final JPasswordField newPassword1Field;
|
||||||
|
private final JPasswordField newPassword2Field;
|
||||||
|
private final JButton confirmButton;
|
||||||
|
private final UserManager userManager;
|
||||||
|
private final String email;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造修改密码对话框
|
||||||
|
*
|
||||||
|
* @param parent 父窗口
|
||||||
|
* @param email 用户邮箱
|
||||||
|
*/
|
||||||
|
public ChangePasswordDialog(Frame parent, String email) {
|
||||||
|
super(parent, "修改密码", true);
|
||||||
|
this.email = email;
|
||||||
|
this.userManager = new UserManager();
|
||||||
|
|
||||||
|
setSize(600, 360);
|
||||||
|
setLocationRelativeTo(parent);
|
||||||
|
setResizable(true);
|
||||||
|
|
||||||
|
JPanel panel = new JPanel(new GridBagLayout());
|
||||||
|
panel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
|
||||||
|
GridBagConstraints gbc = new GridBagConstraints();
|
||||||
|
gbc.insets = new Insets(5, 5, 5, 5);
|
||||||
|
gbc.fill = GridBagConstraints.HORIZONTAL;
|
||||||
|
|
||||||
|
JLabel infoLabel = new JLabel("<html>新密码要求:<br>" +
|
||||||
|
"1. 长度 6-10位<br>" +
|
||||||
|
"2. 必须包含大写字母<br>" +
|
||||||
|
"3. 必须包含小写字母<br>" +
|
||||||
|
"4. 必须包含数字<br>" +
|
||||||
|
"5. 不能包含特殊字符</html>");
|
||||||
|
infoLabel.setFont(new Font("微软雅黑", Font.PLAIN, 11));
|
||||||
|
gbc.gridx = 0;
|
||||||
|
gbc.gridy = 0;
|
||||||
|
gbc.gridwidth = 2;
|
||||||
|
panel.add(infoLabel, gbc);
|
||||||
|
|
||||||
|
gbc.gridwidth = 1;
|
||||||
|
gbc.gridy = 1;
|
||||||
|
panel.add(new JLabel("原密码:"), gbc);
|
||||||
|
|
||||||
|
oldPasswordField = new JPasswordField(20);
|
||||||
|
gbc.gridx = 1;
|
||||||
|
gbc.weightx = 1.0;
|
||||||
|
panel.add(oldPasswordField, gbc);
|
||||||
|
gbc.weightx = 0.0;
|
||||||
|
|
||||||
|
gbc.gridx = 0;
|
||||||
|
gbc.gridy = 2;
|
||||||
|
panel.add(new JLabel("新密码:"), gbc);
|
||||||
|
|
||||||
|
newPassword1Field = new JPasswordField(20);
|
||||||
|
gbc.gridx = 1;
|
||||||
|
gbc.weightx = 1.0;
|
||||||
|
panel.add(newPassword1Field, gbc);
|
||||||
|
gbc.weightx = 0.0;
|
||||||
|
|
||||||
|
gbc.gridx = 0;
|
||||||
|
gbc.gridy = 3;
|
||||||
|
panel.add(new JLabel("确认新密码:"), gbc);
|
||||||
|
|
||||||
|
newPassword2Field = new JPasswordField(20);
|
||||||
|
gbc.gridx = 1;
|
||||||
|
gbc.weightx = 1.0;
|
||||||
|
panel.add(newPassword2Field, gbc);
|
||||||
|
gbc.weightx = 0.0;
|
||||||
|
|
||||||
|
confirmButton = new JButton("确认修改");
|
||||||
|
confirmButton.setPreferredSize(new Dimension(120, 30));
|
||||||
|
gbc.gridx = 0;
|
||||||
|
gbc.gridy = 4;
|
||||||
|
gbc.gridwidth = 2;
|
||||||
|
gbc.anchor = GridBagConstraints.CENTER;
|
||||||
|
panel.add(confirmButton, gbc);
|
||||||
|
|
||||||
|
add(panel);
|
||||||
|
|
||||||
|
confirmButton.addActionListener(e -> handleConfirm());
|
||||||
|
getRootPane().setDefaultButton(confirmButton);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理确认修改
|
||||||
|
*/
|
||||||
|
private void handleConfirm() {
|
||||||
|
String oldPassword = new String(oldPasswordField.getPassword());
|
||||||
|
String newPassword1 = new String(newPassword1Field.getPassword());
|
||||||
|
String newPassword2 = new String(newPassword2Field.getPassword());
|
||||||
|
|
||||||
|
if (oldPassword.isEmpty() || newPassword1.isEmpty() ||
|
||||||
|
newPassword2.isEmpty()) {
|
||||||
|
showError("所有字段都不能为空");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!newPassword1.equals(newPassword2)) {
|
||||||
|
showError("两次输入的新密码不一致");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!PASSWORD_PATTERN.matcher(newPassword1).matches()) {
|
||||||
|
showError("新密码不符合要求:\n" +
|
||||||
|
"长度6-10位, 必须包含大小写字母和数字, 且不能包含特殊字符");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (userManager.changePassword(email, oldPassword, newPassword1)) {
|
||||||
|
JOptionPane.showMessageDialog(this,
|
||||||
|
"密码修改成功!",
|
||||||
|
"成功",
|
||||||
|
JOptionPane.INFORMATION_MESSAGE);
|
||||||
|
dispose();
|
||||||
|
} else {
|
||||||
|
showError("原密码错误");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 显示错误信息
|
||||||
|
*
|
||||||
|
* @param message 错误消息
|
||||||
|
*/
|
||||||
|
private void showError(String message) {
|
||||||
|
JOptionPane.showMessageDialog(this,
|
||||||
|
message,
|
||||||
|
"错误",
|
||||||
|
JOptionPane.ERROR_MESSAGE);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
package ui;
|
||||||
|
|
||||||
|
import javax.swing.SwingUtilities;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数学学习软件主入口
|
||||||
|
*
|
||||||
|
* @author 结对项目
|
||||||
|
* @version 1.0
|
||||||
|
*/
|
||||||
|
public class MathLearningApp {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 程序主入口
|
||||||
|
*
|
||||||
|
* @param args 命令行参数
|
||||||
|
*/
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SwingUtilities.invokeLater(() -> {
|
||||||
|
LoginFrame loginFrame = new LoginFrame();
|
||||||
|
loginFrame.setVisible(true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,215 @@
|
|||||||
|
package ui;
|
||||||
|
|
||||||
|
import model.Grade;
|
||||||
|
import model.UserManager;
|
||||||
|
import javax.swing.BorderFactory;
|
||||||
|
import javax.swing.JButton;
|
||||||
|
import javax.swing.JComboBox;
|
||||||
|
import javax.swing.JDialog;
|
||||||
|
import javax.swing.JLabel;
|
||||||
|
import javax.swing.JOptionPane;
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
import javax.swing.JPasswordField;
|
||||||
|
import javax.swing.JTextField;
|
||||||
|
import java.awt.Dimension;
|
||||||
|
import java.awt.Frame;
|
||||||
|
import java.awt.Font;
|
||||||
|
import java.awt.GridBagConstraints;
|
||||||
|
import java.awt.GridBagLayout;
|
||||||
|
import java.awt.Insets;
|
||||||
|
import java.io.Serial;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 密码设置对话框
|
||||||
|
* 用于新用户注册时设置密码和选择年级
|
||||||
|
*/
|
||||||
|
public class PasswordSetupDialog extends JDialog {
|
||||||
|
@Serial
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
private static final Pattern PASSWORD_PATTERN =
|
||||||
|
Pattern.compile("^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)[a-zA-Z0-9]{6,10}$");
|
||||||
|
|
||||||
|
private final JTextField usernameField;
|
||||||
|
private final JPasswordField password1Field;
|
||||||
|
private final JPasswordField password2Field;
|
||||||
|
private final JComboBox<String> gradeComboBox;
|
||||||
|
private final JButton confirmButton;
|
||||||
|
private final UserManager userManager;
|
||||||
|
private final String email;
|
||||||
|
private boolean registrationComplete;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造密码设置对话框
|
||||||
|
*
|
||||||
|
* @param parent 父窗口
|
||||||
|
* @param userManager 用户管理器
|
||||||
|
* @param email 用户邮箱
|
||||||
|
*/
|
||||||
|
public PasswordSetupDialog(Frame parent, UserManager userManager, String email) {
|
||||||
|
super(parent, "设置密码和用户名", true);
|
||||||
|
this.userManager = userManager;
|
||||||
|
this.email = email;
|
||||||
|
this.registrationComplete = false;
|
||||||
|
|
||||||
|
setSize(600, 420);
|
||||||
|
setLocationRelativeTo(parent);
|
||||||
|
setResizable(true);
|
||||||
|
|
||||||
|
JPanel panel = new JPanel(new GridBagLayout());
|
||||||
|
panel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
|
||||||
|
GridBagConstraints gbc = new GridBagConstraints();
|
||||||
|
gbc.insets = new Insets(5, 5, 5, 5);
|
||||||
|
gbc.fill = GridBagConstraints.HORIZONTAL;
|
||||||
|
|
||||||
|
JLabel infoLabel = new JLabel("<html>密码要求:<br>" +
|
||||||
|
"1. 长度 6-10位<br>" +
|
||||||
|
"2. 必须包含大写字母<br>" +
|
||||||
|
"3. 必须包含小写字母<br>" +
|
||||||
|
"4. 必须包含数字<br>" +
|
||||||
|
"5. 不能包含其他特殊字符</html>");
|
||||||
|
infoLabel.setFont(new Font("微软雅黑", Font.PLAIN, 11));
|
||||||
|
gbc.gridx = 0;
|
||||||
|
gbc.gridy = 0;
|
||||||
|
gbc.gridwidth = 2;
|
||||||
|
panel.add(infoLabel, gbc);
|
||||||
|
|
||||||
|
gbc.gridwidth = 1;
|
||||||
|
gbc.gridy = 1;
|
||||||
|
panel.add(new JLabel("输入密码:"), gbc);
|
||||||
|
|
||||||
|
password1Field = new JPasswordField(20);
|
||||||
|
gbc.gridx = 1;
|
||||||
|
gbc.weightx = 1.0;
|
||||||
|
panel.add(password1Field, gbc);
|
||||||
|
gbc.weightx = 0.0;
|
||||||
|
|
||||||
|
gbc.gridx = 0;
|
||||||
|
gbc.gridy = 2;
|
||||||
|
panel.add(new JLabel("确认密码:"), gbc);
|
||||||
|
|
||||||
|
password2Field = new JPasswordField(20);
|
||||||
|
gbc.gridx = 1;
|
||||||
|
gbc.weightx = 1.0;
|
||||||
|
panel.add(password2Field, gbc);
|
||||||
|
gbc.weightx = 0.0;
|
||||||
|
|
||||||
|
gbc.gridx = 0;
|
||||||
|
gbc.gridy = 3;
|
||||||
|
panel.add(new JLabel("设置用户名:"), gbc);
|
||||||
|
|
||||||
|
usernameField = new JTextField(20);
|
||||||
|
gbc.gridx = 1;
|
||||||
|
gbc.weightx = 1.0;
|
||||||
|
panel.add(usernameField, gbc);
|
||||||
|
gbc.weightx = 0.0;
|
||||||
|
|
||||||
|
gbc.gridx = 0;
|
||||||
|
gbc.gridy = 4;
|
||||||
|
panel.add(new JLabel("选择年级:"), gbc);
|
||||||
|
|
||||||
|
String[] grades = {"小学", "初中", "高中"};
|
||||||
|
gradeComboBox = new JComboBox<>(grades);
|
||||||
|
gbc.gridx = 1;
|
||||||
|
gbc.weightx = 1.0;
|
||||||
|
panel.add(gradeComboBox, gbc);
|
||||||
|
gbc.weightx = 0.0;
|
||||||
|
|
||||||
|
confirmButton = new JButton("确认注册");
|
||||||
|
confirmButton.setPreferredSize(new Dimension(120, 30));
|
||||||
|
gbc.gridx = 0;
|
||||||
|
gbc.gridy = 5;
|
||||||
|
gbc.gridwidth = 2;
|
||||||
|
gbc.anchor = GridBagConstraints.CENTER;
|
||||||
|
panel.add(confirmButton, gbc);
|
||||||
|
|
||||||
|
add(panel);
|
||||||
|
|
||||||
|
confirmButton.addActionListener(e -> handleConfirm());
|
||||||
|
getRootPane().setDefaultButton(confirmButton);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理确认注册
|
||||||
|
*/
|
||||||
|
private void handleConfirm() {
|
||||||
|
String password1 = new String(password1Field.getPassword());
|
||||||
|
String password2 = new String(password2Field.getPassword());
|
||||||
|
String username = usernameField.getText().trim();
|
||||||
|
|
||||||
|
if (username.isEmpty() || password1.isEmpty() || password2.isEmpty()) {
|
||||||
|
showError("用户名和密码不能为空");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (userManager.usernameExists(username)) {
|
||||||
|
showError("该用户名已被使用,请更换一个");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!password1.equals(password2)) {
|
||||||
|
showError("两次输入的密码不一致");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!PASSWORD_PATTERN.matcher(password1).matches()) {
|
||||||
|
showError("密码不符合要求:\n" +
|
||||||
|
"长度6-10位, 必须包含大小写字母和数字, 且不能包含特殊字符");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Grade gradeType = getSelectedGradeType();
|
||||||
|
boolean success = userManager.register(email, password1, gradeType, username);
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
JOptionPane.showMessageDialog(this,
|
||||||
|
"注册成功!请返回登录。",
|
||||||
|
"成功",
|
||||||
|
JOptionPane.INFORMATION_MESSAGE);
|
||||||
|
registrationComplete = true;
|
||||||
|
dispose();
|
||||||
|
} else {
|
||||||
|
showError("注册失败,该邮箱可能已被注册");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取选择的年级类型
|
||||||
|
*
|
||||||
|
* @return 年级类型
|
||||||
|
*/
|
||||||
|
private Grade getSelectedGradeType() {
|
||||||
|
String selected = (String) gradeComboBox.getSelectedItem();
|
||||||
|
switch (selected) {
|
||||||
|
case "小学":
|
||||||
|
return Grade.primary;
|
||||||
|
case "初中":
|
||||||
|
return Grade.middle;
|
||||||
|
case "高中":
|
||||||
|
return Grade.high;
|
||||||
|
default:
|
||||||
|
return Grade.primary;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 显示错误信息
|
||||||
|
*
|
||||||
|
* @param message 错误消息
|
||||||
|
*/
|
||||||
|
private void showError(String message) {
|
||||||
|
JOptionPane.showMessageDialog(this,
|
||||||
|
message,
|
||||||
|
"错误",
|
||||||
|
JOptionPane.ERROR_MESSAGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查注册是否完成
|
||||||
|
*
|
||||||
|
* @return 注册是否完成
|
||||||
|
*/
|
||||||
|
public boolean isRegistrationComplete() {
|
||||||
|
return registrationComplete;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,210 @@
|
|||||||
|
package ui;
|
||||||
|
|
||||||
|
import model.Grade;
|
||||||
|
import model.Question;
|
||||||
|
import model.QuestionMaker;
|
||||||
|
|
||||||
|
import javax.swing.BorderFactory;
|
||||||
|
import javax.swing.ButtonGroup;
|
||||||
|
import javax.swing.JButton;
|
||||||
|
import javax.swing.JFrame;
|
||||||
|
import javax.swing.JLabel;
|
||||||
|
import javax.swing.JOptionPane;
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
import javax.swing.JRadioButton;
|
||||||
|
import java.awt.BorderLayout;
|
||||||
|
import java.awt.Dimension;
|
||||||
|
import java.awt.FlowLayout;
|
||||||
|
import java.awt.Font;
|
||||||
|
import java.awt.GridBagConstraints;
|
||||||
|
import java.awt.GridBagLayout;
|
||||||
|
import java.awt.Insets;
|
||||||
|
import java.io.Serial;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 答题界面
|
||||||
|
* 显示题目和选项,接收用户答案
|
||||||
|
*/
|
||||||
|
public class QuizFrame extends JFrame {
|
||||||
|
@Serial
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private final String email;
|
||||||
|
private final Grade gradeType;
|
||||||
|
private final List<Question> questions;
|
||||||
|
private int currentIndex;
|
||||||
|
private int correctCount;
|
||||||
|
|
||||||
|
private JLabel questionLabel;
|
||||||
|
private JLabel progressLabel;
|
||||||
|
private JRadioButton[] optionButtons;
|
||||||
|
private JButton submitButton;
|
||||||
|
private ButtonGroup optionGroup;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造答题界面
|
||||||
|
*
|
||||||
|
* @param email 用户邮箱
|
||||||
|
* @param gradeType 年级类型
|
||||||
|
* @param questionCount 题目数量
|
||||||
|
*/
|
||||||
|
public QuizFrame(String email, Grade gradeType, int questionCount) {
|
||||||
|
this.email = email;
|
||||||
|
this.gradeType = gradeType;
|
||||||
|
this.currentIndex = 0;
|
||||||
|
this.correctCount = 0;
|
||||||
|
|
||||||
|
QuestionMaker generator = new QuestionMaker();
|
||||||
|
this.questions = generator.makeQuestions(gradeType, questionCount, email);
|
||||||
|
|
||||||
|
if (questions.isEmpty()) {
|
||||||
|
JOptionPane.showMessageDialog(null,
|
||||||
|
"生成题目失败,返回主界面",
|
||||||
|
"错误",
|
||||||
|
JOptionPane.ERROR_MESSAGE);
|
||||||
|
returnToGradeSelection();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setTitle("数学学习软件 - 答题");
|
||||||
|
setSize(900, 600);
|
||||||
|
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||||
|
setLocationRelativeTo(null);
|
||||||
|
setResizable(true);
|
||||||
|
|
||||||
|
JPanel mainPanel = new JPanel(new BorderLayout(10, 10));
|
||||||
|
mainPanel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
|
||||||
|
|
||||||
|
progressLabel = new JLabel("", JLabel.CENTER);
|
||||||
|
progressLabel.setFont(new Font("微软雅黑", Font.BOLD, 14));
|
||||||
|
mainPanel.add(progressLabel, BorderLayout.NORTH);
|
||||||
|
|
||||||
|
JPanel centerPanel = new JPanel(new GridBagLayout());
|
||||||
|
GridBagConstraints gbc = new GridBagConstraints();
|
||||||
|
gbc.insets = new Insets(10, 10, 10, 10);
|
||||||
|
gbc.fill = GridBagConstraints.HORIZONTAL;
|
||||||
|
|
||||||
|
// 新增:答案格式提示
|
||||||
|
JLabel answerFormatLabel = new JLabel("注意:所有计算结果的答案均保留两位小数。", JLabel.CENTER);
|
||||||
|
answerFormatLabel.setFont(new Font("微软雅黑", Font.ITALIC, 12));
|
||||||
|
gbc.gridx = 0;
|
||||||
|
gbc.gridy = 0;
|
||||||
|
gbc.gridwidth = 2;
|
||||||
|
centerPanel.add(answerFormatLabel, gbc);
|
||||||
|
|
||||||
|
gbc.gridx = 0;
|
||||||
|
gbc.gridy = 1;
|
||||||
|
gbc.gridwidth = 2;
|
||||||
|
|
||||||
|
questionLabel = new JLabel();
|
||||||
|
questionLabel.setFont(new Font("Cambria Math", Font.PLAIN, 18));
|
||||||
|
questionLabel.setBorder(BorderFactory.createEmptyBorder(10, 10, 20, 10));
|
||||||
|
centerPanel.add(questionLabel, gbc);
|
||||||
|
|
||||||
|
optionGroup = new ButtonGroup();
|
||||||
|
optionButtons = new JRadioButton[4];
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
optionButtons[i] = new JRadioButton();
|
||||||
|
optionButtons[i].setFont(new Font("Cambria Math", Font.PLAIN, 14));
|
||||||
|
optionGroup.add(optionButtons[i]);
|
||||||
|
gbc.gridy = i + 2;
|
||||||
|
gbc.gridwidth = 2;
|
||||||
|
centerPanel.add(optionButtons[i], gbc);
|
||||||
|
gbc.gridwidth = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
mainPanel.add(centerPanel, BorderLayout.CENTER);
|
||||||
|
|
||||||
|
JPanel bottomPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
|
||||||
|
submitButton = new JButton("提交答案");
|
||||||
|
submitButton.setPreferredSize(new Dimension(150, 35));
|
||||||
|
submitButton.setFont(new Font("微软雅黑", Font.BOLD, 14));
|
||||||
|
bottomPanel.add(submitButton);
|
||||||
|
|
||||||
|
mainPanel.add(bottomPanel, BorderLayout.SOUTH);
|
||||||
|
|
||||||
|
add(mainPanel);
|
||||||
|
|
||||||
|
submitButton.addActionListener(e -> handleSubmit());
|
||||||
|
|
||||||
|
displayQuestion();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 显示当前题目
|
||||||
|
*/
|
||||||
|
private void displayQuestion() {
|
||||||
|
if (currentIndex >= questions.size()) {
|
||||||
|
showResult();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Question question = questions.get(currentIndex);
|
||||||
|
progressLabel.setText(String.format("第 %d/%d 题",
|
||||||
|
currentIndex + 1, questions.size()));
|
||||||
|
questionLabel.setText("<html><body style='width: 500px'>" +
|
||||||
|
question.questionText() + "</body></html>");
|
||||||
|
|
||||||
|
optionGroup.clearSelection();
|
||||||
|
|
||||||
|
String[] options = question.options();
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
optionButtons[i].setText(options[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
submitButton.setEnabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理答案提交
|
||||||
|
*/
|
||||||
|
private void handleSubmit() {
|
||||||
|
int selectedIndex = -1;
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
if (optionButtons[i].isSelected()) {
|
||||||
|
selectedIndex = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selectedIndex == -1) {
|
||||||
|
JOptionPane.showMessageDialog(this,
|
||||||
|
"请选择一个答案",
|
||||||
|
"提示",
|
||||||
|
JOptionPane.WARNING_MESSAGE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Question question = questions.get(currentIndex);
|
||||||
|
if (selectedIndex == question.correctAnswer()) {
|
||||||
|
correctCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
currentIndex++;
|
||||||
|
displayQuestion();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 显示答题结果
|
||||||
|
*/
|
||||||
|
private void showResult() {
|
||||||
|
double percentage = (double) correctCount / questions.size() * 100;
|
||||||
|
int score = (int) percentage;
|
||||||
|
|
||||||
|
ResultFrame resultFrame = new ResultFrame(
|
||||||
|
email, gradeType, score, correctCount, questions.size());
|
||||||
|
resultFrame.setVisible(true);
|
||||||
|
this.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回年级选择界面
|
||||||
|
*/
|
||||||
|
private void returnToGradeSelection() {
|
||||||
|
GradeSelectionFrame frame = new GradeSelectionFrame(email, gradeType);
|
||||||
|
frame.setVisible(true);
|
||||||
|
this.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,127 @@
|
|||||||
|
package ui;
|
||||||
|
|
||||||
|
import model.Grade;
|
||||||
|
import javax.swing.BorderFactory;
|
||||||
|
import javax.swing.JButton;
|
||||||
|
import javax.swing.JFrame;
|
||||||
|
import javax.swing.JLabel;
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
import java.awt.BorderLayout;
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.awt.Dimension;
|
||||||
|
import java.awt.FlowLayout;
|
||||||
|
import java.awt.Font;
|
||||||
|
import java.awt.GridBagConstraints;
|
||||||
|
import java.awt.GridBagLayout;
|
||||||
|
import java.awt.Insets;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 答题结果展示界面
|
||||||
|
* 显示得分和统计信息,提供继续答题或退出选项
|
||||||
|
*/
|
||||||
|
public class ResultFrame extends JFrame {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private final String email;
|
||||||
|
private final Grade gradeType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造结果展示界面
|
||||||
|
*
|
||||||
|
* @param email 用户邮箱
|
||||||
|
* @param gradeType 年级类型
|
||||||
|
* @param score 得分
|
||||||
|
* @param correctCount 答对题数
|
||||||
|
* @param totalCount 总题数
|
||||||
|
*/
|
||||||
|
public ResultFrame(String email, Grade gradeType, int score,
|
||||||
|
int correctCount, int totalCount) {
|
||||||
|
this.email = email;
|
||||||
|
this.gradeType = gradeType;
|
||||||
|
|
||||||
|
setTitle("数学学习软件 - 答题结果");
|
||||||
|
setSize(600, 420);
|
||||||
|
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||||
|
setLocationRelativeTo(null);
|
||||||
|
setResizable(true);
|
||||||
|
|
||||||
|
JPanel mainPanel = new JPanel(new BorderLayout(10, 10));
|
||||||
|
mainPanel.setBorder(BorderFactory.createEmptyBorder(30, 30, 30, 30));
|
||||||
|
|
||||||
|
JPanel centerPanel = new JPanel(new GridBagLayout());
|
||||||
|
GridBagConstraints gbc = new GridBagConstraints();
|
||||||
|
gbc.insets = new Insets(10, 10, 10, 10);
|
||||||
|
gbc.gridx = 0;
|
||||||
|
gbc.gridy = 0;
|
||||||
|
|
||||||
|
JLabel titleLabel = new JLabel("答题完成!", JLabel.CENTER);
|
||||||
|
titleLabel.setFont(new Font("微软雅黑", Font.BOLD, 24));
|
||||||
|
centerPanel.add(titleLabel, gbc);
|
||||||
|
|
||||||
|
gbc.gridy = 1;
|
||||||
|
JLabel scoreLabel = new JLabel("得分: " + score, JLabel.CENTER);
|
||||||
|
scoreLabel.setFont(new Font("微软雅黑", Font.BOLD, 36));
|
||||||
|
scoreLabel.setForeground(getScoreColor(score));
|
||||||
|
centerPanel.add(scoreLabel, gbc);
|
||||||
|
|
||||||
|
gbc.gridy = 2;
|
||||||
|
JLabel detailLabel = new JLabel(
|
||||||
|
String.format("答对 %d 题 / 共 %d 题", correctCount, totalCount),
|
||||||
|
JLabel.CENTER);
|
||||||
|
detailLabel.setFont(new Font("微软雅黑", Font.PLAIN, 14));
|
||||||
|
centerPanel.add(detailLabel, gbc);
|
||||||
|
|
||||||
|
mainPanel.add(centerPanel, BorderLayout.CENTER);
|
||||||
|
|
||||||
|
JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 15, 0));
|
||||||
|
JButton continueButton = new JButton("继续做题");
|
||||||
|
JButton exitButton = new JButton("退出");
|
||||||
|
|
||||||
|
continueButton.setPreferredSize(new Dimension(120, 35));
|
||||||
|
exitButton.setPreferredSize(new Dimension(120, 35));
|
||||||
|
|
||||||
|
buttonPanel.add(continueButton);
|
||||||
|
buttonPanel.add(exitButton);
|
||||||
|
|
||||||
|
mainPanel.add(buttonPanel, BorderLayout.SOUTH);
|
||||||
|
|
||||||
|
add(mainPanel);
|
||||||
|
|
||||||
|
continueButton.addActionListener(e -> continueQuiz());
|
||||||
|
exitButton.addActionListener(e -> exitToSelection());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据分数返回对应颜色
|
||||||
|
*
|
||||||
|
* @param score 分数
|
||||||
|
* @return 颜色对象
|
||||||
|
*/
|
||||||
|
private Color getScoreColor(int score) {
|
||||||
|
if (score >= 90) {
|
||||||
|
return new Color(0, 150, 0);
|
||||||
|
} else if (score >= 60) {
|
||||||
|
return new Color(255, 140, 0);
|
||||||
|
} else {
|
||||||
|
return new Color(200, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 继续做题
|
||||||
|
*/
|
||||||
|
private void continueQuiz() {
|
||||||
|
GradeSelectionFrame frame = new GradeSelectionFrame(email, gradeType);
|
||||||
|
frame.setVisible(true);
|
||||||
|
this.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 退出到选择界面
|
||||||
|
*/
|
||||||
|
private void exitToSelection() {
|
||||||
|
GradeSelectionFrame frame = new GradeSelectionFrame(email, gradeType);
|
||||||
|
frame.setVisible(true);
|
||||||
|
this.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,86 @@
|
|||||||
|
package ui;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
import java.awt.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户设置对话框
|
||||||
|
* 显示用户信息并提供修改密码的入口
|
||||||
|
*/
|
||||||
|
public class UserSettingsDialog extends JDialog {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private final String email;
|
||||||
|
private final String username;
|
||||||
|
private final Frame parentFrame;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造用户设置对话框
|
||||||
|
*
|
||||||
|
* @param parent 父窗口
|
||||||
|
* @param email 用户邮箱
|
||||||
|
* @param username 用户名
|
||||||
|
*/
|
||||||
|
public UserSettingsDialog(Frame parent, String email, String username) {
|
||||||
|
super(parent, "用户设置", true);
|
||||||
|
this.parentFrame = parent;
|
||||||
|
this.email = email;
|
||||||
|
this.username = username;
|
||||||
|
|
||||||
|
setSize(400, 250);
|
||||||
|
setLocationRelativeTo(parent);
|
||||||
|
setResizable(false);
|
||||||
|
|
||||||
|
JPanel panel = new JPanel(new GridBagLayout());
|
||||||
|
panel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
|
||||||
|
GridBagConstraints gbc = new GridBagConstraints();
|
||||||
|
gbc.insets = new Insets(10, 5, 10, 5);
|
||||||
|
gbc.anchor = GridBagConstraints.WEST;
|
||||||
|
|
||||||
|
// 显示用户名
|
||||||
|
gbc.gridx = 0;
|
||||||
|
gbc.gridy = 0;
|
||||||
|
panel.add(new JLabel("用户名:"), gbc);
|
||||||
|
|
||||||
|
gbc.gridx = 1;
|
||||||
|
JLabel usernameLabel = new JLabel(username);
|
||||||
|
usernameLabel.setFont(new Font("微软雅黑", Font.BOLD, 14));
|
||||||
|
panel.add(usernameLabel, gbc);
|
||||||
|
|
||||||
|
// 显示邮箱
|
||||||
|
gbc.gridx = 0;
|
||||||
|
gbc.gridy = 1;
|
||||||
|
panel.add(new JLabel("邮箱:"), gbc);
|
||||||
|
|
||||||
|
gbc.gridx = 1;
|
||||||
|
JLabel emailLabel = new JLabel(email);
|
||||||
|
emailLabel.setFont(new Font("微软雅黑", Font.PLAIN, 14));
|
||||||
|
panel.add(emailLabel, gbc);
|
||||||
|
|
||||||
|
// 修改密码按钮
|
||||||
|
JButton changePasswordButton = new JButton("修改密码");
|
||||||
|
changePasswordButton.setPreferredSize(new Dimension(120, 30));
|
||||||
|
gbc.gridx = 0;
|
||||||
|
gbc.gridy = 2;
|
||||||
|
gbc.gridwidth = 2;
|
||||||
|
gbc.anchor = GridBagConstraints.CENTER;
|
||||||
|
gbc.insets = new Insets(20, 5, 10, 5);
|
||||||
|
panel.add(changePasswordButton, gbc);
|
||||||
|
|
||||||
|
add(panel);
|
||||||
|
|
||||||
|
// 按钮点击事件
|
||||||
|
changePasswordButton.addActionListener(e -> openChangePasswordDialog());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 打开修改密码对话框
|
||||||
|
*/
|
||||||
|
private void openChangePasswordDialog() {
|
||||||
|
// 关闭当前对话框
|
||||||
|
this.dispose();
|
||||||
|
// 打开修改密码对话框
|
||||||
|
ChangePasswordDialog dialog = new ChangePasswordDialog(parentFrame, email);
|
||||||
|
dialog.setVisible(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"1617940512@qq.com": {
|
||||||
|
"email": "1617940512@qq.com",
|
||||||
|
"password": "Qwerty1",
|
||||||
|
"grade": "primary",
|
||||||
|
"username": "zhang"
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in new issue