Beispiel #1
0
 /// <summary>
 /// FillSingleChoices iterates through empty cells. For any empty cell
 /// with only one possible value, it fills in that value.
 /// </summary>
 /// <param name="grid">Current state of grid</param>
 private void FillSingleChoices(PuzzleGrid grid)
 {
     bool anyChanges = false;                    //Set if cell value set
     int numChoices;                           //Number of choices found
     do            //While changes have been made AND grid is not solved
     {
         anyChanges = false;
         for (int i = 0; i < 9; i++)         //Iterate through every row
         {
             for (int j = 0; j < 9; j++)  //Iterate through every column
             {
                 if (grid.Grid[i, j] == 0)
                 {       //Get number of choices available in grid[i, j]
                     numChoices = ListPossible(i, j, grid);
                     if (numChoices == 1) //If only one choice set value
                     {
                         grid.UserSetCell(i, j, FirstTrue());
                                       //Changes made, anyChanges = true
                         anyChanges = (grid.Grid[i, j] != 0);
                     }
                 }
             }
         }
     } while(anyChanges == true && !IsSolved(grid));
 }
Beispiel #2
0
 /// <summary>
 /// IsPossible returns true if IsInRow, IsInCol & IsIn3x3 return false
 /// </summary>
 /// <param name="g">Current state of the grid</param>
 /// <param name="row">row of target cell</param>
 /// <param name="col">column of target cell</param>
 /// <param name="value">value being sought</param>
 /// <returns>True if value can occupy cell at [row, col]</returns>
 private bool IsPossible(PuzzleGrid g, int row, int col, int value)
 {                     //Return true if value can go into [row, col] now
     bool result;
     result = (!IsInRow(g, row, value) && ! IsInCol(g, col, value) &&
         !IsIn3X3(g, row, col, value));
     return result;
 }
Beispiel #3
0
        /// <summary>
        /// This function takes a PuzzleGrid and updates the game board values to the values in the PuzzleGrid.
        /// </summary>
        /// <param name="grid">The puzzle gird.</param>
        private void SetPuzzleGrid(PuzzleGrid grid)
        {
            for (int i = 0; i < GameBoardRows; i++)
            {
                for (int j = 0; j < GameBoardCols; j++)
                {
                    var box = (TextBox)FindName(GetTextBoxNameFromRowColumn(i + 1, j + 1));
                    if (box != null)
                    {
                        box.Style = (Style)(Resources["GridElement"]);

                        if (grid.Grid[i, j] < 0)
                        {
                            box.Text  = ((-1) * grid.Grid[i, j]).ToString();
                            box.Style = (Style)(Resources["GridElementDisabled"]);
                        }
                        else if (grid.Grid[i, j] > 0)
                        {
                            box.Text = grid.Grid[i, j].ToString();
                        }
                        else
                        {
                            box.Text = "";
                        }
                    }
                }
            }
        }
