我正在尝试使用 Visual Studio 2008 制作一个解决数独难题的 C# 应用程序。我的问题是我似乎无法计算应用程序生成新谜题的代码。我试图实现的想法如下:
- 从一个空的谜题开始
- 为拼图中的所有单元格生成数字
- 根据所需的难度级别清空适当数量的单元格
- 解决难题
- 拼图的分数是否在所需难度级别的可接受范围内?
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++;
}
}
}
} }
其余的功能和代码我认为没有必要,因为其他一切都有效。如果我导入一个空的或部分拼图,应用程序可以使用与解决自动生成的网格相同的方法自动解决它。但是当我从菜单中单击“新拼图”时,应用程序会卡住而没有错误(所以我必须终止该进程)。
也许这不是生成有效板的最简单方法,我为代码的长度道歉,但我真的需要修复和使用这个。我试图自己解决这个问题,很多次,但在过去的两个月里,我没有找到任何解决方案(只是因为我在这件事上的无能而感到沮丧)......所以我会很感激我能从这里得到的任何帮助。