/// <summary> /// Search for cells with an unique possible value. /// </summary> /// <param name="sudokuCellsToSolve">List of cells pending to solve.</param> private bool SolveCellsWithOnePossibility(List <SuDoCell> sudokuCellsToSolve) { bool result = false; int i = 0; while (i < sudokuCellsToSolve.Count) { if (sudokuCellsToSolve[i].IsValid) { sudokuCellsToSolve.RemoveAt(i); } else if (sudokuCellsToSolve[i].NumPossibilities == 1) { SuDoCell cell = sudokuCellsToSolve[i]; int solution = cell.PickRandomPossibility(); if (solution < 0) { throw new ApplicationException("Sudoku cannot be solved!"); } this.SetValue(cell.Row, cell.Column, solution); this.OnSudokuStrategyUsed( new SuDoStrategyUsedEventArgs(SuDoStrategy.UniqueValueForCell, cell)); result = true; sudokuCellsToSolve.RemoveAt(i); } else { i++; } } return(result); }
/// <summary> /// 解答题目 /// </summary> public void Solve() { // Prepare cells, rows, cols and squares pending to solve... List <SuDoCell> sudokuCellsToSolve = new List <SuDoCell>(); List <int> sudokuRowsToSolve = new List <int>(); List <int> sudokuColsToSolve = new List <int>(); List <int> sudokuSquaresToSolve = new List <int>(); for (int row = 0; row < 9; row++) { for (int col = 0; col < 9; col++) { if (!this[row, col].IsValid) { sudokuCellsToSolve.Add(this[row, col]); if (!sudokuRowsToSolve.Contains(row)) { sudokuRowsToSolve.Add(row); } if (!sudokuColsToSolve.Contains(col)) { sudokuColsToSolve.Add(col); } int square = (row / 3) * 3 + (col / 3); if (!sudokuSquaresToSolve.Contains(square)) { sudokuSquaresToSolve.Add(square); } } } } sudokuRowsToSolve.Sort(); sudokuColsToSolve.Sort(); sudokuSquaresToSolve.Sort(); // While any cell to solve... while (sudokuCellsToSolve.Count > 0) { while (true) { if (this.SolveCellsWithOnePossibility(sudokuCellsToSolve)) { continue; } if (this.SolveUniqueCellValueInRows(sudokuRowsToSolve)) { continue; } if (this.SolveUniqueCellValueInCols(sudokuColsToSolve)) { continue; } if (this.SolveUniqueCellValueInSquares(sudokuSquaresToSolve)) { continue; } break; } if (sudokuCellsToSolve.Count == 0) { break; } // Cannot solve any cell...now we depend on luck!! // Find the cell with the minimum possibilities to apply random... int index = -1, minPossib = 10; for (int i = 0; i < sudokuCellsToSolve.Count; i++) { if (minPossib > sudokuCellsToSolve[i].NumPossibilities) { index = i; minPossib = sudokuCellsToSolve[i].NumPossibilities; } } // We choose a solution randomly SuDoCell cell = sudokuCellsToSolve[index]; int solution = cell.PickRandomPossibility(); if (solution < 0) { throw new ApplicationException( string.Format("Cannot found a solution for cell at [{0}, {1}].", cell.Row + 1, cell.Column + 1)); } sudokuCellsToSolve.RemoveAt(index); this.SetValue(cell.Row, cell.Column, solution); this.OnSudokuStrategyUsed( new SuDoStrategyUsedEventArgs(SuDoStrategy.RandomPick, cell)); } }