Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 947a875694 | |||
| 1246331125 | |||
| b68fe81914 | |||
| 9c72891048 |
551
app/save/save-1.json
Normal file
551
app/save/save-1.json
Normal file
@@ -0,0 +1,551 @@
|
|||||||
|
{
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"blockID": 0,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 0,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 0,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 1,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 1,
|
||||||
|
"immutable": true,
|
||||||
|
"symbolIndex": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 1,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 2,
|
||||||
|
"immutable": true,
|
||||||
|
"symbolIndex": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 2,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 2,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 0,
|
||||||
|
"immutable": true,
|
||||||
|
"symbolIndex": 8
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 0,
|
||||||
|
"immutable": true,
|
||||||
|
"symbolIndex": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 0,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 1,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 1,
|
||||||
|
"immutable": true,
|
||||||
|
"symbolIndex": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 1,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 2,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 2,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 2,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 0,
|
||||||
|
"immutable": true,
|
||||||
|
"symbolIndex": 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 0,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 0,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 1,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 1,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 1,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 2,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 2,
|
||||||
|
"immutable": true,
|
||||||
|
"symbolIndex": 8
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 2,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 3,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 3,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 3,
|
||||||
|
"immutable": true,
|
||||||
|
"symbolIndex": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 4,
|
||||||
|
"immutable": true,
|
||||||
|
"symbolIndex": 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 4,
|
||||||
|
"immutable": true,
|
||||||
|
"symbolIndex": 6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 4,
|
||||||
|
"immutable": true,
|
||||||
|
"symbolIndex": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 5,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 5,
|
||||||
|
"immutable": true,
|
||||||
|
"symbolIndex": 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 5,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 3,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 3,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 3,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 4,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 4,
|
||||||
|
"immutable": true,
|
||||||
|
"symbolIndex": 7
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 4,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 5,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 5,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 5,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 3,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 3,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 3,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 4,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 4,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 4,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 5,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 5,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 5,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 6,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 6,
|
||||||
|
"immutable": true,
|
||||||
|
"symbolIndex": 6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 6,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 7,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 7,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 7,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 8,
|
||||||
|
"immutable": true,
|
||||||
|
"symbolIndex": 8
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 8,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 8,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 6,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 6,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 6,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 7,
|
||||||
|
"immutable": true,
|
||||||
|
"symbolIndex": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 7,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 7,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 8,
|
||||||
|
"immutable": true,
|
||||||
|
"symbolIndex": 6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 8,
|
||||||
|
"immutable": true,
|
||||||
|
"symbolIndex": 7
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 8,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 6,
|
||||||
|
"immutable": true,
|
||||||
|
"symbolIndex": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 6,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 6,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 7,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 7,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 7,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 8,
|
||||||
|
"immutable": true,
|
||||||
|
"symbolIndex": 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 8,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 8,
|
||||||
|
"symbolIndex": -1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"blocks": [
|
||||||
|
{"cellIDs": [
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
9,
|
||||||
|
10,
|
||||||
|
11,
|
||||||
|
18,
|
||||||
|
19,
|
||||||
|
20
|
||||||
|
]},
|
||||||
|
{"cellIDs": [
|
||||||
|
3,
|
||||||
|
4,
|
||||||
|
5,
|
||||||
|
12,
|
||||||
|
13,
|
||||||
|
14,
|
||||||
|
21,
|
||||||
|
22,
|
||||||
|
23
|
||||||
|
]},
|
||||||
|
{"cellIDs": [
|
||||||
|
6,
|
||||||
|
7,
|
||||||
|
8,
|
||||||
|
15,
|
||||||
|
16,
|
||||||
|
17,
|
||||||
|
24,
|
||||||
|
25,
|
||||||
|
26
|
||||||
|
]},
|
||||||
|
{"cellIDs": [
|
||||||
|
27,
|
||||||
|
28,
|
||||||
|
29,
|
||||||
|
36,
|
||||||
|
37,
|
||||||
|
38,
|
||||||
|
45,
|
||||||
|
46,
|
||||||
|
47
|
||||||
|
]},
|
||||||
|
{"cellIDs": [
|
||||||
|
30,
|
||||||
|
31,
|
||||||
|
32,
|
||||||
|
39,
|
||||||
|
40,
|
||||||
|
41,
|
||||||
|
48,
|
||||||
|
49,
|
||||||
|
50
|
||||||
|
]},
|
||||||
|
{"cellIDs": [
|
||||||
|
33,
|
||||||
|
34,
|
||||||
|
35,
|
||||||
|
42,
|
||||||
|
43,
|
||||||
|
44,
|
||||||
|
51,
|
||||||
|
52,
|
||||||
|
53
|
||||||
|
]},
|
||||||
|
{"cellIDs": [
|
||||||
|
54,
|
||||||
|
55,
|
||||||
|
56,
|
||||||
|
63,
|
||||||
|
64,
|
||||||
|
65,
|
||||||
|
72,
|
||||||
|
73,
|
||||||
|
74
|
||||||
|
]},
|
||||||
|
{"cellIDs": [
|
||||||
|
57,
|
||||||
|
58,
|
||||||
|
59,
|
||||||
|
66,
|
||||||
|
67,
|
||||||
|
68,
|
||||||
|
75,
|
||||||
|
76,
|
||||||
|
77
|
||||||
|
]},
|
||||||
|
{"cellIDs": [
|
||||||
|
60,
|
||||||
|
61,
|
||||||
|
62,
|
||||||
|
69,
|
||||||
|
70,
|
||||||
|
71,
|
||||||
|
78,
|
||||||
|
79,
|
||||||
|
80
|
||||||
|
]}
|
||||||
|
],
|
||||||
|
"multidoku": [{
|
||||||
|
"blockWidth": 3,
|
||||||
|
"cells": [
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
4,
|
||||||
|
5,
|
||||||
|
6,
|
||||||
|
7,
|
||||||
|
8,
|
||||||
|
9,
|
||||||
|
10,
|
||||||
|
11,
|
||||||
|
12,
|
||||||
|
13,
|
||||||
|
14,
|
||||||
|
15,
|
||||||
|
16,
|
||||||
|
17,
|
||||||
|
18,
|
||||||
|
19,
|
||||||
|
20,
|
||||||
|
21,
|
||||||
|
22,
|
||||||
|
23,
|
||||||
|
24,
|
||||||
|
25,
|
||||||
|
26,
|
||||||
|
27,
|
||||||
|
28,
|
||||||
|
29,
|
||||||
|
30,
|
||||||
|
31,
|
||||||
|
32,
|
||||||
|
33,
|
||||||
|
34,
|
||||||
|
35,
|
||||||
|
36,
|
||||||
|
37,
|
||||||
|
38,
|
||||||
|
39,
|
||||||
|
40,
|
||||||
|
41,
|
||||||
|
42,
|
||||||
|
43,
|
||||||
|
44,
|
||||||
|
45,
|
||||||
|
46,
|
||||||
|
47,
|
||||||
|
48,
|
||||||
|
49,
|
||||||
|
50,
|
||||||
|
51,
|
||||||
|
52,
|
||||||
|
53,
|
||||||
|
54,
|
||||||
|
55,
|
||||||
|
56,
|
||||||
|
57,
|
||||||
|
58,
|
||||||
|
59,
|
||||||
|
60,
|
||||||
|
61,
|
||||||
|
62,
|
||||||
|
63,
|
||||||
|
64,
|
||||||
|
65,
|
||||||
|
66,
|
||||||
|
67,
|
||||||
|
68,
|
||||||
|
69,
|
||||||
|
70,
|
||||||
|
71,
|
||||||
|
72,
|
||||||
|
73,
|
||||||
|
74,
|
||||||
|
75,
|
||||||
|
76,
|
||||||
|
77,
|
||||||
|
78,
|
||||||
|
79,
|
||||||
|
80
|
||||||
|
],
|
||||||
|
"blocks": [
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
4,
|
||||||
|
5,
|
||||||
|
6,
|
||||||
|
7,
|
||||||
|
8
|
||||||
|
],
|
||||||
|
"constraints": [
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
2
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
}
|
||||||
554
app/save/save.json
Normal file
554
app/save/save.json
Normal file
@@ -0,0 +1,554 @@
|
|||||||
|
{
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"blockID": 0,
|
||||||
|
"immutable": true,
|
||||||
|
"symbolIndex": 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 0,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 0,
|
||||||
|
"immutable": true,
|
||||||
|
"symbolIndex": 6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 1,
|
||||||
|
"immutable": true,
|
||||||
|
"symbolIndex": 7
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 1,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 1,
|
||||||
|
"immutable": true,
|
||||||
|
"symbolIndex": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 2,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 2,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 2,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 0,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 0,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 0,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 1,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 1,
|
||||||
|
"immutable": true,
|
||||||
|
"symbolIndex": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 1,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 2,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 2,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 2,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 0,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 0,
|
||||||
|
"immutable": true,
|
||||||
|
"symbolIndex": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 0,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 1,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 1,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 1,
|
||||||
|
"immutable": true,
|
||||||
|
"symbolIndex": 8
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 2,
|
||||||
|
"immutable": true,
|
||||||
|
"symbolIndex": 7
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 2,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 2,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 3,
|
||||||
|
"immutable": true,
|
||||||
|
"symbolIndex": 6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 3,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 3,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 4,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 4,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 4,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 5,
|
||||||
|
"immutable": true,
|
||||||
|
"symbolIndex": 8
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 5,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 5,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 3,
|
||||||
|
"immutable": true,
|
||||||
|
"symbolIndex": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 3,
|
||||||
|
"immutable": true,
|
||||||
|
"symbolIndex": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 3,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 4,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 4,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 4,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 5,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 5,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 5,
|
||||||
|
"immutable": true,
|
||||||
|
"symbolIndex": 6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 3,
|
||||||
|
"immutable": true,
|
||||||
|
"symbolIndex": 8
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 3,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 3,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 4,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 4,
|
||||||
|
"immutable": true,
|
||||||
|
"symbolIndex": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 4,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 5,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 5,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 5,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 6,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 6,
|
||||||
|
"immutable": true,
|
||||||
|
"symbolIndex": 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 6,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 7,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 7,
|
||||||
|
"immutable": true,
|
||||||
|
"symbolIndex": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 7,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 8,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 8,
|
||||||
|
"immutable": true,
|
||||||
|
"symbolIndex": 7
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 8,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 6,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 6,
|
||||||
|
"immutable": true,
|
||||||
|
"symbolIndex": 8
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 6,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 7,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 7,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 7,
|
||||||
|
"immutable": true,
|
||||||
|
"symbolIndex": 6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 8,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 8,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 8,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 6,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 6,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 6,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 7,
|
||||||
|
"immutable": true,
|
||||||
|
"symbolIndex": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 7,
|
||||||
|
"immutable": true,
|
||||||
|
"symbolIndex": 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 7,
|
||||||
|
"immutable": true,
|
||||||
|
"symbolIndex": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 8,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 8,
|
||||||
|
"symbolIndex": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"blockID": 8,
|
||||||
|
"symbolIndex": -1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"blocks": [
|
||||||
|
{"cellIDs": [
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
9,
|
||||||
|
10,
|
||||||
|
11,
|
||||||
|
18,
|
||||||
|
19,
|
||||||
|
20
|
||||||
|
]},
|
||||||
|
{"cellIDs": [
|
||||||
|
3,
|
||||||
|
4,
|
||||||
|
5,
|
||||||
|
12,
|
||||||
|
13,
|
||||||
|
14,
|
||||||
|
21,
|
||||||
|
22,
|
||||||
|
23
|
||||||
|
]},
|
||||||
|
{"cellIDs": [
|
||||||
|
6,
|
||||||
|
7,
|
||||||
|
8,
|
||||||
|
15,
|
||||||
|
16,
|
||||||
|
17,
|
||||||
|
24,
|
||||||
|
25,
|
||||||
|
26
|
||||||
|
]},
|
||||||
|
{"cellIDs": [
|
||||||
|
27,
|
||||||
|
28,
|
||||||
|
29,
|
||||||
|
36,
|
||||||
|
37,
|
||||||
|
38,
|
||||||
|
45,
|
||||||
|
46,
|
||||||
|
47
|
||||||
|
]},
|
||||||
|
{"cellIDs": [
|
||||||
|
30,
|
||||||
|
31,
|
||||||
|
32,
|
||||||
|
39,
|
||||||
|
40,
|
||||||
|
41,
|
||||||
|
48,
|
||||||
|
49,
|
||||||
|
50
|
||||||
|
]},
|
||||||
|
{"cellIDs": [
|
||||||
|
33,
|
||||||
|
34,
|
||||||
|
35,
|
||||||
|
42,
|
||||||
|
43,
|
||||||
|
44,
|
||||||
|
51,
|
||||||
|
52,
|
||||||
|
53
|
||||||
|
]},
|
||||||
|
{"cellIDs": [
|
||||||
|
54,
|
||||||
|
55,
|
||||||
|
56,
|
||||||
|
63,
|
||||||
|
64,
|
||||||
|
65,
|
||||||
|
72,
|
||||||
|
73,
|
||||||
|
74
|
||||||
|
]},
|
||||||
|
{"cellIDs": [
|
||||||
|
57,
|
||||||
|
58,
|
||||||
|
59,
|
||||||
|
66,
|
||||||
|
67,
|
||||||
|
68,
|
||||||
|
75,
|
||||||
|
76,
|
||||||
|
77
|
||||||
|
]},
|
||||||
|
{"cellIDs": [
|
||||||
|
60,
|
||||||
|
61,
|
||||||
|
62,
|
||||||
|
69,
|
||||||
|
70,
|
||||||
|
71,
|
||||||
|
78,
|
||||||
|
79,
|
||||||
|
80
|
||||||
|
]}
|
||||||
|
],
|
||||||
|
"multidoku": [{
|
||||||
|
"blockWidth": 3,
|
||||||
|
"cells": [
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
4,
|
||||||
|
5,
|
||||||
|
6,
|
||||||
|
7,
|
||||||
|
8,
|
||||||
|
9,
|
||||||
|
10,
|
||||||
|
11,
|
||||||
|
12,
|
||||||
|
13,
|
||||||
|
14,
|
||||||
|
15,
|
||||||
|
16,
|
||||||
|
17,
|
||||||
|
18,
|
||||||
|
19,
|
||||||
|
20,
|
||||||
|
21,
|
||||||
|
22,
|
||||||
|
23,
|
||||||
|
24,
|
||||||
|
25,
|
||||||
|
26,
|
||||||
|
27,
|
||||||
|
28,
|
||||||
|
29,
|
||||||
|
30,
|
||||||
|
31,
|
||||||
|
32,
|
||||||
|
33,
|
||||||
|
34,
|
||||||
|
35,
|
||||||
|
36,
|
||||||
|
37,
|
||||||
|
38,
|
||||||
|
39,
|
||||||
|
40,
|
||||||
|
41,
|
||||||
|
42,
|
||||||
|
43,
|
||||||
|
44,
|
||||||
|
45,
|
||||||
|
46,
|
||||||
|
47,
|
||||||
|
48,
|
||||||
|
49,
|
||||||
|
50,
|
||||||
|
51,
|
||||||
|
52,
|
||||||
|
53,
|
||||||
|
54,
|
||||||
|
55,
|
||||||
|
56,
|
||||||
|
57,
|
||||||
|
58,
|
||||||
|
59,
|
||||||
|
60,
|
||||||
|
61,
|
||||||
|
62,
|
||||||
|
63,
|
||||||
|
64,
|
||||||
|
65,
|
||||||
|
66,
|
||||||
|
67,
|
||||||
|
68,
|
||||||
|
69,
|
||||||
|
70,
|
||||||
|
71,
|
||||||
|
72,
|
||||||
|
73,
|
||||||
|
74,
|
||||||
|
75,
|
||||||
|
76,
|
||||||
|
77,
|
||||||
|
78,
|
||||||
|
79,
|
||||||
|
80
|
||||||
|
],
|
||||||
|
"blocks": [
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
4,
|
||||||
|
5,
|
||||||
|
6,
|
||||||
|
7,
|
||||||
|
8
|
||||||
|
],
|
||||||
|
"constraints": [
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
2
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
}
|
||||||
@@ -15,6 +15,7 @@ import sudoku.constraint.IConstraint;
|
|||||||
import sudoku.structure.Difficulty;
|
import sudoku.structure.Difficulty;
|
||||||
import sudoku.structure.MultiDoku;
|
import sudoku.structure.MultiDoku;
|
||||||
import sudoku.structure.SudokuFactory;
|
import sudoku.structure.SudokuFactory;
|
||||||
|
import sudoku.structure.SudokuFiller;
|
||||||
|
|
||||||
public class SudokuSelector {
|
public class SudokuSelector {
|
||||||
|
|
||||||
@@ -86,7 +87,8 @@ public class SudokuSelector {
|
|||||||
this.genThread = new Thread(() -> {
|
this.genThread = new Thread(() -> {
|
||||||
try {
|
try {
|
||||||
if (!empty) {
|
if (!empty) {
|
||||||
SudokuFactory.fillDoku(doku, Difficulty.values()[difficulty.get()]);
|
SudokuFiller.fillDoku(doku, Difficulty.values()[difficulty.get()]);
|
||||||
|
// SudokuFactory.fillDoku(doku, Difficulty.values()[difficulty.get()]);
|
||||||
}
|
}
|
||||||
this.onSelect.emit(this.doku);
|
this.onSelect.emit(this.doku);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
package sudoku.io;
|
package sudoku.io;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import gui.RenderableMultidoku;
|
import gui.RenderableMultidoku;
|
||||||
import gui.constants.Symbols;
|
import gui.constants.Symbols;
|
||||||
import sudoku.structure.Cell;
|
import sudoku.structure.Cell;
|
||||||
import sudoku.structure.MultiDoku;
|
import sudoku.structure.MultiDoku;
|
||||||
import sudoku.structure.Sudoku;
|
import sudoku.structure.Sudoku;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class SudokuPrinter {
|
public class SudokuPrinter {
|
||||||
public static final String ANSI_RESET = "\u001B[0m";
|
public static final String ANSI_RESET = "\u001B[0m";
|
||||||
public static final String ANSI_RED = "\u001B[31m";
|
public static final String ANSI_RED = "\u001B[31m";
|
||||||
@@ -47,7 +47,7 @@ public class SudokuPrinter {
|
|||||||
List<String> listSymbols) {
|
List<String> listSymbols) {
|
||||||
StringBuilder header = new StringBuilder("");
|
StringBuilder header = new StringBuilder("");
|
||||||
header.append(" ");
|
header.append(" ");
|
||||||
for (int x = 0; x < blockWidth * blockHeight; x++) {
|
for (int x = 0; x < blockWidth*blockHeight; x++) {
|
||||||
header.append(x + 1).append(" ");
|
header.append(x + 1).append(" ");
|
||||||
if (x % blockWidth == blockWidth - 1 && x != blockWidth * blockHeight - 1) {
|
if (x % blockWidth == blockWidth - 1 && x != blockWidth * blockHeight - 1) {
|
||||||
header.append(" ");
|
header.append(" ");
|
||||||
@@ -77,12 +77,11 @@ public class SudokuPrinter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String printMultiDoku(final RenderableMultidoku rm, Symbols symbols, int blockWidth,
|
public static void printMultiDoku(final RenderableMultidoku rm, Symbols symbols, int blockWidth, int blockHeight) {
|
||||||
int blockHeight) {
|
printMultiDoku(rm, symbols.getSymbols(), blockWidth, blockHeight);
|
||||||
return printMultiDoku(rm, symbols.getSymbols(), blockWidth, blockHeight);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String printMultiDoku(final RenderableMultidoku rm, List<String> listSymbols, int blockWidth,
|
public static void printMultiDoku(final RenderableMultidoku rm, List<String> listSymbols, int blockWidth,
|
||||||
int blockHeight) {
|
int blockHeight) {
|
||||||
StringBuilder line = new StringBuilder("\n");
|
StringBuilder line = new StringBuilder("\n");
|
||||||
int nBlockInWidth = rm.getWidth() / blockWidth;
|
int nBlockInWidth = rm.getWidth() / blockWidth;
|
||||||
@@ -109,8 +108,7 @@ public class SudokuPrinter {
|
|||||||
line.append("]\n");
|
line.append("]\n");
|
||||||
}
|
}
|
||||||
line.append("__".repeat(Math.max(0, rm.getWidth() + nBlockInWidth))).append("_\n");
|
line.append("__".repeat(Math.max(0, rm.getWidth() + nBlockInWidth))).append("_\n");
|
||||||
// System.out.println(line);
|
System.out.println(line);
|
||||||
return line.toString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void printMultiDokuWithIndex(final RenderableMultidoku rm, List<String> listSymbols, int blockWidth,
|
public static void printMultiDokuWithIndex(final RenderableMultidoku rm, List<String> listSymbols, int blockWidth,
|
||||||
@@ -129,7 +127,7 @@ public class SudokuPrinter {
|
|||||||
if (y % blockHeight == 0) {
|
if (y % blockHeight == 0) {
|
||||||
line.append(" ").append("__".repeat(Math.max(0, rm.getWidth() + nBlockInWidth))).append("_\n");
|
line.append(" ").append("__".repeat(Math.max(0, rm.getWidth() + nBlockInWidth))).append("_\n");
|
||||||
}
|
}
|
||||||
line.append(y + 1).append(" [ ");
|
line.append(y+1).append(" [ ");
|
||||||
for (int x = 0; x < rm.getWidth(); x++) {
|
for (int x = 0; x < rm.getWidth(); x++) {
|
||||||
if (x % blockWidth == 0 && x > 0) {
|
if (x % blockWidth == 0 && x > 0) {
|
||||||
line.append("| ");
|
line.append("| ");
|
||||||
@@ -184,16 +182,12 @@ public class SudokuPrinter {
|
|||||||
return result.toString();
|
return result.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String printMultiDoku(final MultiDoku doku) {
|
public static void printMultiDoku(final MultiDoku doku, int blockWidth, int blockHeight, Symbols symbols) {
|
||||||
int blockWidth = doku.getSubGrid(0).getBlockWidth();
|
if (doku.getNbSubGrids() == 1) {
|
||||||
if (blockWidth == 0)
|
printRectangleSudoku(doku.getSubGrid(0), blockWidth, blockHeight, symbols);
|
||||||
return printMultiDoku(doku, 0, 0, Symbols.Numbers);
|
} else {
|
||||||
else
|
printMultiDoku(RenderableMultidoku.fromMultidoku(doku), symbols, blockWidth, blockHeight);
|
||||||
return printMultiDoku(doku, blockWidth, doku.getSubGrid(0).getSize() / blockWidth, Symbols.Letters);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String printMultiDoku(final MultiDoku doku, int blockWidth, int blockHeight, Symbols symbols) {
|
|
||||||
return printMultiDoku(RenderableMultidoku.fromMultidoku(doku), symbols, blockWidth, blockHeight);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void printMultiDokuWithIndex(final MultiDoku doku, int blockWidth, int blockHeight, Symbols symbols) {
|
public static void printMultiDokuWithIndex(final MultiDoku doku, int blockWidth, int blockHeight, Symbols symbols) {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package sudoku.solver;
|
package sudoku.solver;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.CancellationException;
|
import java.util.concurrent.CancellationException;
|
||||||
|
|
||||||
@@ -8,18 +9,28 @@ import sudoku.structure.MultiDoku;
|
|||||||
|
|
||||||
public class MixedSolver implements Solver {
|
public class MixedSolver implements Solver {
|
||||||
|
|
||||||
private Cell findCellToBacktrack(MultiDoku doku, int maxPossibilities) {
|
private List<Cell> findCellToBacktrack(MultiDoku doku, int maxPossibilities) {
|
||||||
|
int symbolCount = doku.getSubGrid(0).getSize();
|
||||||
|
if (maxPossibilities > symbolCount)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
List<Cell> backtrackCells = new ArrayList<>();
|
||||||
|
|
||||||
for (Cell cell : doku.getCells()) {
|
for (Cell cell : doku.getCells()) {
|
||||||
if (!cell.isMutable() || !cell.isEmpty())
|
if (!cell.isMutable() || !cell.isEmpty())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
List<Integer> possibleSymbols = cell.getPossibleSymbols();
|
List<Integer> possibleSymbols = cell.getPossibleSymbols();
|
||||||
if (possibleSymbols.size() == maxPossibilities) {
|
if (possibleSymbols.size() == maxPossibilities) {
|
||||||
return cell;
|
backtrackCells.add(cell);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// grille non résolvable
|
||||||
|
if (possibleSymbols.size() == 0)
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
return backtrackCells;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Résout le MultiDoku passé en paramètre, avec règles de déduction et
|
* Résout le MultiDoku passé en paramètre, avec règles de déduction et
|
||||||
@@ -34,8 +45,12 @@ public class MixedSolver implements Solver {
|
|||||||
throw new CancellationException("User wants to stop the solver");
|
throw new CancellationException("User wants to stop the solver");
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!doku.isSolved()) {
|
if (doku.isSolved())
|
||||||
boolean filledCell = false;
|
return true;
|
||||||
|
|
||||||
|
int symbolCount = doku.getSubGrid(0).getSize();
|
||||||
|
|
||||||
|
// on remplit les cases par déduction
|
||||||
for (Cell cell : doku.getCells()) {
|
for (Cell cell : doku.getCells()) {
|
||||||
if (!cell.isMutable() || !cell.isEmpty())
|
if (!cell.isMutable() || !cell.isEmpty())
|
||||||
continue;
|
continue;
|
||||||
@@ -44,31 +59,41 @@ public class MixedSolver implements Solver {
|
|||||||
if (possibleSymbols.size() == 1) {
|
if (possibleSymbols.size() == 1) {
|
||||||
cell.setSymbolIndex(possibleSymbols.getFirst());
|
cell.setSymbolIndex(possibleSymbols.getFirst());
|
||||||
addStep(cell, steps);
|
addStep(cell, steps);
|
||||||
filledCell = true;
|
if (solve(doku, steps))
|
||||||
|
return true;
|
||||||
|
cell.setSymbolIndex(Cell.NOSYMBOL);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// on ne peut plus remplir de cases, on tente de backtrack
|
// on ne peut plus remplir de cases, on tente de backtrack
|
||||||
if (!filledCell) {
|
for (int maxPossibilities = 2; maxPossibilities <= symbolCount; maxPossibilities++) {
|
||||||
int maxPossibilities = 2;
|
List<Cell> backtrackCells = new ArrayList<>();
|
||||||
Cell backtrackCell = null;
|
while (backtrackCells.isEmpty()) {
|
||||||
while (backtrackCell == null) {
|
backtrackCells = findCellToBacktrack(doku, maxPossibilities);
|
||||||
backtrackCell = findCellToBacktrack(doku, maxPossibilities);
|
// grille non résolvable
|
||||||
|
if (backtrackCells == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
maxPossibilities++;
|
maxPossibilities++;
|
||||||
}
|
}
|
||||||
// on fait du backtracking
|
// on fait du backtracking
|
||||||
|
for (Cell backtrackCell : backtrackCells) {
|
||||||
List<Integer> possibilities = backtrackCell.getPossibleSymbols();
|
List<Integer> possibilities = backtrackCell.getPossibleSymbols();
|
||||||
|
|
||||||
|
// System.out.println("Backtraing on " + backtrackCell);
|
||||||
|
|
||||||
|
// on tente de placer chacun des symboles
|
||||||
for (int symbol : possibilities) {
|
for (int symbol : possibilities) {
|
||||||
doku.getStateManager().pushState();
|
|
||||||
backtrackCell.setSymbolIndex(symbol);
|
backtrackCell.setSymbolIndex(symbol);
|
||||||
if (solve(doku, steps))
|
if (solve(doku, steps)) {
|
||||||
return true;
|
return true;
|
||||||
doku.getStateManager().popState();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
backtrackCell.setSymbolIndex(Cell.NOSYMBOL);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return true;
|
return doku.isSolved();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package sudoku.structure;
|
package sudoku.structure;
|
||||||
|
|
||||||
import sudoku.io.SudokuPrinter;
|
|
||||||
import sudoku.io.SudokuSerializer;
|
import sudoku.io.SudokuSerializer;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -183,7 +182,7 @@ public class MultiDoku {
|
|||||||
if (sudoku.getSize() != otherSudoku.getSize())
|
if (sudoku.getSize() != otherSudoku.getSize())
|
||||||
return false;
|
return false;
|
||||||
for (int j = 0; j < sudoku.getSize() * sudoku.getSize(); j++) {
|
for (int j = 0; j < sudoku.getSize() * sudoku.getSize(); j++) {
|
||||||
if (sudoku.getCell(j).getSymbolIndex() != otherSudoku.getCell(j).getSymbolIndex())
|
if (sudoku.getCell(i).getSymbolIndex() != otherSudoku.getCell(i).getSymbolIndex())
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -192,7 +191,13 @@ public class MultiDoku {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return SudokuPrinter.printMultiDoku(this);
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append("Multidoku {");
|
||||||
|
for (Sudoku sudoku : subGrids) {
|
||||||
|
sb.append("\n\t").append(sudoku.toString());
|
||||||
|
}
|
||||||
|
sb.append("\n}");
|
||||||
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public MultiDoku clone() {
|
public MultiDoku clone() {
|
||||||
|
|||||||
@@ -25,6 +25,10 @@ public class StateManager {
|
|||||||
this.doku = doku;
|
this.doku = doku;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void forgetState() {
|
||||||
|
states.pop();
|
||||||
|
}
|
||||||
|
|
||||||
public Map<Cell, Integer> pushState() {
|
public Map<Cell, Integer> pushState() {
|
||||||
states.add(saveState());
|
states.add(saveState());
|
||||||
return states.getLast();
|
return states.getLast();
|
||||||
@@ -42,7 +46,7 @@ public class StateManager {
|
|||||||
return currentState;
|
return currentState;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void restoreState(Map<Cell, Integer> state) {
|
public void restoreState(Map<Cell, Integer> state) {
|
||||||
for (var entry : state.entrySet()) {
|
for (var entry : state.entrySet()) {
|
||||||
entry.getKey().setSymbolIndex(entry.getValue());
|
entry.getKey().setSymbolIndex(entry.getValue());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -328,7 +328,7 @@ public class SudokuFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remplit un MultiDoku donné par rapport à une difficulté.
|
* Rempli un MultiDoku donné par rapport à un difficulté.
|
||||||
*
|
*
|
||||||
* @param doku MultiDoku, vide.
|
* @param doku MultiDoku, vide.
|
||||||
* @param difficulty Difficulty, qui correspond au pourcentage de cases à enlever.
|
* @param difficulty Difficulty, qui correspond au pourcentage de cases à enlever.
|
||||||
|
|||||||
78
app/src/main/java/sudoku/structure/SudokuFiller.java
Normal file
78
app/src/main/java/sudoku/structure/SudokuFiller.java
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
package sudoku.structure;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
import sudoku.solver.BacktrackingSolver;
|
||||||
|
import sudoku.solver.HumanSolver;
|
||||||
|
import sudoku.solver.MixedSolver;
|
||||||
|
import sudoku.solver.RandomSolver;
|
||||||
|
import sudoku.solver.Solver;
|
||||||
|
|
||||||
|
public class SudokuFiller {
|
||||||
|
|
||||||
|
private static boolean isPossiblySolvable(MultiDoku doku) {
|
||||||
|
for (Cell cell : doku.getEmptyCells()) {
|
||||||
|
if (cell.getPossibleSymbols().size() == 0)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void tryFillRandomCells(MultiDoku doku) {
|
||||||
|
Random r = new Random();
|
||||||
|
while (isPossiblySolvable(doku)) {
|
||||||
|
int cellCount = doku.getEmptyCells().size();
|
||||||
|
if (cellCount == 0)
|
||||||
|
return;
|
||||||
|
Cell cellToFill = doku.getEmptyCells().get(r.nextInt(cellCount));
|
||||||
|
if (!cellToFill.isEmpty() || !cellToFill.isMutable())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
List<Integer> possibleSymbols = cellToFill.getPossibleSymbols();
|
||||||
|
int symbolCount = possibleSymbols.size();
|
||||||
|
// la cellule n'a pas de valeur possible
|
||||||
|
if (symbolCount == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
cellToFill.setSymbolIndex(possibleSymbols.get(r.nextInt(symbolCount)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void removeRandomCell(MultiDoku doku) {
|
||||||
|
Random r = new Random();
|
||||||
|
int cellCount = doku.getFilledCells().size();
|
||||||
|
doku.getFilledCells().get(r.nextInt(cellCount)).clearCurrentSymbol();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void makeSolvable(MultiDoku doku) {
|
||||||
|
while (!isPossiblySolvable(doku)) {
|
||||||
|
removeRandomCell(doku);
|
||||||
|
}
|
||||||
|
Solver solver = new BacktrackingSolver();
|
||||||
|
boolean solvable = false;
|
||||||
|
while (!solvable) {
|
||||||
|
removeRandomCell(doku);
|
||||||
|
doku.getStateManager().pushState();
|
||||||
|
solvable = solver.solve(doku);
|
||||||
|
doku.getStateManager().popState();
|
||||||
|
System.out.println("eeeeeeeeeeeee");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void fillDoku(MultiDoku doku) {
|
||||||
|
tryFillRandomCells(doku);
|
||||||
|
makeSolvable(doku);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void setCellsImmutable(MultiDoku doku) {
|
||||||
|
for (Cell cell : doku.getFilledCells())
|
||||||
|
cell.setImmutable();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void fillDoku(MultiDoku doku, Difficulty difficulty) {
|
||||||
|
fillDoku(doku);
|
||||||
|
setCellsImmutable(doku);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -101,24 +101,17 @@ class SolverTest {
|
|||||||
MultiDoku mdResult = SudokuSerializer.deserializeSudoku(SudokuSerializer.serializeSudoku(mdTest));
|
MultiDoku mdResult = SudokuSerializer.deserializeSudoku(SudokuSerializer.serializeSudoku(mdTest));
|
||||||
assertFalse(mdTest.isSolved());
|
assertFalse(mdTest.isSolved());
|
||||||
assertFalse(mdResult.isSolved());
|
assertFalse(mdResult.isSolved());
|
||||||
assertEquals(mdTest, mdResult);
|
|
||||||
|
|
||||||
assertTrue(solver.solve(mdTest));
|
assertTrue(solver.solve(mdTest));
|
||||||
|
|
||||||
assertTrue(mdTest.isSolved());
|
assertTrue(mdTest.isSolved());
|
||||||
assertFalse(mdResult.isSolved());
|
assertFalse(mdResult.isSolved());
|
||||||
System.out.println(mdTest);
|
|
||||||
System.out.println(mdResult);
|
|
||||||
assertNotEquals(mdTest, mdResult);
|
assertNotEquals(mdTest, mdResult);
|
||||||
|
solver.solve(mdResult);
|
||||||
assertTrue(solver.solve(mdResult));
|
|
||||||
|
|
||||||
assertEquals(mdTest, mdResult);
|
assertEquals(mdTest, mdResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void solveTest() {
|
void solveTest() {
|
||||||
for (int i = 0; i < 100; i++) {
|
initializeSolvers();
|
||||||
testSize2(h);
|
testSize2(h);
|
||||||
testSize3(h);
|
testSize3(h);
|
||||||
testSize2(m);
|
testSize2(m);
|
||||||
@@ -128,5 +121,4 @@ class SolverTest {
|
|||||||
testSize3(r);
|
testSize3(r);
|
||||||
testMDSize3(r);
|
testMDSize3(r);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user