0

我正在尝试使用 Visual Studio 2008 制作一个解决数独难题的 C# 应用程序。我的问题是我似乎无法计算应用程序生成新谜题的代码。我试图实现的想法如下:

  1. 从一个空的谜题开始
  2. 为拼图中的所有单元格生成数字
  3. 根据所需的难度级别清空适当数量的单元格
  4. 解决难题
  5. 拼图的分数是否在所需难度级别的可接受范围内?

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++;
            }
        }
    }
} }

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

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

4

1 回答 1

0

问题解决了!

上面的代码实际上没有问题,我的问题是我在“SolvePuzzleByBruteForce()”函数中出现了一些编码错误。有问题的函数没有在这里发布,所以上面的代码不需要更正,它可以正常运行。

如果有人愿意,我可以输入“SolvePuzzleByBruteForce()”,但我觉得这无关紧要,因为它没什么特别的,而且互联网上到处都是这样的功能。

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

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

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

于 2013-06-05T15:53:06.373 回答