/// <summary> /// Takes in an integer representing the number of items to randomly mask. /// Copies the Solution grid to a new Puzzle grid, and then randomly selects the specified number of values /// to mask (change to value of zero) to build a puzzle sudoku board. /// Sets this newly created SudokuGrid as the Puzzle grid for this builder. /// </summary> /// <param name="masked"> Number of items to randomly mask </param> private void GeneratePuzzle(int masked) { HashSet <Tuple <int, int> > UnmaskedCoords = new HashSet <Tuple <int, int> >(); for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { UnmaskedCoords.Add(new Tuple <int, int>(i, j)); } } Puzzle = new SudokuGrid(); Puzzle.CloneFrom(Solution); for (int m = 0; m < masked; m++) { Tuple <int, int> randCoord = UnmaskedCoords.ElementAt(Rand.Next(UnmaskedCoords.Count)); // picks a random coordinate that hasnt yet been emptied int rx = randCoord.Item1; int ry = randCoord.Item2; UnmaskedCoords.Remove(randCoord); Puzzle.Set(rx, ry, 0); } }
/// <summary> /// Clones the values from the given SudokuGrid. /// </summary> /// <param name="original"> SudokuGrid to copy coordinate values from. </param> public void CloneFrom(SudokuGrid original) { for (int y = 0; y < 9; y++) { for (int x = 0; x < 9; x++) { Set(x, y, original.Get(x, y)); } } }
/// <summary> /// Attempts to generate a new, solved, randomized SudokuGrid to represent the Sudoku solution, /// and saves it as this GridBuilder's Solution. /// Takes in an integer representing the number of attempts to generate a solution before a placeholder grid will be used. /// </summary> /// <param name="attemptMax"> Number of failed attempts to generate a board allowed before a placeholder will be used. </param> private void GenerateSolution(int maxAttempts) { HashSet <Tuple <int, int> > EmptyCoords = new HashSet <Tuple <int, int> >(); for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { EmptyCoords.Add(new Tuple <int, int>(i, j)); } } if (EmptyCoords.Count != 81) { throw new Exception("Problem generating possible coordinates in GenerateSolution."); } Solution = new SudokuGrid(); int placed = 0; while (EmptyCoords.Count > 0) { Tuple <int, int> randCoord = EmptyCoords.ElementAt(Rand.Next(EmptyCoords.Count)); int rx = randCoord.Item1; int ry = randCoord.Item2; int[] possibleValues = Solution.LegalValues(rx, ry); if (possibleValues.Length > 0) { int rval = possibleValues[Rand.Next(0, possibleValues.Length - 1)]; Solution.Set(rx, ry, rval); placed++; EmptyCoords.Remove(randCoord); } else // No possible moves at this coordinate. { if (maxAttempts > 0) { GenerateSolution(maxAttempts - 1); } else { GenerateSolution(); } } } Console.Write("ay"); }
/// <summary> /// Recursively generates a new Solution sudokuboard, modifying this GridBuilder's "Solution" grid. /// </summary> public void GenerateSolutionRecursively() { Solution = new SudokuGrid(); HashSet <Tuple <int, int> > AllCoords = new HashSet <Tuple <int, int> >(); for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { AllCoords.Add(new Tuple <int, int>(i, j)); } } // Build randomized initial row for (int i = 0; i < 9; i++) { Tuple <int, int> initCoord = AllCoords.First(); AllCoords.Remove(initCoord); int x = initCoord.Item1; int y = initCoord.Item2; int[] possibleValues = Solution.LegalValues(x, y); Solution.Set(x, y, possibleValues[Rand.Next(possibleValues.Length)]); } Stack <Tuple <int, int> > emptySpaces = new Stack <Tuple <int, int> >(); while (AllCoords.Count > 0) { Tuple <int, int> randCoord = AllCoords.First(); AllCoords.Remove(randCoord); emptySpaces.Push(randCoord); } if (!GenSolutionRec(emptySpaces)) { throw new Exception("It asplode"); } }