Beispiel #4
0
 /// <summary>
 /// FindFewestChoices finds the first cell having the smallest number
 /// of available choices, and sets the row and column of that cell for
 /// use in SolveGrid
 /// </summary>
 /// <param name="grid">Current state of the grid</param>
 /// <param name="r">OUTPUT sets r for use in caller</param>
 /// <param name="c">OUTPUT sets c for use in caller</param>
 /// <param name="numChoices">OUTPUT sets var for use in caller</param>
 /// <returns>Returns true if valid cell found, false if not</returns>
 private bool FindFewestChoices(PuzzleGrid grid, out int r, out int c,
     out int numChoices)
 {
     bool[] minList = new bool[10];
     int numCh, minR, minC, minChoice, i, j;
     bool bad, result;
     minChoice = 10;
     minR = 0;
     minC = 0;
     for (i = 1; i < 10; i++)              //Initialize minList to FALSE
     {
         minList[i] = false;
     }
     bad = false;
     i = 0;
     while (!bad && i < 9) //While not a bad solutn and trying valid row
     {
         j = 0;
         while (!bad && j < 9) //not a bad solutn and trying valid column
         {
             if (grid.Grid[i, j] == 0)
             {
                 numCh = ListPossible(i, j, grid);    //Get # of choices
                 if (numCh == 0)     //If no choices found, bad solution
                 {
                     bad = true;
                 }
                 else                             //If not bad solutn...
                 {
                     if (numCh < minChoice)   //If less than current min
                     {
                         minChoice = numCh;          //Set new min value
                         list.CopyTo(minList, 0);//Save list of possible
                         minR = i;          //set row of cell with least
                         minC = j;          //set col of cell with least
                     }
                 }
             }
             j++;
         }
         i++;
     }
     if (bad || minChoice == 10)  //If bad solutn or minChoice never set
     {
         result = false;                    //No fewest possible choices
         r = 0;
         c = 0;
         numChoices = 0;
     }
     else
     {
         result = true; //Valid cell found, return information to caller
         r = minR;
         c = minC;
         numChoices = minChoice;
         minList.CopyTo(list, 0);
     }
     return result;
 }
        public PuzzleGrid InitGrid()
        {                                                                  //Randomly fill in the first row and column of puzzlegrid
            PuzzleGrid tempGrid = new PuzzleGrid {
            };                                                             //temporary grid to assign values into
            int        row      = 0;                                       //variable for navigating 'rows'
            int        col      = 0;                                       //variable for navigating 'columns'
            int        newVal;                                             //value to place into grid
            bool       solved;
            List <int> valueSet = new List <int>(Enumerable.Range(-9, 9)); //range
            //of numbers that can be added to the grid
            List <int> valueSet2 = new List <int>();                       //placeholder values in column 0
            Random     rnd       = new Random();                           //random variable for choosing random number
            int        randIndex = 0;                                      //index in valueSet/valueSet2 that is accessed

            randIndex = rnd.Next(0, 8);                                    //get a random number and place in grid(0,0)
            newVal    = valueSet[randIndex];
            tempGrid.InitSetCell(row, col, newVal);
            valueSet.Remove(newVal); //remove paced value from options
            for (row = 1; row < 9; row++)
            {                        //fills in column 0 with remaining possible values, storing in place-
                      //holder as it goes so as to preserve when placing in row 0 later
                randIndex = rnd.Next(0, valueSet.Count);
                newVal    = valueSet[randIndex];
                valueSet2.Add(newVal);
                valueSet.Remove(newVal);
                tempGrid.InitSetCell(row, col, newVal);
            }
            row = 0;         //reset row to 0
            for (col = 1; col < 3; col++)
            {                //fills in col 1,2 of row 0, checking that don't duplicate the
                //values in rows 1,2 of col 0
                randIndex = rnd.Next(0, valueSet2.Count);
                newVal    = valueSet2[randIndex];
                while ((newVal == tempGrid.Grid[1, 0] || (newVal == tempGrid.Grid[2, 0])))
                {
                    randIndex = rnd.Next(0, valueSet2.Count);
                    newVal    = valueSet2[randIndex];
                }
                valueSet2.Remove(newVal);
                tempGrid.InitSetCell(row, col, newVal);
            }
            for (col = 3; col < 9; col++)
            {                   //fill in remainder of row 0 with remaining possible values
                randIndex = rnd.Next(0, valueSet2.Count);
                newVal    = valueSet2[randIndex];
                valueSet2.Remove(newVal);
                tempGrid.InitSetCell(row, col, newVal);
            }
            do
            {
                puzzleSolver = new PuzzleSolver();
                puzzleSolver.SolveGrid((PuzzleGrid)tempGrid.Clone(), false);     //Slv to fill remainder of grid
                SolutionGrid = puzzleSolver.SolutionGrid;
            } while (SolutionGrid == null || SolutionGrid.IsBlank());
            PermaGrid = Blanker(SolutionGrid); //call Blanker to carry out the
            return(PermaGrid);                 //blanking of fileds,then return the grid to user to solve
        }
