コード例 #1
0
        /// <summary>
        /// This will solve the puzzle by using a recursive Backtracking algorthim
        /// </summary>
        /// <remarks>
        /// This is a brute force routine
        /// </remarks>
        /// <param name="puzzle"></param>
        /// <param name="cells"></param>
        /// <param name="index"></param>
        private static void SolveRecursive(Puzzle puzzle, Puzzle.Cell[] cells, int index)
        {
            int minIndex = cells.GetLowerBound(0);
            int maxIndex = cells.GetUpperBound(0);

            // Check the index, and exit if the index is outside the boundries
            if (index < minIndex || index > maxIndex)
            {
                return;
            }

            // Much easier to reference a single cell in the beginning than array[index] the whole time
            Puzzle.Cell cell = cells[index];

            // Need to bypass if this cell is Locked.
            if (cell.IsLocked)
            {
                // Call recursively sending the next index to process
                SolveRecursive(puzzle, cells, index + 1);
            }
            else
            {
                // Re-Initialize the cell's value
                cell.Value = null;

                // Check to see if the puzzle is solved, if so, break out of the routine all together
                // Iterate through all the possible values for this cell
                while (!Validator.IsSolved(puzzle))
                {
                    if (cell.Value.GetValueOrDefault() < Puzzle.MAX_VALUE)
                    {
                        // Increment current cell
                        // Note: The Increment method has logic to determine if the cell is Locked already
                        cell.Increment();

                        // Determine if we stay on the current cell (to obtain a valid value) or move to the next cell
                        // Call recursively sending the next index to process
                        if (!Validator.IsExistValue(puzzle, cell))
                        {
                            SolveRecursive(puzzle, cells, index + 1);
                        }
                    }
                    else
                    {
                        // Re-Initialize the cell's value if the current value is at the max value
                        cell.Value = null;

                        // By breaking out of the loop, we are forcing the method to return to the previous call
                        break;
                    }
                }
            }
        }
コード例 #2
0
        /// <summary>
        /// Checks to see if cell's value already exists in the cell's current row, column and quadrient
        /// </summary>
        /// <param name="cell"></param>
        /// <returns></returns>
        internal static bool IsExistValue(Puzzle puzzle, Puzzle.Cell cell)
        {
            bool ret = false;

            Puzzle.Cell[] cells         = null;
            Puzzle.Cell[] filteredCells = null;

            // Check current row to determine if the cell's value already exists by iterating through all the columns in that row
            cells = Utils.Transpose <Puzzle.Cell>(puzzle.ToArray(),
                                                  cell.Row,
                                                  1,
                                                  0,
                                                  Puzzle.PUZZLE_GRID_SIZE);

            // Need to remove the cell that we are checking against
            filteredCells = cells.Where(x => x.Column != cell.Column)
                            .ToArray();
            ret = ret || IsExistValue(cell.Value.GetValueOrDefault(), filteredCells);


            // Check current column to determine if the cell's value already exists by iterating through all the rows in that column
            cells = Utils.Transpose <Puzzle.Cell>(puzzle.ToArray(),
                                                  0,
                                                  Puzzle.PUZZLE_GRID_SIZE,
                                                  cell.Column,
                                                  1);

            // Need to remove the cell that we are checking against
            filteredCells = cells.Where(x => x.Row != cell.Row)
                            .ToArray();
            ret = ret || IsExistValue(cell.Value.GetValueOrDefault(), filteredCells);


            // Check current quadrient to determine if the cell's value already exists by iterating through all the rows and columns in that quadrient
            // Determine quadrient
            int quadRow = (cell.Row / Puzzle.QUADRIENT_GRID_SIZE);
            int quadCol = (cell.Column / Puzzle.QUADRIENT_GRID_SIZE);

            cells = Utils.Transpose <Puzzle.Cell>(puzzle.ToArray(),
                                                  (quadRow * Puzzle.QUADRIENT_GRID_SIZE),
                                                  Puzzle.QUADRIENT_GRID_SIZE,
                                                  (quadCol * Puzzle.QUADRIENT_GRID_SIZE),
                                                  Puzzle.QUADRIENT_GRID_SIZE);

            // Need to remove the cell that we are checking against
            filteredCells = cells.Where(x => !((x.Row == cell.Row) && (x.Column == cell.Column)))
                            .ToArray();
            ret = ret || IsExistValue(cell.Value.GetValueOrDefault(), filteredCells);


            return(ret);
        }
