@@ -14,15 +14,29 @@ public class Solver
14
14
{
15
15
private Random rnd = new Random ( ) ;
16
16
17
+ /// <summary>
18
+ /// return all candidates in the block containing the current cell
19
+ /// </summary>
20
+ /// <param name="row">the row number of the current cell</param>
21
+ /// <param name="col">the column number of the current cell</param>
22
+ /// <param name="candidates">list of possibly previously calculated cells</param>
23
+ /// <param name="sudoku">reference of the sudoku</param>
24
+ /// <returns>the partially filled list of candidates</returns>
17
25
public List < int > getBlockNumbers ( double row , double col , ref List < int > candidates , ref int [ ] [ ] sudoku )
18
26
{
19
- //calculate start coordinates for
20
- double blockStartRow = row - ( row % 3 ) ;
21
- double blockStartColumn = col - ( col % 3 ) ;
27
+ // calculate start coordinates for the block of the cell
28
+ // when row = 5:
29
+ // ┌─┐ = row % 3 = 2, so 5 - 2 = 3 and this is the start col index of the block
30
+ // 0 1 2 3 4 5
31
+ // ╟─┼─┼─╫─┼─┼─╫─┼─┼─╢
32
+ double blockStartCol = row - ( row % 3 ) ;
33
+ // same as the above but for row number
34
+ double blockStartRow = col - ( col % 3 ) ;
22
35
23
- for ( int r = ( int ) blockStartRow ; r < blockStartRow + 3 ; r ++ )
36
+ // iterate through all block cells from top left postion of the current block
37
+ for ( int r = ( int ) blockStartCol ; r < blockStartCol + 3 ; r ++ )
24
38
{
25
- for ( int c = ( int ) blockStartColumn ; c < blockStartColumn + 3 ; c ++ )
39
+ for ( int c = ( int ) blockStartRow ; c < blockStartRow + 3 ; c ++ )
26
40
{
27
41
candidates . Remove ( sudoku [ r ] [ c ] ) ;
28
42
}
@@ -31,6 +45,13 @@ public List<int> getBlockNumbers(double row, double col, ref List<int> candidate
31
45
return candidates ;
32
46
}
33
47
48
+ /// <summary>
49
+ /// return all candidates in the row containing the current cell
50
+ /// </summary>
51
+ /// <param name="row">the row number of the current cell</param>
52
+ /// <param name="candidates">list of possibly previously calculated cells</param>
53
+ /// <param name="sudoku">reference of the sudoku</param>
54
+ /// <returns>the partially filled list of candidates</returns>
34
55
public List < int > getRowNumbers ( int row , ref List < int > candidates , ref int [ ] [ ] sudoku )
35
56
{
36
57
for ( int i = 0 ; i < 9 ; i ++ )
@@ -41,6 +62,13 @@ public List<int> getRowNumbers(int row, ref List<int> candidates, ref int[][] su
41
62
return candidates ;
42
63
}
43
64
65
+ /// <summary>
66
+ /// return all candidates in the column containing the current cell
67
+ /// </summary>
68
+ /// <param name="col">the column number of the current cell</param>
69
+ /// <param name="candidates">list of possibly previously calculated cells</param>
70
+ /// <param name="sudoku">reference of the sudoku</param>
71
+ /// <returns>the partially filled list of candidates</returns>
44
72
public List < int > getColumnNumbers ( int col , ref List < int > candidates , ref int [ ] [ ] sudoku )
45
73
{
46
74
for ( int i = 0 ; i < 9 ; i ++ )
@@ -51,6 +79,13 @@ public List<int> getColumnNumbers(int col, ref List<int> candidates, ref int[][]
51
79
return candidates ;
52
80
}
53
81
82
+ /// <summary>
83
+ /// get all the candidates for the row, column and block containing the current cell
84
+ /// </summary>
85
+ /// <param name="row">the row number of the current cell</param>
86
+ /// <param name="col">the column number of the current cell</param>
87
+ /// <param name="sudoku">reference of the sudoku</param>
88
+ /// <returns>the complete list of candidates</returns>
54
89
public List < int > getAllCandidates ( int row , int col , ref int [ ] [ ] sudoku )
55
90
{
56
91
List < int > candidates = new List < int > { 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 } ;
@@ -61,6 +96,13 @@ public List<int> getAllCandidates(int row, int col, ref int[][] sudoku)
61
96
return candidates ;
62
97
}
63
98
99
+ /// <summary>
100
+ /// Returns the sole candidate if there is only one
101
+ /// </summary>
102
+ /// <param name="row">the row number of the current cell</param>
103
+ /// <param name="col">the column number of the current cell</param>
104
+ /// <param name="sudoku">reference of the sudoku</param>
105
+ /// <returns>the sole candidate value</returns>
64
106
public int soleCandidate ( int row , int col , ref int [ ] [ ] sudoku )
65
107
{
66
108
//get all candidates for the current cell
@@ -74,7 +116,11 @@ public int soleCandidate(int row, int col, ref int[][] sudoku)
74
116
return 0 ;
75
117
}
76
118
77
-
119
+ /// <summary>
120
+ /// The method that solves the sudoku logically
121
+ /// </summary>
122
+ /// <param name="sudoku">reference of the sudoku</param>
123
+ /// <returns>the solved sudoku</returns>
78
124
public int [ ] [ ] solveLogical ( ref int [ ] [ ] sudoku )
79
125
{
80
126
//check if there are cells solved and keep track of this using two variables
@@ -128,6 +174,13 @@ static int[][] CopyArrayBuiltIn(int[][] source)
128
174
return dest ;
129
175
}
130
176
177
+ /// <summary>
178
+ /// Recursive function based on guessing numbers picked from possible candidates
179
+ /// </summary>
180
+ /// <param name="row">the row number of the current cell</param>
181
+ /// <param name="col">the column number of the current cell</param>
182
+ /// <param name="sudoku">reference of the sudoku</param>
183
+ /// <returns>false if the the call couldnt guess the right number. True if it can or the cell is already filled</returns>
131
184
public bool SolveGuessingRecursion ( int row , int col , ref int [ ] [ ] sudoku )
132
185
{
133
186
//DateTime.Now;
@@ -158,8 +211,6 @@ public bool SolveGuessingRecursion(int row, int col, ref int[][] sudoku)
158
211
//if there are candidates, walk through them in a linear fashion
159
212
foreach ( var guess in candidates )
160
213
{
161
- //if (1 == random)
162
- // continue;
163
214
//lets try out a guess from candidates
164
215
sudoku [ row ] [ col ] = guess ;
165
216
@@ -186,6 +237,12 @@ public bool SolveGuessingRecursion(int row, int col, ref int[][] sudoku)
186
237
return false ;
187
238
}
188
239
240
+ /// <summary>
241
+ /// Fills in an empty sudoku and then shuffles the rows and columns per block and also
242
+ /// the block rows and columns themselves
243
+ /// </summary>
244
+ /// <param name="sudoku">the sudoku as reference</param>
245
+ /// <returns>boolean succes</returns>
189
246
public bool ShuffleSudoku ( ref int [ ] [ ] sudoku )
190
247
{
191
248
//fill all the cells
@@ -194,19 +251,20 @@ public bool ShuffleSudoku (ref int[][] sudoku)
194
251
//keep track of random picks
195
252
int rndInt = 0 ;
196
253
197
- //
198
- // a column a block column
199
- // ┌─┐ ┌─────┐
200
- // ╔═╤═╤═╦═╤═╤═╦═╤═╤═╗ ┐
201
- // ╟─┼─┼─╫─┼─┼─╫─┼─┼─╢ │ a block row
202
- // ╟─┼─┼─╫─┼─┼─╫─┼─┼─╢ │
203
- // ╠═╪═╪═╬═╪═╪═╬═╪═╪═╣ ┘
204
- // ╟─┼─┼─╫─┼─┼─╫─┼─┼─╢ ┐ a row
205
- // ╟─┼─┼─╫─┼─┼─╫─┼─┼─╢ ┘
206
- // ╠═╪═╪═╬═╪═╪═╬═╪═╪═╣
207
- // ╟─┼─┼─╫─┼─┼─╫─┼─┼─╢
208
- // ╟─┼─┼─╫─┼─┼─╫─┼─┼─╢
209
- // ╚═╧═╧═╩═╧═╧═╩═╧═╧═╝
254
+ /// <example>
255
+ /// a column a block column
256
+ /// ┌─┐ ┌─────┐
257
+ /// ╔═╤═╤═╦═╤═╤═╦═╤═╤═╗ ┐
258
+ /// ╟─┼─┼─╫─┼─┼─╫─┼─┼─╢ │ a block row
259
+ /// ╟─┼─┼─╫─┼─┼─╫─┼─┼─╢ │
260
+ /// ╠═╪═╪═╬═╪═╪═╬═╪═╪═╣ ┘
261
+ /// ╟─┼─┼─╫─┼─┼─╫─┼─┼─╢ ┐ a row
262
+ /// ╟─┼─┼─╫─┼─┼─╫─┼─┼─╢ ┘
263
+ /// ╠═╪═╪═╬═╪═╪═╬═╪═╪═╣
264
+ /// ╟─┼─┼─╫─┼─┼─╫─┼─┼─╢
265
+ /// ╟─┼─┼─╫─┼─┼─╫─┼─┼─╢
266
+ /// ╚═╧═╧═╩═╧═╧═╩═╧═╧═╝
267
+ /// </example>
210
268
//shuffle columns per block columns
211
269
for ( int i = 2 ; i >= 0 ; i -- )
212
270
{
@@ -278,6 +336,10 @@ public bool ShuffleSudoku (ref int[][] sudoku)
278
336
return true ;
279
337
}
280
338
339
+ /// <summary>
340
+ /// A list of shuffled indices later to be used for random deletion of cell values
341
+ /// </summary>
342
+ /// <returns>the shuffled list of random indices</returns>
281
343
public List < int > createShuffledSudokuIndices ( )
282
344
{
283
345
//keep track of random picks;
@@ -323,19 +385,24 @@ public int[][] SolveGuessing(int[][] sudoku)
323
385
return sudoku ;
324
386
}
325
387
388
+ // note the parameter with random object reference, this allows for different random numbers
389
+ // through the entire program. The Random object is initialized in the view Sudoku.cshtml
326
390
public int [ ] [ ] CreateGuessing ( int [ ] [ ] sudoku , Random rnd )
327
391
{
328
392
ShuffleSudoku ( ref sudoku ) ;
329
393
330
- //keep track of the cell coordinates we are going to zero in random order
394
+ // the amount cells we want to keep
395
+ int remainingCells = 13 ;
396
+
397
+ // keep track of the cell coordinates we are going to zero in random order
331
398
// [0]{ 1 , 6 }
332
399
// [1]{ 4 , 0 }
333
400
// [2]{ 3 , 2 }
334
401
// ...
335
402
List < int > randomIndices = createShuffledSudokuIndices ( ) ;
336
403
337
404
//walk trough all 81 (9*9) (shuffled) numbers to see wich cell can or cant be zeroed
338
- for ( int i = 0 ; i < randomIndices . Count - 18 ; i ++ )
405
+ for ( int i = 0 ; i < randomIndices . Count - remainingCells ; i ++ )
339
406
{
340
407
//cell number to coordinates
341
408
int row = Convert . ToInt32 ( Math . Floor ( Convert . ToDecimal ( randomIndices [ i ] / 9 ) ) ) ;
@@ -347,6 +414,8 @@ public int[][] CreateGuessing(int[][] sudoku, Random rnd)
347
414
return sudoku ;
348
415
}
349
416
417
+ // note the parameter with random object reference, this allows for different random numbers
418
+ // through the entire program. The Random object is initialized in the view Sudoku.cshtml
350
419
public int [ ] [ ] Create ( int [ ] [ ] sudoku , Random rnd )
351
420
{
352
421
ShuffleSudoku ( ref sudoku ) ;
0 commit comments