Beispiel #6
0
 /// <summary>
 /// IsInColumn checks if given value occurs in the given row.
 /// </summary>
 /// <param name="grid">Current state of the grid</param>
 /// <param name="col">Column being check</param>
 /// <param name="value">Value being sought</param>
 /// <returns></returns>
 private bool IsInCol(PuzzleGrid grid, int col, int value)
 {
     bool result = false;
     for (int i = 0; i < 9; i++)                //Iterate through column
     {                          //check if cell holds value being sought
         result = result || (Math.Abs(grid.Grid[i, col]) == value);
     }
     return result;
 }
Beispiel #7
0
 /// <summary>
 /// IsInRow checks if given value occurs in the given row
 /// </summary>
 /// <param name="grid">Current state of puzzle grid</param>
 /// <param name="row">Row to check</param>
 /// <param name="value">Value to look for</param>
 /// <returns></returns>
 private bool IsInRow(PuzzleGrid grid, int row, int value)
 {
     bool result = false;
     for (int i = 0; i < 9; i++)                   //Iterate through row
     {                          //check if cell holds value being sought
         result = result || (Math.Abs(grid.Grid[row, i]) == value);
     }
     return result;
 }
        //	Call SolveGrid to solve puzzlegrid
        //Store solved gamegrid as the correct solution in solutiongrid

        public PuzzleGrid Blanker(PuzzleGrid solvedGrid)
        {                              //enable blanking of squares based on difficulty
            PuzzleGrid tempGrid;
            PuzzleGrid saveCopy;
            //temporary grids to save between tests
            bool unique      = true;             //flag for if blanked form has unique soln
            int  totalBlanks = 0;                //count of current blanks
            int  tries       = 0;                //count of tries to blank appropriately
            int  desiredBlanks;                  //amount of blanks desired via difficulty
            int  symmetry = 0;                   //symmetry type

            tempGrid = (PuzzleGrid)solvedGrid.Clone();
            //cloned input grid (no damage)
            Random rnd = new Random();    //allow for random number generation

            switch (difficulty)           //set desiredBlanks via chosen difficulty
            {
            case Difficulty.Easy:         //easy difficulty
                desiredBlanks = 40;
                break;

            case Difficulty.Medium:         //medium difficulty
                desiredBlanks = 45;
                break;

            case Difficulty.Hard:         //hard difficulty
                desiredBlanks = 50;
                break;

            default:         //easy difficulty
                desiredBlanks = 40;
                break;
            }

            symmetry = rnd.Next(0, 2);                   //Randomly select symmetry
            do
            {                                            //call RandomlyBlank() to blank random squares symmetrically
                saveCopy = (PuzzleGrid)tempGrid.Clone(); // in case undo needed
                tempGrid = RandomlyBlank(tempGrid, symmetry, ref totalBlanks);
                //blanks 1 or 2 squares according to symmetry chosen
                puzzleSolver = new PuzzleSolver();
                unique       = puzzleSolver.SolveGrid((PuzzleGrid)tempGrid.Clone(), true);       // will it solve uniquely?
                if (!unique)
                {
                    tempGrid = (PuzzleGrid)saveCopy.Clone();
                    tries++;
                }
            } while((totalBlanks < desiredBlanks) && (tries < 1000));
            solvedGrid = tempGrid;
            solvedGrid.Finish();
            return(solvedGrid);
        }
        public PuzzleGrid RandomlyBlank(PuzzleGrid tempGrid, int sym, ref int blankCount)
        {
            //blank one or two squares(depending on if on center line) randomly
            Random rnd    = new Random();           //allow random number generation
            int    row    = rnd.Next(0, 8);         //choose randomly the row
            int    column = rnd.Next(0, 8);         //and column of cell to blank

            while (tempGrid.Grid[row, column] == 0) //don't blank a blank cell
            {
                row    = rnd.Next(0, 8);
                column = rnd.Next(0, 8);
            }
            tempGrid.InitSetCell(row, column, 0); //clear chosen cell
            blankCount++;                         //increment the count of blanks
            switch (sym)
            {
            //based on symmetry, blank a second cell
            case 0:                                       //vertical symmetry
                if (tempGrid.Grid[row, 8 - column] != 0)  //if not already blanked
                {
                    blankCount++;                         //increment blank counter
                }
                tempGrid.InitSetCell(row, 8 - column, 0); //blank opposite cell
                break;

            case 1:         //horizontal symmetry
                if (tempGrid.Grid[8 - row, column] != 0)
                {
                    blankCount++;
                }
                tempGrid.InitSetCell(8 - row, column, 0);
                break;

            case 2:         //diagonal symmetry
                if (tempGrid.Grid[column, row] != 0)
                {
                    blankCount++;
                }
                tempGrid.InitSetCell(column, row, 0);
                break;

            default:         //diagonal symmetry
                if (tempGrid.Grid[row, 8 - column] != 0)
                {
                    blankCount++;
                }
                tempGrid.InitSetCell(column, row, 0);
                break;
            }
            return(tempGrid);
        }
