public void TestPuzzleValidity() { int dimension = 3; List <int> cellValues = new List <int>(); // Test a row for (int i = 0; i < dimension * dimension * dimension * dimension; ++i) { cellValues.Add(0); } SudokuPuzzle puzzle = new SudokuPuzzle(dimension, cellValues); Assert.IsTrue(puzzle.IsValid()); // Test a column having the same value twice for (int i = 0; i < dimension * dimension; ++i) { puzzle.Rows[0][i].RemoveAllExcept(i + 1); } Assert.IsTrue(puzzle.IsValid()); puzzle.Rows[dimension + 1][0].RemoveAllExcept(1); Assert.IsFalse(puzzle.IsValid()); // Test a block having the same value twice puzzle = new SudokuPuzzle(dimension, cellValues); for (int i = 0; i < dimension * dimension; ++i) { puzzle.Rows[0][i].RemoveAllExcept(i + 1); } puzzle.Rows[1][1].RemoveAllExcept(1); Assert.IsFalse(puzzle.IsValid()); // Test a row having the same value twice puzzle = new SudokuPuzzle(dimension, cellValues); for (int i = 0; i < dimension * dimension; ++i) { puzzle.Columns[0][i].RemoveAllExcept(i + 1); } Assert.IsTrue(puzzle.IsValid()); puzzle.Rows[0][1].RemoveAllExcept(1); Assert.IsFalse(puzzle.IsValid()); }
/// <summary> /// Solves the given <see cref="SudokuPuzzle"/> /// </summary> /// <param name="puzzle">The <see cref="SudokuPuzzle"/> being solved</param> /// <returns>A list of <see cref="SudokuPuzzle"/>s that are solutions to the given <see cref="SudokuPuzzle"/></returns> public List <SudokuPuzzle> Solve(SudokuPuzzle puzzle) { List <SudokuPuzzle> solutions = new List <SudokuPuzzle>(); Stack <SudokuPuzzle> puzzleStack = new Stack <SudokuPuzzle>(); puzzleStack.Push(puzzle.Clone()); while (puzzleStack.Count > 0) { try { SudokuPuzzle puzzleToSolve = puzzleStack.Pop(); if (puzzle.IsValid()) { bool puzzleAdvanced = false; do { puzzleAdvanced = false; for (int i = 0; i < this.strategies.Count; ++i) { while (this.strategies[i].AdvancePuzzle(puzzleToSolve)) { puzzleAdvanced = true; } } }while (puzzleAdvanced); if (puzzleToSolve.IsSolved() && puzzleToSolve.IsValid()) { solutions.Add(puzzleToSolve); if (solutions.Count > 1) { break; } } else { foreach (SudokuPuzzle guess in this.Guess(puzzleToSolve)) { puzzleStack.Push(guess); } } } } catch (Exception) { } } return(solutions); }
/// <summary> /// Finds a <see cref="Cell"/> with the least possible values (other than solved <see cref="Cell"/>s), /// and tries each possible puzzle using those values in that cell /// </summary> /// <param name="puzzle">The <see cref="SudokuPuzzle"/> being solved</param> /// <returns>The puzzle solutions found from guessing</returns> private List <SudokuPuzzle> Guess(SudokuPuzzle puzzle) { if (!puzzle.IsValid()) { return(new List <SudokuPuzzle>()); } Cell cellToGuessOn = null; int x = -1; int y = -1; for (int i = 0; i < puzzle.Rows.Count; ++i) { for (int k = 0; k < puzzle.Rows[i].Count; ++k) { Cell cell = puzzle.Rows[i][k]; if (cell.Count > 1) { if (cellToGuessOn == null) { cellToGuessOn = cell; x = i; y = k; } else if (cellToGuessOn.Count > cell.Count) { cellToGuessOn = cell; x = i; y = k; } } } } List <SudokuPuzzle> guesses = new List <SudokuPuzzle>(); if (cellToGuessOn != null) { foreach (int allowedValue in cellToGuessOn.AllowedValues.Keys) { SudokuPuzzle guess = puzzle.Clone(); guess.Rows[x][y].RemoveAllExcept(allowedValue); guesses.Add(guess); } } return(guesses); }