上一篇讲了怎么构造数独,这一节讲怎么对一个被挖掉一些格子的数独矩阵(如以下矩阵)进行求解,用的是回溯法。
(1)用程序求解:构造数独矩阵,随机挖掉一些空格的时候,要记录下这些空格的坐标,我们在Table类中用一个链表储存这些坐标。因为储存的这些坐标是随机产生的,所以求解之前最后排下序(排序时可以将Coord坐标类实现IComparable接口,将坐标按X,Y进行二级排序),这样回溯起来效率会快很多。依次取出链表中的坐标,往坐标的格子依次填入1~9,然后分别在行、列、3*3的小表格中检验,如果通过则继续取链表中下一个坐标,再重复一下过程,如果不能通过则回溯。
核心代码:
public void GenerateSolutionMatrix(int finishNumber) { if (finishNumber == emptyCellList.Count) { isFinished = true; return; } Coord currentCoord = new Coord(); currentCoord.X = emptyCellList[finishNumber].X; currentCoord.Y = emptyCellList[finishNumber].Y; int row = (currentCoord.X / 3) * 3 + 2; int column = (currentCoord.Y / 3) * 3 + 2; //这个要注意啊,因为产生的随机数可能一样,即一个表格被挖空了几次 //如果对一个已处理的表格重复处理会出错 if (table[currentCoord.X, currentCoord.Y].IsProcessed) GenerateSolutionMatrix(finishNumber+1); else for (int i = 1; i <= TableSize; i++) { if (!isFinished && ValidLine(i, currentCoord.X, TableSize) && ValidColumn(i, TableSize, currentCoord.Y) && ValidSmallTable(i, row, column)) { //填表 table[currentCoord.X, currentCoord.Y].Number = i; table[currentCoord.X, currentCoord.Y].IsProcessed = true; GenerateSolutionMatrix(finishNumber + 1); table[currentCoord.X, currentCoord.Y].IsProcessed = false; //回溯 } } }
(2)验证用户的解答是否正确,这里我把用户填入的数字放到一个数组里面,然后再验证
(注意数组里面的数字是按X坐标从小到大(相等则按Y坐标从小到大)排列的,顺序不能乱,当然在这之前储存被挖掉的格子坐标的链表emptyCellList要先排序
这样才能与用户输入的数字一一对应)
/// <summary> /// 检验解答是否正确 /// </summary> /// <param name="solution">输入的数字序列</param> /// <returns></returns> public bool ValidateSolution(IEnumerable<int> solution) { if (solution.Count() != emptyCellList.Count()) return false; int currentIndex = 0; int row, column; foreach (int number in solution) { row = (emptyCellList[currentIndex].X / 3) * 3 + 2; column = (emptyCellList[currentIndex].Y / 3) * 3 + 2; if (ValidLine(number, emptyCellList[currentIndex].X, TableSize) && ValidColumn(number, TableSize, emptyCellList[currentIndex].Y) && ValidSmallTable(number, row, column)) { table[emptyCellList[currentIndex].X, emptyCellList[currentIndex].Y].Number = number; //table[emptyCellList[currentIndex].X, // emptyCellList[currentIndex].Y].IsProcessed = true; } else return false; currentIndex++; } return true; }
(3)测试:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace sudoku { class Program { static void Main(string[] args) { Table table = new Table(); int level = 6; //难度为6级 table.GenerateValidMatrix(); Console.WriteLine("Here is the Matrix"); table.PrintTable(); Console.WriteLine("\nHere is the problem Matrix"); table.GenerateProblemMatrix(level); table.PrintTable(); Console.WriteLine("\nHere is the solution Matrix"); table.GenerateSolutionMatrix(0); table.PrintTable(); Console.ReadKey(); } } }
结果:
关于界面——好吧,原来自己是想把数字放到datagridview里面的,可是发现界面好丑,而且还要控制好每一个格子的颜色(这个暂时还没做控制好)
所以界面巨丑陋……对界面有好建议的朋友欢迎提出建议,当然也可对我的实现方法、代码等等提建议……
本文为原创博文,转载请注明作者博客地址:http://www.cnblogs.com/-Lei/