Beispiel #10
0
        /// <summary>
        /// This clones the object.
        /// </summary>
        /// <returns>A clone of itself.</returns>
        public object Clone()
        {
            //enable cloning for safe copying of the object
            PuzzleGrid p = new PuzzleGrid();

            for (int i = 0; i < Max; i++)
            {
                for (int j = 0; j < Max; j++)
                {
                    p.InitSetCell(i, j, Grid[i, j]);
                }
            }
            return(p);
        }
Beispiel #11
0
        // The following methods are helper methods
        /// <summary>
        /// Enters the puzzle entry state.
        /// </summary>
        private void EnterPuzzleEntryState()
        {
            // clear puzzle grid
            puzzleGrid = new PuzzleGrid();
            SetPuzzleGrid(puzzleGrid);

            // hide buttons
            SolveNow.Visibility      = Visibility.Hidden;
            HintsBox.Visibility      = Visibility.Hidden;
            HintsBoxTitle.Visibility = Visibility.Hidden;

            // show correct buttons
            EntryComplete.Visibility = Visibility.Visible;

            inPuzzleEnterMode = true;
        }
Beispiel #12
0
 /// <summary>
 /// IsSolved checks to see if all cells in the grid contain a value.
 /// If so, due to how the solve algorithm solves, the puzzle must be 
 ///  solved correctly.
 /// </summary>
 /// <param name="grid">Current state of the puzzle grid</param>
 /// <returns>TRUE: Puzzle is solved, FALSE: Not solved</returns>
 private bool IsSolved(PuzzleGrid grid)
 {
     bool result = true;                       //Assume puzzle is solved
     int r, c;
     r = 0;
     while (result == true && r < 9)                   //Check every row
     {
         c = 0;
         while (result == true && c < 9)            //Check every column
         {                //If an empty cell is found, result gets FALSE
             result = (result && grid.Grid[r, c] != 0);
             c++;
         }
         r++;
     }
     return result;
 }
Beispiel #13
0
 /// <summary>
 /// ListPossible populates list[] with "true" at each index
 /// representing that value is a possible value for cell at [row, col].
 /// It returns the total count of possible values in that square
 /// </summary>
 /// <param name="row">Row of target cell</param>
 /// <param name="col">Column of target cell</param>
 /// <param name="g">current state of grid</param>
 /// <returns>Integer count of possible values for given cell</returns>
 private int ListPossible(int row, int col, PuzzleGrid g)
 {
     int count = 0;
     ClearList();              //Create a fresh list for bool population
     for (int i = 1; i < 10; i++)          //For i = 1..9 (valid values)
     {
         if (IsPossible(g, row, col, i) == true)   //If i can go in cell
         {
             list[i] = true;
             count++;
         }
         else                     //Value of i found in Row, Col, or 3x3
         {
             list[i] = false;
         }
     }
     return count;
 }