コード例 #3
0
ファイル: Generator.cs プロジェクト: RyanPLehan/Sudoku
        /// <summary>
        /// This will randomly pick a cell from the given puzzle
        /// </summary>
        /// <remarks>
        /// If the picked cell has a value or is locked, then a new cell will be randomly chosen
        /// </remarks>
        /// <param name="puzzle"></param>
        /// <returns></returns>
        private Puzzle.Cell GetRandomCell(Puzzle puzzle)
        {
            int row = 0;
            int col = 0;

            Puzzle.Cell cell   = null;
            Random      random = new Random();

            do
            {
                row  = random.Next(0, Puzzle.PUZZLE_GRID_SIZE);
                col  = random.Next(0, Puzzle.PUZZLE_GRID_SIZE);
                cell = puzzle.GetCell(row, col);
            } while (cell.IsLocked || cell.Value.HasValue);

            return(cell);
        }
コード例 #4
0
ファイル: Generator.cs プロジェクト: RyanPLehan/Sudoku
        /// <summary>
        /// Populate puzzle with random values
        /// </summary>
        /// <remarks>
        /// This will perform some validations to make sure the random value can be placed within the specified cell
        /// </remarks>
        /// <param name="puzzle"></param>
        private void Populate(Puzzle puzzle)
        {
            int    value  = 0;
            Random random = new Random();

            // Loop for the number of random number values to generate
            for (int i = 0; i < NumberOfRandomValues; i++)
            {
                Puzzle.Cell cell = GetRandomCell(puzzle);

                // Loop until we have a valid random number in a random cell
                do
                {
                    cell.Value = null;                                          // Clear out previous value
                    cell       = GetRandomCell(puzzle);
                    value      = random.Next(Puzzle.MIN_VALUE, Puzzle.MAX_VALUE + 1);
                    cell.Value = Convert.ToByte(value);
                } while (Validator.IsExistValue(puzzle, cell));

                // Lock cell so that value cannot be changed
                cell.IsLocked = true;
            }
        }
コード例 #5
0
        /// <summary>
        /// This will solve the puzzle by using a non-recursive Backtracking algorthim
        /// </summary>
        /// <remarks>
        /// This is a brute force routine
        /// </remarks>
        /// <param name="puzzle"></param>
        /// <param name="cells"></param>
        private static void SolveNonRecursive(Puzzle puzzle)
        {
            // Much easier to work with a single dimensional array, so lets transpose it
            Puzzle.Cell[] cells = Utils.Transpose <Puzzle.Cell>(puzzle.ToArray(),
                                                                0,
                                                                Puzzle.PUZZLE_GRID_SIZE,
                                                                0,
                                                                Puzzle.PUZZLE_GRID_SIZE);

            int minIndex        = cells.GetLowerBound(0);
            int maxIndex        = cells.GetUpperBound(0);
            int index           = minIndex;
            int directionFactor = 0;        // 1 to move forward, -1 to move backward

            // Loop until we have either solved or exhusted our routine
            while (!Validator.IsSolved(puzzle) && index >= minIndex)
            {
                // Check to see if we have gone beyond the boundries, change the index factor
                if (index > maxIndex)
                {
                    index           = maxIndex;
                    directionFactor = -1;
                }

                // Much easier to reference a single cell in the beginning than array[index] the whole time
                Puzzle.Cell cell = cells[index];

                // Need to bypass if this cell is IsLocked. (if cell is locked keep the directionFactor the same)
                if (!cell.IsLocked)
                {
                    // Iterate through all the possible values for this cell
                    if (cell.Value.GetValueOrDefault() < Puzzle.MAX_VALUE)
                    {
                        // Increment current cell
                        // Note: The Increment method has logic to determine if the cell is Locked already
                        cell.Increment();

                        // Determine if we stay on the current cell (to obtain a valid value) or move to the next cell
                        if (Validator.IsExistValue(puzzle, cell))
                        {
                            directionFactor = 0;        // Stay on current cell
                        }
                        else
                        {
                            directionFactor = 1;        // Move to next cell
                        }
                    }
                    else
                    {
                        // Re-Initialize the cell's value if the current value is at the max value
                        cell.Value = null;

                        // Set the direction factor to the previous cell
                        directionFactor = -1;
                    }
                }
                else
                {
                    // The index will not change if the first cell is locked and the directionFactor is zero
                    if (directionFactor == 0)
                    {
                        directionFactor = 1;
                    }
                }

                // Change the index by the direction factor
                index += directionFactor;
            }
        }