public SudokuPuzzle GenerateSudoku(SudokuDifficuty difficulty, int length = 9)
        {
            // get randomly filled out sudoku
            SudokuPuzzle solution = SolveSudoku(new SudokuPuzzle());
            SudokuPuzzle sudoku   = (SudokuPuzzle)solution.Clone();

            // check how many fields need to be removed (depending on desired difficulty)
            int fieldsToRemove = ((length * length) - (int)difficulty);

            while (fieldsToRemove > 0)
            {
                int freeFieldsCount = sudoku.GetFreeFields().Count;

                foreach (var field in sudoku.GetSetFields().Shuffle())
                {
                    if (fieldsToRemove > 0 && isFieldDetermined(sudoku, solution, field.RowIndex, field.ColumnIndex))
                    {
                        field.SetValue(0);
                        fieldsToRemove--;
                    }
                }

                // check if progress was made (if not => try with another sudoku puzzle)
                if ((freeFieldsCount - sudoku.GetFreeFields().Count) == 0)
                {
                    sudoku = GenerateSudoku(difficulty, length);
                    break;
                }
            }

            // check if the generated sudoku is unique. if not create a new one.
            return((HasSudokuUniqueSolution(sudoku)) ? sudoku : GenerateSudoku(difficulty, length));
        }
Beispiel #2
0
        public bool HasSudokuUniqueSolution(SudokuPuzzle sudoku)
        {
            // sudokus with 16 or less determinded fields cannot have a unique solution
            // source: https://www.technologyreview.com/s/426554/mathematicians-solve-minimum-sudoku-problem/
            bool ret = (sudoku.GetSetFields()?.Count > 16);

            if (ret)
            {
                // solve sudoku (gets one solution out of possibly many solutions)
                var solution = SolveSudoku(sudoku);
                ret = (solution != null);

                if (ret)
                {
                    var temp = (SudokuPuzzle)sudoku.Clone();

                    // go through all empty fields (filled out fields are ignored)
                    while (ret && !temp.IsSolved())
                    {
                        // choose a free field with a minimum amount of remaining possibilities
                        int minPossibleValuesCount = temp.GetFreeFields().Select(x => x.GetPossibleValuesCount()).Min();
                        var field = temp.GetFreeFields().Where(x => x.GetPossibleValuesCount() == minPossibleValuesCount).ChooseRandom();

                        // check if the field is determined; if not, there is a second solution => return false
                        ret = isFieldDetermined(temp, solution, field);

                        // apply the determined value to the sudoku => less possibilities
                        field.SetValue(solution.Fields[field.RowIndex, field.ColumnIndex].Value);
                    }
                }
            }

            return(ret);
        }
Beispiel #3
0
        private bool removeField(SudokuPuzzle sudoku, SudokuPuzzle solution)
        {
            foreach (SudokuField field in sudoku.GetSetFields().Shuffle())
            {
                // clone sudoku and set the field value to 0
                SudokuPuzzle temp      = (SudokuPuzzle)sudoku.Clone();
                SudokuField  tempField = temp.Fields[field.RowIndex, field.ColumnIndex];
                tempField.SetValue(0);

                if (HasSudokuUniqueSolution(temp))
                {
                    field.SetValue(0);
                    return(true);
                }
            }

            return(false);
        }