Beispiel #14
0
        /// <summary>
        /// Creates a new game.
        /// </summary>
        private void MakeNewGame(bool noCancel = false)
        {
            var dlg = new NewGameDifficultyDialogBox(noCancel)
            {
                Owner = this
            };

            dlg.ShowDialog();
            var difficulty = dlg.HowHard;

            if (dlg.CreateGame)
            {
                var        puzzleGenerator = new PuzzleGenerator(difficulty);
                PuzzleGrid newPuzzleGrid   = puzzleGenerator.InitGrid();

                SetPuzzleGrid(newPuzzleGrid);
                puzzleGrid = newPuzzleGrid;
            }
        }
Beispiel #15
0
 /// <summary>
 /// IsIn3x3 determines which 3x3 grid cell is in using GroupNum. 
 /// Values are:
 /// [0, 0]  [0, 1]  [0, 2]
 /// [1, 0]  [1, 1]  [1, 2]
 /// [2, 0]  [2, 1]  [2, 2]
 /// And then checks if given value occurs in the 3x3 grid.
 /// </summary>
 /// <param name="g">Current state of the grid</param>
 /// <param name="row">Row of cell being checked</param>
 /// <param name="col">Column of cell being checked</param>
 /// <param name="value">Value being sought</param>
 /// <returns>True if Value is found, false if not</returns>
 private bool IsIn3X3(PuzzleGrid g, int row, int col, int value)
 {
     int rLow;
     int cLow;
     rLow = 3 * GroupNum(row);    //Index of smallest number row in grid
     cLow = 3 * GroupNum(col);//Index of smallest number columin in grid
     bool result = false;
     for (int i = rLow; i < rLow + 3; i++) //Check all 3 rows in subgrid
     {
         for (int j = cLow; j < cLow + 3; j++)     //Check all 3 columns
         {               //Compare value of cell with value being sought
             if (Math.Abs(g.Grid[i, j]) == value)
             {
                 result = true;
             }
         }
     }
     return result;
 }
Beispiel #16
0
        /// <summary>
        /// This function opens a game.
        /// </summary>
        public PuzzleGrid OpenFile(String fileName)
        {
            PuzzleGrid openedPuzzle = new PuzzleGrid();
            int        i            = 0; //mnemonic: row
            int        j            = 0; //mnemonic: column
            int        cellVal      = 0;
            bool       eOF          = false;

            using (StreamReader reader = new StreamReader(fileName))
            {
                for (i = 0; i < 9; i++)
                {
                    string currentLine;
                    if ((currentLine = reader.ReadLine()) != null)
                    {
                        for (j = 0; j < 9; j++)
                        {
                            cellVal = (int)currentLine[2 * j] - '0';
                            if (currentLine[(2 * j) + 1] == '+')
                            {
                                openedPuzzle.InitSetCell(i, j, cellVal);
                            }
                            else if (currentLine[(2 * j) + 1] == '-')
                            {
                                openedPuzzle.InitSetCell(i, j, -(cellVal));
                            }
                        }
                    }
                    else
                    {
                        eOF = true;
                    }
                }
            }
            if (eOF)
            {
                return(null);
            }
            else
            {
                return(openedPuzzle);
            }
        }
Beispiel #17
0
        /// <summary>
        /// This function saves a game.
        /// </summary>
        public bool SaveFile(PuzzleGrid board, String fileName, bool unsolved = false)
        {
            int        i      = 0; //mnemonic: row
            int        j      = 0; //mnemonic: column
            TextWriter writer = new StreamWriter(fileName);
            int        cellVal;

            for (i = 0; i < 9; i++)
            {
                string currentLine = "";
                for (j = 0; j < 9; j++)
                {
                    cellVal = board.Grid[i, j];
                    if (cellVal < 0)
                    {
                        currentLine += Math.Abs(cellVal).ToString();
                        currentLine += "-";
                    }
                    else
                    {
                        if (unsolved)
                        {
                            currentLine += "0";
                        }
                        else
                        {
                            currentLine += cellVal.ToString();
                        }

                        currentLine += "+";
                    }
                }
                writer.WriteLine(currentLine);
            }
            writer.Close();
            return(true);
        }
