生成新的Sudoku网格C#

时间:2013-06-04 22:21:14

标签: c# puzzle sudoku

我正在尝试使用Visual Studio 2008创建一个C#应用程序,它解决了Sudoku难题。 我的问题是我似乎无法想象应用程序生成新拼图的代码。我想要实现的想法如下:

  1. 从空谜题开始
  2. 为拼图中的所有单元格生成数字
  3. 根据所需的难易程度清空适当数量的单元格
  4. 解决难题
  5. 谜题的分数是否在所需的难度范围内?
  6. 6a上。如果否 - >重新生成谜题(转到1.)

    6b中。如果是 - >益智生成(显示)

    “新游戏”按钮使用的代码:

        //--------------------------------------------------
        // Starting a new game menu button
        //--------------------------------------------------
        public void NewToolStripMenuItem_Click(System.Object sender, System.EventArgs e)
        {
    
            if (GameStarted) // this cheking part seems to work (message is displayed and game gets saved if selected)
            {
                MsgBoxResult response = (MsgBoxResult)(MessageBox.Show("Doriți salvarea jocului curent?", "Salvează jocul curent...", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question));
    
                if (response == MsgBoxResult.Yes)
                {
                    SaveGameToDisk(false);
                }
                else if (response == MsgBoxResult.Cancel)
                {
                    return;
                }
            }
    
            // Changing the cursor while generating
            System.Windows.Forms.Cursor.Current = Cursors.WaitCursor;
            ToolStripStatusLabel1.Text = "Se generează un puzzle nou...";
    
            // Creating an instance for the SudokuPuzzle class
            SudokuPuzzle sp = new SudokuPuzzle();
            string puzzle = string.Empty;
    
            // Determining the difficulty level selected (from menu objects)
            if (EasyToolStripMenuItem.Checked)
            {
                puzzle = sp.GetPuzzle(1);
            }
            else if (MediumToolStripMenuItem.Checked)
            {
                puzzle = sp.GetPuzzle(2);
            }
            else if (DifficultToolStripMenuItem.Checked)
            {
                puzzle = sp.GetPuzzle(3);
            }
            else if (ExtremelyDifficultToolStripMenuItem.Checked)
            {
                puzzle = sp.GetPuzzle(4);
            }
            else if (EmptyPuzzleToolStripMenuItem.Checked)
            {
                puzzle = sp.GetPuzzle(5);
            }
    
            // Changing to default cursor
            System.Windows.Forms.Cursor.Current = Cursors.Default;
    
            StartNewGame();
    
            // Initialisation of the grid
            int counter = 0;
            for (int row = 1; row <= 9; row++)
            {
                for (int col = 1; col <= 9; col++)
                {
                    if (puzzle[counter].ToString() != "0")
                    {
                        SetCell(col, row, System.Convert.ToInt32(puzzle[counter].ToString()), (short)0);
                    }
                    counter++;
                }
            }
        }
    

    所以下一个函数的代码叫做GetPuzzle(1):

        //--------------------------------------------------
        // Obtaining a new puzzle (of the required level)
        //--------------------------------------------------
        public string GetPuzzle(int level)
        {
            int score = 0;
            string result;
            do
            {
                result = GenerateNewPuzzle(level, ref score);
                if (result != string.Empty)
                {
                    // Verify if the generated puzzle is of the selected dificulty
                    switch (level)
                    {
                        // The average for dificutly 1
                        case 1:
                            if (score >= 42 && score <= 46)
                            {
                                goto endOfDoLoop;
                            }
                            break;
                        // The average for dificutly 2
                        case 2:
                            if (score >= 49 && score <= 53)
                            {
                                goto endOfDoLoop;
                            }
                            break;
                        // The average for dificutly 3                                   case 3:
                            if (score >= 56 && score <= 60)
                            {
                                goto endOfDoLoop;
                            }
                            break;
                        // The average for dificutly 4
                        case 4:
                            if (score >= 112 && score <= 116)
                            {
                                goto endOfDoLoop;
                            }
                            break;
                    }
                }
            } while (!false); // loops ending 
        endOfDoLoop:
            return result;
        }
    

    使用的下一个函数是GenerateNewPuzzle():

        //--------------------------------------------------
        // Generating a new puzzle
        //--------------------------------------------------
        public string GenerateNewPuzzle(int level, ref int score)
        {
            int c;
            int r;
            string str;
            int numberofemptycells = 0;
    
            // Initializing the entire grid
            for (r = 1; r <= 9; r++)
            {
                for (c = 1; c <= 9; c++)
                {
                    actual[c, r] = 0;
                    possible[c, r] = string.Empty;
                }
            }
    
            // Empty the stacks used
            ActualStack.Clear();
            PossibleStack.Clear();
    
            // Complete by solving an empty grid
            try
            {
                // First used logical methods to solve the grid
                if (!SolvePuzzle())
                {
                    // Then use brute force
                    SolvePuzzleByBruteForce();
                }
            }
            catch (Exception)
            {
                // If there’s any error, return emptry string
                return string.Empty;
            }
    
            // Create a copy for the actual array
            actual_backup = (int[,])(actual.Clone());
    
            // Set the number of empty cells based on the difficulty  level
            switch (level)
            {
                // For difficulty level 1
                case 1:
                    numberofemptycells = RandomNumber(40, 45);
                    break;
                // For difficulty level 2
                case 2:
                    numberofemptycells = RandomNumber(46, 49);
                    break;
                // For difficulty level 3
                case 3:
                    numberofemptycells = RandomNumber(50, 53);
                    break;
                // For difficulty level 4
                case 4:
                    numberofemptycells = RandomNumber(54, 58);
                    break;
            }
    
            // Empty the stacks used by brute force
            ActualStack.Clear();
            PossibleStack.Clear();
            BruteForceStop = false;
    
            // Create empty cells
            CreateEmptyCells(numberofemptycells);
    
            // Convert the values from the actual array to string
            str = string.Empty;
            for (r = 1; r <= 9; r++)
            {
                for (c = 1; c <= 9; c++)
                {
                    str += (string)(actual[c, r].ToString());
                }
            }
    
            // Verrify that the puzzle has only one solution
            int tries = 0;
            do
            {
                totalscore = 0;
                try
                {
                    if (!SolvePuzzle())
                    {
                        // If puzzle is not solved and difficulty level is 1-3
                        if (level < 4)
                        {
                            // Choose another combination of cells to empty
                            VacateAnotherPairOfCells(ref str);
                            tries++;
                        }
                        else
                        {
                            // Puzzles of difficulty 4 don’t guranty a single solution
                            SolvePuzzleByBruteForce();
                            goto endOfDoLoop;
                        }
                    }
                    else
                    {
                        // The puzzle has 1 solution
                        goto endOfDoLoop;
                    }
                }
                catch (Exception)
                {
                    return string.Empty;
                }
    
                // If too many tries are executed, exit at 50
                if (tries > 50)
                {
                    return string.Empty;
                }
            }
            while (true);
        endOfDoLoop:
    
            // Return the obtained score and the puzzle as a string
            score = totalscore;
            return str;
        }
    

    最后一个有用的(我认为)函数,VacateAnotherPairOfCells():

        //--------------------------------------------------
        // Empty another pair of cells
        //--------------------------------------------------
        private void VacateAnotherPairOfCells(ref string str)
        {
            int c;
            int r;
    
            // Search for a pair of cells to empty (the empty cells should be simetrical from the center of the grid)
            do
            {
                c = RandomNumber(1, 9);
                r = RandomNumber(1, 9);
            } while (!(int.Parse(str[(c - 1) + (r - 1) * 9].ToString()) == 0));
    
            // Restore the value of the cell from the backup array
            str = str.Remove(System.Convert.ToInt32((c - 1) + (r - 1) * 9), 1);
            str = str.Insert(System.Convert.ToInt32((c - 1) + (r - 1) * 9), (string)(actual_backup[c, r].ToString()));
    
            // Restore the value of the simetrical cell
            str = str.Remove(System.Convert.ToInt32((10 - c - 1) + (10 - r - 1) * 9), 1);
            str = str.Insert(System.Convert.ToInt32((10 - c - 1) + (10 - r - 1) * 9), (string)(actual_backup[10 - c, 10 - r].ToString()));
    
            // Search for another pair of cells that can be emptyed
            do
            {
                c = RandomNumber(1, 9);
                r = RandomNumber(1, 9);
            } while (!(int.Parse(str[(c - 1) + (r - 1) * 9].ToString()) != 0));
    
            // Delete the cell from the string
            str = str.Remove(System.Convert.ToInt32((c - 1) + (r - 1) * 9), 1);
            str = str.Insert(System.Convert.ToInt32((c - 1) + (r - 1) * 9), "0");
    
            // Delete the simetrical cell from the string
            str = str.Remove(System.Convert.ToInt32((10 - c - 1) + (10 - r - 1) * 9), 1);
            str = str.Insert(System.Convert.ToInt32((10 - c - 1) + (10 - r - 1) * 9), "0");
    
            // Reinitilisation of the grid
            short counter = (short)0;
            for (int row = 1; row <= 9; row++)
            {
                for (int col = 1; col <= 9; col++)
                {
                    if (System.Convert.ToInt32(str[counter].ToString()) != 0)
                    {
                        actual[col, row] = System.Convert.ToInt32(str[counter].ToString());
                        possible[col, row] = (string)(str[counter].ToString());
                    }
                    else
                    {
                        actual[col, row] = 0;
                        possible[col, row] = string.Empty;
                    }
                    counter++;
                }
            }
        }
    } }
    

    其他功能和代码我认为没有必要,因为其他一切都有效。如果我导入一个空的或部分拼图,应用程序可以使用与解决自动生成的网格相同的方法自动解决它。但是,当我从菜单中单击“新建拼图”时,应用程序卡住了没有错误(所以我必须终止该过程)。

    也许这不是生成有效板的最简单方法,我为代码的长度道歉,但我真的需要修复并使用这个。我曾多次尝试解决这个问题,但在过去的两个月里我没有解决办法(只是因为我在这件事上的无能而感到非常沮丧)......所以我很感激能从这里得到任何帮助。

1 个答案:

答案 0 :(得分:0)

问题解决了!

上面的代码实际上没有问题,我的问题是我在“SolvePuzzleByBruteForce()”函数中遇到了一些编码错误。有问题的功能未在此处发布,因此上述代码无需更正,并且功能正常。

如果有人愿意的话,我可以把“SolvePuzzleByBruteForce()”放进去,但我觉得它无关紧要,因为它没什么特别的,互联网上到处都充满了这些功能。

回复评论: @HighCore使用goto与我的问题无关。

@Mark Lakata这个问题并不含糊。我说了问题,它需要做的事情,以及使用的代码。这不是家庭作业问题,因为我不在学校,也不会尝试2个月做作业。

@Wilson感谢您的评论,它帮助我追查并找出了不良功能中的问题。