public DTSudokuFrame(DTSudokuDifficultyValue initialDifficulty) { this.random = new SudokuRandom(); this.sudokuBoardFrameSection = null; this.sudokuDifficultySelectionFrameSection = new DTSudokuDifficultySelectionFrameSection(initialDifficulty); this.sudokuNewGameButtonFrameSection = new DTSudokuNewGameButtonFrameSection(); this.sudokuLoadingBoardFrameSection = new DTSudokuLoadingBoardFrameSection(initialDifficulty, this.random); }
public int[,] SolveForRandomSolution(int[,] board, ISudokuRandom random) { var solution = this.GetSolutions(board, 1, random); if (solution.Count == 0) { throw new Exception("Undefined behavior - board must have at least one solution"); } return(solution[0]); }
public SudokuGenerator(IRandomizedSudokuSolver s, ISudokuRandom r) { this.solver = s; this.random = r; this.currentPuzzle = null; this.numRemoved = -1; this.numTries = -1; this.isDone = false; this.difficulty = SudokuDifficulty.Easy; this.cellsThatCannotBeRemoved = null; }
// Given a board, returns up to numSolutions solutions, chosen randomly. // If there are less than numSolutions solutions, the returned list's // length is the number of solutions the board has. private List <int[, ]> GetSolutions(int[,] board, int numSolutions, ISudokuRandom random) { if (numSolutions == 0) { return(new List <int[, ]>()); } if (!this.NoConflicts(board)) { return(new List <int[, ]>()); } List <int[, ]> solutions = this.GetSolutionsRecursive(this.CopyBoard(board), numSolutions, random); if (solutions == null) { return(new List <int[, ]>()); } return(solutions); }
public DTSudokuLoadingBoardFrameSection(DTSudokuDifficultyValue difficulty, ISudokuRandom random) { SudokuDifficulty sudokuDifficulty; if (difficulty == DTSudokuDifficultyValue.Easy) { sudokuDifficulty = SudokuDifficulty.Easy; } else if (difficulty == DTSudokuDifficultyValue.Normal) { sudokuDifficulty = SudokuDifficulty.Normal; } else if (difficulty == DTSudokuDifficultyValue.Hard) { sudokuDifficulty = SudokuDifficulty.Hard; } else { throw new Exception(); } this.sudokuGenerator = new SudokuGenerator(new RandomizedSudokuSolver(), random); this.sudokuGenerator.StartGeneratingSudokuPuzzle(sudokuDifficulty); }
/* * Unlike this.GetSolutions, this function requires that numSolutions > 0 * and that the board has no obvious conflicts. (An obvious conflict is two * duplicate numbers on the same row, column, or 3x3 box.) * * Also, unlike this.GetSolutions, if the board has no solutions, this function returns * null instead of an empty list. */ private List <int[, ]> GetSolutionsRecursive(int[,] board, int numSolutions, ISudokuRandom random) { int xEmpty = -1; int yEmpty = -1; int numEmptyCells = 0; for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { if (board[i, j] == 0) { xEmpty = i; yEmpty = j; numEmptyCells++; } } } if (xEmpty == -1) { var list = new List <int[, ]>(); list.Add(this.CopyBoard(board)); return(list); } if (numEmptyCells > 50) { Tuple <int, int> mostConstrainedEmptyCell = this.GetMostConstrainedEmptyCell(board); xEmpty = mostConstrainedEmptyCell.Item1; yEmpty = mostConstrainedEmptyCell.Item2; } bool[] potentialValues = new bool[] { true, true, true, true, true, true, true, true, true, true }; for (int i = 0; i < 9; i++) { int num = board[i, yEmpty]; if (num != 0) { potentialValues[num] = false; } } for (int j = 0; j < 9; j++) { int num = board[xEmpty, j]; if (num != 0) { potentialValues[num] = false; } } int boxX = (xEmpty / 3) * 3; int boxY = (yEmpty / 3) * 3; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { int num = board[boxX + i, boxY + j]; if (num != 0) { potentialValues[num] = false; } } } if (!potentialValues[1] && !potentialValues[2] && !potentialValues[3] && !potentialValues[4] && !potentialValues[5] && !potentialValues[6] && !potentialValues[7] && !potentialValues[8] && !potentialValues[9]) { return(null); } List <int> valuesToTry = new List <int>(); for (int x = 1; x <= 9; x++) { if (potentialValues[x]) { valuesToTry.Add(x); } } List <int[, ]> solutions = null; while (valuesToTry.Count > 0) { int nextIndex = random != null?random.NextInt(valuesToTry.Count) : 0; int nextValueToTry = valuesToTry[nextIndex]; valuesToTry.RemoveAt(nextIndex); board[xEmpty, yEmpty] = nextValueToTry; int numSolutionsNeeded = numSolutions - (solutions != null ? solutions.Count : 0); List <int[, ]> subsolutions = this.GetSolutionsRecursive(board, numSolutionsNeeded, random); if (subsolutions != null) { if (solutions == null) { solutions = subsolutions; } else { foreach (int[,] subsolution in subsolutions) { solutions.Add(subsolution); } } } if (solutions != null && solutions.Count == numSolutions) { board[xEmpty, yEmpty] = 0; return(solutions); } } board[xEmpty, yEmpty] = 0; return(solutions); }