Beispiel #18
0
        /// <summary>
        /// This method shows the open file dialog box.
        /// </summary>
        private void OpenFile()
        {
            // Show save file dialog box
            var result = openGameDialog.ShowDialog();

            // Process save file dialog box results
            if (result == true)
            {
                // Save document
                string fileName = openGameDialog.FileName;

                PuzzleGrid grid = fileHandler.OpenFile(fileName);
                puzzleGrid = (PuzzleGrid)grid.Clone();

                if (grid == null)
                {
                    MessageBox.Show("There was a problem opening your file. Please try again.");
                }
                else
                {
                    SetPuzzleGrid(grid);
                }
            }
        }
Beispiel #19
0
        /// <summary>
        /// This function instantiates all the game objects and sets up the game window.
        /// </summary>
        public UserInterface()
        {
            InitializeComponent();

            // Initialize game elements
            fileHandler = new FileHandler();

            //puzzleSolver = new PuzzleSolver();
            //var result = puzzleSolver.SolveGrid(puzzleGrid, true);
            //StatusBarText.Text = result ? "This puzzle has a solution solved." : "This puzzle cannot be solved.";

            // Initialize the save game dialog
            saveGameDialog = new SaveFileDialog {
                Filter = "Sudoku Games | *.sud", DefaultExt = ".sud"
            };
            openGameDialog = new OpenFileDialog {
                Filter = "Sudoku Games | *.sud", DefaultExt = ".sud"
            };

            puzzleGrid = new PuzzleGrid();
            SetPuzzleGrid(puzzleGrid);

            SetHintsBoxToDefault();
        }
Beispiel #20
0
        /// <summary>
        /// SolveGrid attempts to solve a puzzle by checking through all
        /// possible values for each cell, discarding values that do not lead
        /// to a valid solution. On a try, it recursively calls itself to
        /// maintain previous states of the grid to back track to if the
        /// current path fails. It creates a local version of the grid to
        /// facilitate this. It also checks if the puzzle is uniquely solvable.
        /// </summary>
        /// <param name="g">Current state of the grid</param>
        /// <param name="checkUnique">Do we care if it has unique soln?</param>
        /// <returns></returns>
        public bool SolveGrid(PuzzleGrid g, bool checkUnique)
        {
            PuzzleGrid grid = new PuzzleGrid();
            grid = (PuzzleGrid)g.Clone();                 //Copy the input grid
            int i, choice, r, c, numChoices;
            bool done, got_one, solved, result;
            got_one = false;
            recursions++;
            FillSingleChoices(grid);  //First, fill in all single choice values
            if (IsSolved(grid))                        //If it's already solved
            {
                if (numSolns > 0)               //If another soln already found
                {
                    stoplooking = true;                   //Don't look for more
                    result = false;              //Return false, no UNIQUE soln
                }
                else                               //If no other soln found yet
                {
                    numSolns++;
                    final[numSolns] = (PuzzleGrid)g.Clone();  //Save found soln
                    result = true;
                    SolutionGrid = grid;
                }
            }
            else                                            //If not solved yet
            {
                if (!FindFewestChoices(grid, out r, out c, out numChoices))
                {
                    result = false;                          //Invalid solution
                }
                else                                 //Current grid still valid
                {
                    i = 1;
                    done = false;
                    got_one = false;
                    while (!done && i <= numChoices)
                    {
                        choice = PickOneTrue();         //Pick a possible value
                        list[choice] = false;      //Won't want to use it again
                        grid.UserSetCell(r, c, choice);

                        if (recursions < MaxDepth)
                        {
                       //-----------We must go deeper. SUDCEPTION!-----------//
                             solved = (SolveGrid(grid, checkUnique)); //Recurse
                        }
                        else
                        {
                            solved = false;
                        }
                        if (stoplooking == true)
                        {
                            done = true;
                            got_one = true;
                        }
                        else
                        {
                            got_one = (got_one || solved);
                            if (!checkUnique)  //If not looking for unique soln
                            {
                                done = got_one;       //Then we have a solution
                            }
                        }
                        i++;
                    }
                    result = got_one;
                }
            }
            return result;
        }