我正在尝试为那些不知道它是什么的人创建一个数独游戏。你有一个 9x9 的盒子,需要用 1-9 的数字填充,每个数字在它的行和列中都必须是唯一的,并且在找到它的 3x3 盒子中也是如此。我最终在二维数组中进行了大量循环。
但在某个点它只是停止,没有任何异常(exception),只是突然爆发,什么也没有发生,而且它并不总是在同一个位置,但总是超过一半。
我至少期待堆栈溢出异常。
这是我的代码:
public class Engine
{
public int[,] Create()
{
int[,] outer = new int[9, 9];
for (int i = 0; i < 9; i++)
{
for (int j = 0; j < 9; j++)
{
outer[i, j] = GetRandom(GetUsed(outer, i, j));
}
}
return outer;
}
List<int> GetUsed(int[,] arr, int x, int y)
{
List<int> usedNums = new List<int>();
for (int i = 0; i < 9; i++)
{
if (arr[x, i] != 0 && i != y)
{
if(!usedNums.Contains(arr[x, i]))
usedNums.Add(arr[x, i]);
}
}
for (int i = 0; i < 9; i++)
{
if (arr[i, y] != 0 && i != x)
{
if (!usedNums.Contains(arr[i, y]))
usedNums.Add(arr[i, y]);
}
}
int x2 = 9 - (x + 1);
int y2 = 9 - (y + 1);
if (x2 <= 3)
x2 = 2;
else if (x2 > 3 && x2 <= 6)
x2 = 5;
else x2 = 8;
if (y2 <= 3)
y2 = 2;
else if (y2 > 3 && y2 <= 6)
y2 = 5;
else y2 = 8;
for (int i = x2 - 2; i < x2; i++)
{
for (int j = y2 - 2; j < y2; j++)
{
if (arr[i, j] != 0 && i != x && j != y)
{
if (!usedNums.Contains(arr[i, j]))
usedNums.Add(arr[i, j]);
}
}
}
return usedNums;
}
int GetRandom(List<int> numbers)
{
Random r;
int newNum;
do
{
r = new Random();
newNum = r.Next(1, 10);
} while (numbers.Contains(newNum));
return newNum;
}
}
最佳答案
这不是爆发,而是陷入了无限循环。
如果我没看错,您似乎正在尝试创建一个数独游戏板。问题是,它并不像你想象的那么简单。据我所知,您只是在通过它填充随机未使用的值;问题是,并不是每一个这样的配置都是有效的——大多数时候你的随机输入最终会让你进入一个无法解决的电路板配置。
然后,当您尝试为某个正方形选择一个随机值时,内部 GetRandom
函数将无限循环尝试选择一个数字(因为 getUsed
已经有了所有 1 - 9
,do..while
永远不会退出)。
自己查看的简单方法:将其添加到 GetRandom
函数的顶部:
if (Enumerable.Range(1, 9).All(i => numbers.Contains(i)))
Console.WriteLine("PROBLEM!");
现在,如果 numbers
包含 1 到 9 的全部,它会告诉您。 (然后仍然陷入无限循环,但这就是你现在的问题;))
此外,作为旁注,像这样继续创建 new Random()
对象并不是一个好习惯;最好只有一个 Random
实例,在您的构造函数中对其进行初始化,然后继续使用 Random.Next
。至少,在函数的顶部有 Random r = new Random()
,然后在循环内有 r.Next
。
好的,这是一个非常简单的进入无法解决的位置的例子,就在前两行:
123|456|789
456|123|X
没有有效数字可放入标记为 X
的位置 - 看看这是怎么回事?
用随机未使用的数字填充网格与用“答案”填充它不同 - 可以这样想,如果你玩一个普通的数独游戏并试图通过随机输入来解决它每个空白方 block 中满足规则的数字 - 你很快就会卡住,对吧?这正是您的程序正在发生的事情。
我建议您首先尝试编写一个数独求解器,它采用有效的初始板配置并尝试解决它 - 然后您可以继续尝试自己制作板。
关于c# - 嵌套循环意外中断,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2839805/