生成新的数独网格c#

本文关键字:网格 | 更新日期: 2023-09-27 18:16:51

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

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

6。如果NO ->重新生成拼图(转到1.)

6 b。如果是->拼图生成(显示它)

"新游戏"按钮的使用代码:

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

其余的函数和代码我不认为是必要的,因为其他一切工作。如果我导入一个空的或部分的拼图,应用程序可以使用解决自动生成网格的相同方法自动解决它。但是当我从菜单中点击"New puzzle"时,应用程序卡住了,没有任何错误(所以我不得不终止该进程)。

也许这不是最简单的方法来生成一个有效的板,我为代码的长度道歉,但我真的需要修复和使用这个。我试着自己解决这个问题,很多次,但在过去的两个月里,我没有解决办法(只是我在这件事上的无能造成了很多挫折)……所以我将感谢任何我能从这里得到的帮助。

生成新的数独网格c#

问题解决了!

上面的代码实际上没有问题,我的问题是我在"SolvePuzzleByBruteForce()"函数中有一些编码错误。有问题的函数没有在这里发布,所以上面的代码不需要更正,它正常工作。

如果有人想,我可以把"SolvePuzzleByBruteForce()",但我发现它无关紧要,因为它没有什么特别的,而且互联网上到处都是这样的功能。

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

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

@Wilson谢谢你的意见,它帮助我找到并找出了不良功能中的问题