//生成谜题 public static void GeneratePuzzle(FunctionForm userinterface) { Sudoku Toreturn = new Sudoku(); if (userinterface.CurrentAuto == AutoMode.SemiAuto) { Toreturn.AnswerCountToStop = 1; for (int hintscount = 0; hintscount < userinterface.targethints; hintscount++) { GenerateOneHint(Toreturn, userinterface); userinterface.SetDialogText("数独谜题生成中...(" + (hintscount + 1) + ") /" + "\nSudoku puzzle generating...(" + (hintscount + 1) + ")"); } } else { Toreturn.AnswerCountToStop = 2; int hintscount = 1; while (Toreturn.AnswerCount != 1) { GenerateOneHint(Toreturn, userinterface); userinterface.SetDialogText("数独谜题生成中...(" + hintscount + ") /" + "\nSudoku puzzle generating...(" + hintscount + ")"); hintscount++; } } //触发完成按钮事件 userinterface.ManualDoneButton_Click(userinterface.ManualDoneButton, new EventArgs()); }
//带UI的检查方格合理性 public bool CheckRule(int rowindex, int columnindex, int value, FunctionForm userinterface) { //将不带UI同名方法返回值赋到ToReturn中,获取冲突的行列坐标 bool ToReturn = CheckRule(rowindex, columnindex, value, out int stuckrow, out int stuckcolumn); //存在冲突坐标时在UI上显示冲突详情 if (stuckrow >= 0) { userinterface.SudokuGridLabel[rowindex, columnindex].ForeColor = userinterface.SudokuGridLabel[stuckrow, stuckcolumn].ForeColor = System.Drawing.Color.DarkRed; userinterface.SetDialogText("方格(" + (rowindex + 1) + "," + (columnindex + 1) + ")填入数值" + value + "失败," + "方格(" + (stuckrow + 1) + "," + (stuckcolumn + 1) + ")含有相同值。\n" + "Fill(" + (rowindex + 1) + "," + (columnindex + 1) + ") with value " + value + " failed. " + "Same value found in(" + (stuckrow + 1) + "," + (stuckcolumn + 1) + ")."); } //返回ToReturn return(ToReturn); }
//递归计算答案 private void GetAnswer(int currentrow, int currentcolumn, FunctionForm userinterface) { //坐标超出数独范围则返回上一方格 if (currentrow == -1 || currentcolumn == -1) { return; } //递归次数超时返回 if (triescount >= 20000000 && userinterface.CurrentManual == ManualMode.Generate) { return; } //计算下个和最后可填方格的坐标 FindNextFillable(currentrow, currentcolumn, out int nextrow, out int nextcolumn); FindLastFillable(out int lastrow, out int lastcolumn); for (int tryvalue = 1; tryvalue <= 9; tryvalue++) { triescount++; //跳过非法赋值,尝试下一数值 if (!CheckRule(currentrow, currentcolumn, tryvalue, out int stuckrow, out int stuckcolumn)) { continue; } //记录下合法赋值 GridNumber[currentrow, currentcolumn] = tryvalue; //尝试下一方格 GetAnswer(nextrow, nextcolumn, userinterface); //最后可填方格合法赋值完成即谜题存在答案 //UI显示答案 if (currentrow == lastrow && currentcolumn == lastcolumn) { //答案数自加 AnswerCount++; //记录当前答案 if (userinterface.CurrentManual == ManualMode.Solve) { //在之前撤销过则重新作为最新步骤记录 if (userinterface.solvingrecord.Count > userinterface.solvingstepindex + 1) { userinterface.solvingrecord.RemoveRange(userinterface.solvingstepindex + 1, userinterface.solvingrecord.Count - userinterface.solvingstepindex - 1); userinterface.solvingrecord.TrimExcess(); } //答案写进UI的短整型数组中 userinterface.solvingrecord.Add(new short[9, 9]); for (int rowindex = 0; rowindex < 9; rowindex++) { for (int columnindex = 0; columnindex < 9; columnindex++) { userinterface.solvingarray[rowindex, columnindex] = GridNumber[rowindex, columnindex]; userinterface.solvingrecord[userinterface.solvingstepindex][rowindex, columnindex] = (short)GridNumber[rowindex, columnindex]; } } //步骤计数器自加 userinterface.solvingstepindex++; } //检测指定的答案数是否为-2,是则计算整个谜题所有答案 if (AnswerCountToStop == -2) { //提示目前答案数 userinterface.SetDialogText("计算谜题答案中...(" + AnswerCount + ") /" + "\nAnswers generating...(" + AnswerCount + ")"); //答案数过多时(超过100000),提示答案过多,继续计算会消耗大量系统资源和时间,询问是否继续 if (AnswerCount == 100000) { userinterface.SetAnswerButtonVisibility("WithoutYes"); userinterface.SetDialogText("答案数已超过100000,仍然继续?" + "\nOver 100,000 answers. Still continue?"); //获取目前用户点击按钮 string buttonpress = userinterface.WaitAnswerButtonPressed(); //如果点击“×”按钮则终止目前谜题计算,并返回答案数 if (buttonpress == "No") { AnswerCountToStop = AnswerCount; return; } } continue; } //指定的答案数为-1时,每发现一个新答案询问用户是否继续 else if (AnswerCountToStop == -1) { //UI提示目前有新答案 userinterface.DisplayAnswer(this); //UI询问用户 userinterface.SetAnswerButtonVisibility("WithYes"); userinterface.SetDialogText("有新答案,是否继续?" + "\nNew answer found. Continue?"); //获取目前用户点击按钮 string buttonpressed = userinterface.WaitAnswerButtonPressed(); //如果点击“×”按钮则终止目前谜题计算,并返回答案数 if (buttonpressed == "No") { AnswerCountToStop = AnswerCount; return; } //如果点击“√√”按钮则一直计算到遍历所有可能,不再询问用户 else if (buttonpressed == "Endless") { AnswerCountToStop = -2; continue; } //如果点击“√”按钮则继续计算,发现下一个新答案时仍然询问用户 else { userinterface.SetDialogText("计算谜题答案中...(" + AnswerCount + ") /" + "\nAnswers generating...(" + AnswerCount + ")"); } } //检测答案数是否到达指定的答案数,是则退出返回 else if (AnswerCount == AnswerCountToStop) { return; } } //答案数达到指定答案数直接返回 if (AnswerCount == AnswerCountToStop) { return; } } //尝试完9个数值,此方格不存在数值 //清除此方格数字后返回上一方格 GridNumber[currentrow, currentcolumn] = 0; }