本来想自己写个创建+解题的数独流程,但是…写着写着发现创建和解题就是直接连贯的…
所以干脆搞个81步创建数独的流程算了;
主要关键点
1.随机数
现在的版本而言,无论是java还是C#的random出来的随机数都不是平均分布,所以要随机的基础上取随机数;
2.排除3×3九宫格中有相同数字
这里可以直接
x和y不同的值域(1~ 3、4 ~ 6、7 ~ 9)组合出9个3×3的宫格然后对比坐标的值去排查,也可以像下面代码那样利用数理去分区排查;
PS.解特定题目用的位置主要用来解题,把固定的坐标点及对应值输入即可~
Dictionary<Point, int> pointsDic_0 = new Dictionary<Point, int>
{
// 解特定题目用,只想随机生成一个标准数独就直接注释即可
{ new Point(1, 1), 0 },{ new Point(1, 2), 0 },{ new Point(1, 3), 0 },{ new Point(1, 4), 0 },{ new Point(1, 5), 0 },{ new Point(1, 6), 0 },{ new Point(1, 7), 0 },{ new Point(1, 8), 0 },{ new Point(1, 9), 0 },
{ new Point(2, 1), 0 },{ new Point(2, 2), 0 },{ new Point(2, 3), 0 },{ new Point(2, 4), 0 },{ new Point(2, 5), 0 },{ new Point(2, 6), 0 },{ new Point(2, 7), 0 },{ new Point(2, 8), 0 },{ new Point(2, 9), 0 },
{ new Point(3, 1), 0 },{ new Point(3, 2), 0 },{ new Point(3, 3), 0 },{ new Point(3, 4), 0 },{ new Point(3, 5), 0 },{ new Point(3, 6), 0 },{ new Point(3, 7), 0 },{ new Point(3, 8), 0 },{ new Point(3, 9), 0 },
{ new Point(4, 1), 0 },{ new Point(4, 2), 0 },{ new Point(4, 3), 0 },{ new Point(4, 4), 6 },{ new Point(4, 5), 0 },{ new Point(4, 6), 0 },{ new Point(4, 7), 0 },{ new Point(4, 8), 0 },{ new Point(4, 9), 0 },
{ new Point(5, 1), 0 },{ new Point(5, 2), 0 },{ new Point(5, 3), 0 },{ new Point(5, 4), 0 },{ new Point(5, 5), 0 },{ new Point(5, 6), 0 },{ new Point(5, 7), 0 },{ new Point(5, 8), 0 },{ new Point(5, 9), 0 },
{ new Point(6, 1), 0 },{ new Point(6, 2), 0 },{ new Point(6, 3), 0 },{ new Point(6, 4), 0 },{ new Point(6, 5), 0 },{ new Point(6, 6), 0 },{ new Point(6, 7), 0 },{ new Point(6, 8), 0 },{ new Point(6, 9), 0 },
{ new Point(7, 1), 0 },{ new Point(7, 2), 0 },{ new Point(7, 3), 0 },{ new Point(7, 4), 0 },{ new Point(7, 5), 0 },{ new Point(7, 6), 0 },{ new Point(7, 7), 0 },{ new Point(7, 8), 0 },{ new Point(7, 9), 0 },
{ new Point(8, 1), 0 },{ new Point(8, 2), 0 },{ new Point(8, 3), 0 },{ new Point(8, 4), 0 },{ new Point(8, 5), 0 },{ new Point(8, 6), 0 },{ new Point(8, 7), 0 },{ new Point(8, 8), 0 },{ new Point(8, 9), 0 },
{ new Point(9, 1), 0 },{ new Point(9, 2), 0 },{ new Point(9, 3), 0 },{ new Point(9, 4), 0 },{ new Point(9, 5), 0 },{ new Point(9, 6), 0 },{ new Point(9, 7), 0 },{ new Point(9, 8), 0 },{ new Point(9, 9), 0 },
};
string numbers = "" +
"1 0 0 0 0 0 0 0 0 " +
"2 0 0 0 0 0 0 0 0 " +
"3 0 0 0 0 0 0 0 0 " +
"4 0 0 0 0 0 0 0 0 " +
"5 0 0 0 0 0 0 0 0 " +
"6 0 0 0 0 0 0 0 0 " +
"7 0 0 0 0 0 0 0 0 " +
"8 0 0 0 0 0 0 0 0 " +
"9 0 0 0 0 0 0 0 0 " +
"";
string[] nums = numbers.Split();
for (int i = 0; i < nums.Length; i++)
if (int.TryParse(nums[i], out int num))
pointsDic_0[ pointsDic_0.Keys.ToList()[i]] = num;
List<Point> keys = new List<Point>(pointsDic_0.Keys);
foreach (var key in keys)
if (pointsDic_0[key] == 0)
pointsDic_0.Remove(key);
Dictionary<Point, int> pointsDic = new Dictionary<Point, int>(pointsDic_0);// 结果3维数组
Random random = new Random();
int buildFailTime = 0;// 构建失败次数
for (int i = 1; i < 10; i++)
for (int j = 1; j < 10; j++)
{
Point point = new Point(i, j);
if (pointsDic.ContainsKey(point))
continue;// 解谜用
int randomInt = random.Next(1, 1000) % 9 + 1;// 由于random.Next的随机数不够平均分布,所以用取余方式让其趋向平均分布
int testTime = 0;
do
{
randomInt++;
testTime++;
if (randomInt > 9)
randomInt = 1;
}
while (testTime < 10 && pointsDic.Any((point_int) =>// 9次之内是否有不存在横竖或者3×3宫格重复的数(这里只讨论【标准数独】玩法),存在则找其他数
{
Point key = point_int.Key;
int x = key.X;
int y = key.Y;
if (x == i || y == j // 同一横竖轴
|| ((i - 1) / 3 == (x - 1) / 3 && (j - 1) / 3 == (y - 1) / 3))// 同一3×3宫格
return randomInt == point_int.Value;
return false;
}));
if (testTime == 10)// 重新再构建
{
i = 1;
j = 0;
pointsDic.Clear();
pointsDic = new Dictionary<Point, int>(pointsDic_0);
buildFailTime++;
}
else
pointsDic.Add(point, randomInt);
}
Console.WriteLine(" buildFailTime:" + buildFailTime);
for (int i = 1; i < 10; i++)
{
Console.Write(" ");
if ((i - 1) % 3 == 0 && i != 1)
{
for (int j = 0; j < 16; j++)
Console.Write("—");
Console.Write("\n ");
}
for (int j = 1; j < 10; j++)
{
if ((j - 1) % 3 == 0 && j != 1)
Console.Write("| ");
Console.Write(pointsDic[new Point(i, j)] + " ");
}
Console.WriteLine();
}
Console.ReadKey();