Exemplo n.º 1
0
        /// <summary>
        ///
        /// </summary>
        /// <returns>the puzzle in form of SudokuGrid</returns>
        public SudokuGrid Setter()
        {
            PuzzleSolverAdvDS solve = new PuzzleSolverAdvDS();
            SudokuGrid        grid  = ConstructGrid();
            //Using Backtracking Solver to fill in a blank grid to get a starting solution - possibly the part of the generator that causes performance issues
            bool testing = false;//testing condition

            if (!testing)
            {
                try
                {
                    if (!solve.CompileBacktracker(grid, 2))
                    {
                        MessageBox.Show("Generator did not find a puzzle to generate");
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Something has gone terribly wrong...\r\nError: " + ex);
                    return(grid);
                }
            }
            else
            {
                #region Manual Testing Puzzle
                StringToGrid(grid, "600438079900705080800000032200004060000000000040600003180000005070806001560941008");
                #endregion
            }
            RemoveNumbers(grid, solve);
            return(grid);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Function that recieves a puzzle and the string version of the puzzle and tests the difficulty of the puzzle by solving it using the Human-Strategy solver
        /// </summary>
        /// <param name="puzzleGrid"></param>
        /// <param name="puzzleString"></param>
        /// <returns>returns the difficulty rating of the puzzle</returns>
        public long GetDifficulty(SudokuGrid puzzleGrid, string puzzleString, PuzzleSolverAdvDS solver)
        {
            long rating  = 0;
            int  counter = 0;

            for (int x = 0; x < 9; x++)
            {
                for (int y = 0; y < 9; y++)
                {
                    if (puzzleString[counter] == '0')
                    {
                        puzzleGrid.Cells[x][y].Candidates = new List <char> {
                            '1', '2', '3', '4', '5', '6', '7', '8', '9'
                        };
                    }
                    else
                    {
                        puzzleGrid.Cells[x][y].Candidates = new List <char> {
                        };
                    }
                    puzzleGrid.Cells[x][y].Num = puzzleString[counter];
                    counter++;
                }
            }
            solver.Solver(puzzleGrid, 1);
            rating = solver.g_Rating;
            puzzleGrid.Difficulty = solver.g_Difficulty;
            return(rating);
        }
Exemplo n.º 3
0
        /// <summary>
        /// checks for if the puzzle is valid in the sense that is has more than 7 unique numbers at any point in the puzzle, more than 16 givens, and one solution
        /// </summary>
        /// <param name="grid"></param>
        /// <returns></returns>
        public bool CheckValidity(SudokuGrid grid)
        {
            bool        minOfEight = false;
            int         givens     = 0;
            List <char> numList    = new List <char> {
                '1', '2', '3', '4', '5', '6', '7', '8', '9'
            };

            for (int x = 0; x < 9; x++)
            {
                for (int y = 0; y < 9; y++)
                {
                    if (grid.Cells[x][y].Num != '0')
                    {
                        numList.Remove(grid.Cells[x][y].Num);
                        if (numList.Count <= 1)
                        {
                            minOfEight = true;
                        }
                        givens++;
                    }
                }
            }
            if (!minOfEight || givens < 17)
            {
                return(false);
            }
            char[][] sudokuArray = new char[9][] { new char[9], new char[9], new char[9], new char[9], new char[9], new char[9], new char[9], new char[9], new char[9] };
            for (int r = 0; r < 9; r++)
            {
                for (int c = 0; c < 9; c++)
                {
                    sudokuArray[r][c] = grid.Cells[r][c].Num;
                }
            }
            PuzzleSolverAdvDS solve = new PuzzleSolverAdvDS();

            if (solve.CompileBacktracker(grid, 4))
            {
                string firstSol = GridToString(grid);
                grid = RestartPuzzle(grid, sudokuArray);
                if (solve.CompileBacktracker(grid, 1))
                {
                    string secSol = GridToString(grid);
                    if (firstSol == secSol)//valid puzzle
                    {
                        grid = RestartPuzzle(grid, sudokuArray);
                        return(true);
                    }
                    else
                    {
                        grid = RestartPuzzle(grid, sudokuArray);
                        return(false);
                    }
                }
            }
            return(true);
        }
Exemplo n.º 4
0
        public void PopulateTextBlock(int difficultyRating, string timeString, PuzzleSolverAdvDS puzzleSolver)
        {
            Show();
            AdditionalInfo.Text = "Difficulty Rating: " + difficultyRating + "\r\n" + timeString + "\r\nNumber of Steps: " + puzzleSolver.g_StepCounter;
            string solvePath = "";

            for (int i = 0; i < puzzleSolver.g_SolvePath.Count; i++)
            {
                if (puzzleSolver.g_SolvePath[i][0] != '-')
                {
                    solvePath += "\r\n" + puzzleSolver.g_SolvePath[i] + "\r\n\r\n";
                }
                else
                {
                    solvePath += puzzleSolver.g_SolvePath[i] + "\r\n";
                }
            }
            solvePathBlock.Text = solvePath;
        }
Exemplo n.º 5
0
        public void RemoveNumbers(SudokuGrid grid, PuzzleSolverAdvDS solve)
        {
            ///This section consists of constantly removing parallel numbers, e.g. [0,0] and [8,8] or [2,5] and [5,2], and checking if the puzzle is still valid (i.e. still has only one solution)

            int           removed      = 0;
            List <string> cellsChecked = new List <string>(81);
            List <int>    rowList      = new List <int> {
                0, 1, 2, 3, 4, 5, 6, 7, 8
            };
            List <int> colList = new List <int> {
                0, 1, 2, 3, 4, 5, 6, 7, 8
            };

            rowList = Shuffler_intList(rowList);
            colList = Shuffler_intList(colList);
            foreach (int row in rowList)
            {
                if (removed >= g_MaxRemoves)
                {
                    break;
                }
                foreach (int col in colList)
                {
                    if (removed >= g_MaxRemoves)
                    {
                        break;
                    }
                    if (!cellsChecked.Contains(row.ToString() + col.ToString()))
                    {
                        int altRow = NumberSwitch(row);
                        int altCol = NumberSwitch(col);

                        if (grid.Cells[altRow][altCol].Num != '0' && grid.Cells[row][col].Num != '0')
                        {
                            bool        valid   = false;
                            List <char> numList = new List <char> {
                                '1', '2', '3', '4', '5', '6', '7', '8', '9'
                            };
                            for (int x = 0; x < 9 && !valid; x++)//checks for if the puzzle is valid in the sense that is has more than 7 unique numbers at any point in the puzzle
                            {
                                for (int y = 0; y < 9 && !valid; y++)
                                {
                                    if (grid.Cells[x][y].Num != '0')
                                    {
                                        if ((x == altRow && y == altCol) == false && (x == row && y == col) == false)
                                        {
                                            numList.Remove(grid.Cells[x][y].Num);
                                        }
                                        if (numList.Count <= 1)
                                        {
                                            valid = true;
                                        }
                                    }
                                }
                            }
                            if (valid)
                            {
                                char[][] sudokuArray = new char[9][] { new char[9], new char[9], new char[9], new char[9], new char[9], new char[9], new char[9], new char[9], new char[9] };
                                for (int r = 0; r < 9; r++)
                                {
                                    for (int c = 0; c < 9; c++)
                                    {
                                        sudokuArray[r][c] = grid.Cells[r][c].Num;
                                    }
                                }
                                grid.Cells[row][col].Num       = '0';
                                grid.Cells[altRow][altCol].Num = '0';
                                if (solve.CompileBacktracker(grid, 4))
                                {
                                    string firstSol = GridToString(grid);
                                    grid = RestartPuzzle(grid, sudokuArray);
                                    grid.Cells[row][col].Num       = '0';
                                    grid.Cells[altRow][altCol].Num = '0';
                                    if (solve.CompileBacktracker(grid, 1))//tries Backtracking algorithm using reversed candidate lists so that if a solution that is different to the previous solution exists, it will be found, invalidating the puzzle
                                    {
                                        string secSol = GridToString(grid);
                                        if (firstSol == secSol)//valid puzzle
                                        {
                                            grid = RestartPuzzle(grid, sudokuArray);
                                            grid.Cells[row][col].Num       = '0';
                                            grid.Cells[altRow][altCol].Num = '0';
                                            if (grid.Cells[row][col] == grid.Cells[altRow][altCol])
                                            {
                                                removed++;
                                            }
                                            else
                                            {
                                                removed += 2;
                                            }
                                        }
                                        else//Multiple solutions
                                        {
                                            grid = RestartPuzzle(grid, sudokuArray);
                                        }
                                    }
                                }
                                else//Invalid puzzle, should never occur
                                {
                                    grid = RestartPuzzle(grid, sudokuArray);
                                }
                            }
                            if (grid.Cells[row][col] == grid.Cells[altRow][altCol])
                            {
                                cellsChecked.Add(row.ToString() + col.ToString());
                            }
                            else
                            {
                                cellsChecked.Add(row.ToString() + col.ToString());
                                cellsChecked.Add(altRow.ToString() + altCol.ToString());
                            }
                        }
                    }
                }
            }
            if (removed < g_MaxRemoves)
            {
                cellsChecked = new List <string>();
                foreach (int row in rowList)
                {
                    if (removed >= g_MaxRemoves)
                    {
                        break;
                    }
                    foreach (int col in colList)
                    {
                        if (removed >= g_MaxRemoves)
                        {
                            break;
                        }
                        if (!cellsChecked.Contains(row.ToString() + col.ToString()))
                        {
                            if (grid.Cells[row][col].Num != '0')
                            {
                                bool        valid   = false;
                                List <char> numList = new List <char> {
                                    '1', '2', '3', '4', '5', '6', '7', '8', '9'
                                };
                                for (int x = 0; x < 9 && !valid; x++)//checks for if the puzzle is valid in the sense that is has more than 7 unique numbers at any point in the puzzle
                                {
                                    for (int y = 0; y < 9 && !valid; y++)
                                    {
                                        if (grid.Cells[x][y].Num != '0')
                                        {
                                            if ((x == row && y == col) == false)
                                            {
                                                numList.Remove(grid.Cells[x][y].Num);
                                            }
                                            if (numList.Count <= 1)
                                            {
                                                valid = true;
                                            }
                                        }
                                    }
                                }
                                if (valid)
                                {
                                    char[][] sudokuArray = new char[9][] { new char[9], new char[9], new char[9], new char[9], new char[9], new char[9], new char[9], new char[9], new char[9] };
                                    for (int r = 0; r < 9; r++)
                                    {
                                        for (int c = 0; c < 9; c++)
                                        {
                                            sudokuArray[r][c] = grid.Cells[r][c].Num;
                                        }
                                    }
                                    grid.Cells[row][col].Num = '0';
                                    if (solve.CompileBacktracker(grid, 4))
                                    {
                                        string firstSol = GridToString(grid);
                                        grid = RestartPuzzle(grid, sudokuArray);
                                        grid.Cells[row][col].Num = '0';
                                        if (solve.CompileBacktracker(grid, 1))
                                        {
                                            string secSol = GridToString(grid);
                                            if (firstSol == secSol)//valid puzzle
                                            {
                                                grid = RestartPuzzle(grid, sudokuArray);
                                                grid.Cells[row][col].Num = '0';
                                                removed++;
                                            }
                                            else
                                            {
                                                grid = RestartPuzzle(grid, sudokuArray);
                                            }
                                        }
                                    }
                                    else
                                    {
                                        grid = RestartPuzzle(grid, sudokuArray);
                                    }
                                }
                            }
                            cellsChecked.Add(row.ToString() + col.ToString());
                        }
                    }
                }
            }
        }
Exemplo n.º 6
0
        /// <summary>
        /// Function that reacts to the button click and generates the given number of puzzles
        /// </summary>
        /// <param name="numPuzzles"></param>
        public void GeneratePuzzles(int numPuzzles)
        {
            List <SudokuGrid> sudokuPuzzles = new List <SudokuGrid>();
            PuzzleGenerator   gen           = new PuzzleGenerator();

            try
            {
                XDocument doc;
                string    filename = @"Puzzles/SudokuPuzzles.xml";
                int       ID       = 0;
                if (File.Exists(filename))
                {
                    doc = XDocument.Load(filename);
                    XmlDocument xmlDoc = new XmlDocument();
                    xmlDoc.Load(filename);
                    XmlNode types      = xmlDoc.DocumentElement.SelectSingleNode("/SudokuPuzzles");
                    XmlNode notStarted = types.FirstChild;
                    foreach (XmlNode item in notStarted.ChildNodes)
                    {
                        ID += item.ChildNodes.Count;
                    }
                }
                else
                {
                    doc = new XDocument(
                        new XDeclaration("1.0", "utf-8", "yes"),
                        new XComment("Sudoku Puzzle Storage For SudokuSolverSetter App"),
                        new XElement("SudokuPuzzles",
                                     new XElement("NotStarted",
                                                  new XElement("Beginner"),
                                                  new XElement("Moderate"),
                                                  new XElement("Advanced"),
                                                  new XElement("Extreme")
                                                  ),
                                     new XElement("Started",
                                                  new XElement("Beginner"),
                                                  new XElement("Moderate"),
                                                  new XElement("Advanced"),
                                                  new XElement("Extreme")
                                                  ),
                                     new XElement("Completed",
                                                  new XElement("Beginner"),
                                                  new XElement("Moderate"),
                                                  new XElement("Advanced"),
                                                  new XElement("Extreme")
                                                  )
                                     )
                        );
                }
                StreamWriter ratingWrite = new StreamWriter(@"Puzzles/ratings.txt", true);
                StreamWriter difficWrite = new StreamWriter(@"Puzzles/difficulties.txt", true);
                StreamWriter givensWrite = new StreamWriter(@"Puzzles/givens.txt", true);
                StreamWriter IDsWrite    = new StreamWriter(@"Puzzles/IDs.txt", true);
                StreamWriter stepsWrite  = new StreamWriter(@"Puzzles/steps.txt", false);
                #region Strategy Files
                StreamWriter NS = new StreamWriter(@"Puzzles/StratsCounts/nakedsingles.txt", true), HS = new StreamWriter(@"Puzzles/StratsCounts/hiddensingles.txt", true), NP = new StreamWriter(@"Puzzles/StratsCounts/nakedpair.txt", true),
                             HP = new StreamWriter(@"Puzzles/StratsCounts/hiddenpair.txt", true), PP = new StreamWriter(@"Puzzles/StratsCounts/pointline.txt", true), BLR = new StreamWriter(@"Puzzles/StratsCounts/blocklinereduc.txt", true), NT = new StreamWriter(@"Puzzles/StratsCounts/nakedtriple.txt", true),
                             HT = new StreamWriter(@"Puzzles/StratsCounts/hiddentriple.txt", true), XW = new StreamWriter(@"Puzzles/StratsCounts/xwing.txt", true), YW = new StreamWriter(@"Puzzles/StratsCounts/ywing.txt", true), XYZ = new StreamWriter(@"Puzzles/StratsCounts/xyzwing.txt", true),
                             SC = new StreamWriter(@"Puzzles/StratsCounts/singlechains.txt", true), UR1 = new StreamWriter(@"Puzzles/StratsCounts/uniquerecttyp1.txt", true), BT = new StreamWriter(@"Puzzles/StratsCounts/backtrack.txt", true);
                #endregion
                Stopwatch Timer = new Stopwatch();
                Timer.Start();
                for (int i = 0; i < numPuzzles; i++)
                {
                    sudokuPuzzles.Add(gen.Setter());
                    string            puzzleString = gen.GridToString(sudokuPuzzles[i]);
                    PuzzleSolverAdvDS solver       = new PuzzleSolverAdvDS();
                    long rating = GetDifficulty(sudokuPuzzles[i], puzzleString, solver);
                    doc.Element("SudokuPuzzles").Element("NotStarted").Element(sudokuPuzzles[i].Difficulty).Add(
                        new XElement("puzzle",
                                     new XElement("ID", ++ID),
                                     new XElement("DifficultyRating", rating),
                                     new XElement("SudokuString", puzzleString)
                                     )
                        );

                    int givens = 0;
                    for (int x = 0; x < puzzleString.Length; x++)
                    {
                        if (puzzleString[x] != '0')
                        {
                            givens++;
                        }
                    }
                    switch (sudokuPuzzles[i].Difficulty)
                    {
                    case "Beginner":
                        difficWrite.WriteLine("1");
                        break;

                    case "Moderate":
                        difficWrite.WriteLine("2");
                        break;

                    case "Advanced":
                        difficWrite.WriteLine("3");
                        break;

                    default:
                        difficWrite.WriteLine("4");
                        break;
                    }
                    ratingWrite.WriteLine(rating);
                    givensWrite.WriteLine(givens);
                    IDsWrite.WriteLine(ID);
                    stepsWrite.WriteLine(solver.g_StepCounter);

                    NS.WriteLine(solver.g_StrategyCount[1]); HS.WriteLine(solver.g_StrategyCount[2]); NP.WriteLine(solver.g_StrategyCount[3]);
                    HP.WriteLine(solver.g_StrategyCount[4]); PP.WriteLine(solver.g_StrategyCount[5]); BLR.WriteLine(solver.g_StrategyCount[6]);
                    NT.WriteLine(solver.g_StrategyCount[7]); HT.WriteLine(solver.g_StrategyCount[8]); XW.WriteLine(solver.g_StrategyCount[9]);
                    YW.WriteLine(solver.g_StrategyCount[10]); XYZ.WriteLine(solver.g_StrategyCount[11]); SC.WriteLine(solver.g_StrategyCount[12]);
                    UR1.WriteLine(solver.g_StrategyCount[13]); BT.WriteLine(solver.g_StrategyCount[0]);
                }
                Timer.Stop();
                ratingWrite.Close();
                IDsWrite.Close();
                difficWrite.Close();
                givensWrite.Close();
                stepsWrite.Close();
                NS.Close(); HS.Close(); NP.Close(); HP.Close(); PP.Close(); BLR.Close(); NT.Close();
                HT.Close(); XW.Close(); YW.Close(); XYZ.Close(); SC.Close(); UR1.Close(); BT.Close();
                doc.Save(filename);
                MessageBox.Show("Successfully added " + numPuzzles + " puzzles.\r\nThe generator took " + Timer.Elapsed + " to generate and store all of those puzzles.", "Success!");
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error with writing: " + ex);
                throw;
            }
        }