C# 数独求解算法中的随机性

C# 数独求解算法中的随机性,c#,random,backtracking,sudoku,C#,Random,Backtracking,Sudoku,我正在使用这个回溯索杜库解决算法,这是非常好和有效的 private void solve() { for (var y = 8; y >= 0; y--) { for (var x = 8; x >= 0; x--) { var a = grid[y, x]; if (a == 0) {

我正在使用这个回溯索杜库解决算法,这是非常好和有效的

    private void solve()
    {
        for (var y = 8; y >= 0; y--)
        {
            for (var x = 8; x >= 0; x--)
            {
                var a = grid[y, x];
                if (a == 0)
                {
                    for (var n = 1; n <= 9; n++)
                    {
                        if (possible(y, x, n))
                        {
                            grid[y, x] = n;
                            solve();
                            grid[y, x] = 0;
                        }
                    }
                    return;
                }
            }
        }
        print();
    }
private void solve()
{
对于(变量y=8;y>=0;y--)
{
对于(变量x=8;x>=0;x--)
{
var a=网格[y,x];
如果(a==0)
{
对于(var n=1;n
公共静态类MyRandomGenerator)
{
私有静态随机=新随机();
公共静态int[]生成(int inclusiveMinValue、int exclusiveMaxValue)
{
if(exclusiveMaxValue
公共静态类MyRandomGenerator
{
私有静态随机=新随机();
公共静态int[]生成(int inclusiveMinValue、int exclusiveMaxValue)
{


如果(exclusiveMaxValue)您尝试过什么吗?有什么想法吗,但不确定如何实现它?创建一个数组或9个数字的集合,使用Fisher-Yates shuffle对集合进行洗牌,然后在集合中循环,以随机顺序从中选取数字。@Kevin使用随机数很容易获得随机数。Next()函数。给我带来最大麻烦的是没有重复。为此,我尝试了一个哈希集,以及一些我在互联网上找到的其他想法,比如有一个数字1到9的列表,并在使用时将其删除。这些都不起作用,@LasseV.Karlsen,我会查找它,谢谢这把小提琴:你试过什么吗?有什么办法吗但不知道如何实现它?创建一个包含9个数字的数组或集合,使用Fisher-Yates shuffle对集合进行洗牌,然后在集合中循环,从中选择数字,从而以随机顺序进行。@Kevin使用随机数很容易获得随机数。Next()函数。给我带来最大麻烦的是没有重复。为此,我尝试了一个哈希集,以及一些我在互联网上发现的其他想法,比如有一个数字1到9的列表,并在使用时将其删除。这些都不起作用,@LasseV.Karlsen我会查找它,谢谢这把小提琴:使用shufflin实现这一点要好得多g算法,如Fisher-Yates shuffle。对于这种方法,如果有足够大的数字范围可供选择,则搜索最后一个数字将花费相对较长的时间。此外,HashSet无法保证顺序,甚至可能对随机性产生负面影响。W我的意思是,将数字添加到散列集中的顺序可能不是它们最终的顺序。如果必须调整散列集的大小,它可能会对数字重新排序,并且用于拾取存储桶的散列代码生成可能不够随机。现在,对于数独算法来说,这两种方法都可能有些过分,但我不会使用这是一个通用的“创建随机数列表”implementation.@LasseV.Karlsen另外,这个函数不能生成一些数字的重复值而忽略其他数字吗?我们不希望每个数字都有一个吗?Maradik选择的方法不会生成重复的数字,这就是他使用hashset的原因。hashset如果已经在其中,就会拒绝添加值,这就是为什么循环是while loop。他一直试图添加一个随机值,直到添加足够的值为止,但每个值只会添加一次。在这方面,答案中的代码没有问题。我只是觉得它的性能非常差,但这只是我的看法。@LasseV.Karlsen你是对的,我的解决方案存在性能问题。但它是very简单并解决原始任务。您不应将我的解决方案用于生产系统和高负载系统。最好使用洗牌算法(如Fisher-Yates shuffle)来实现这一点。由于此方法有足够大的数字,它将具有指数运行时间,因为如果有足够大范围的数字可供选择。此外,哈希集无法保证顺序,甚至可能会对随机性产生负面影响。我的意思是,将数字添加到哈希集中的顺序可能不是它们最终的顺序。如果哈希集必须调整大小,它可能会对数字进行重新排序,哈希c用于拾取存储桶的ode生成可能不够随机。现在,对于数独算法来说,这两种方法都可能有点过分,但我不会将其用作一般用途的“创建随机数列表”implementation.@LasseV.Karlsen另外,这个函数不能生成一些数字的重复值而忽略其他数字吗?我们不希望每个数字都有一个吗?Maradik选择的方法不会生成重复的数字,这就是他使用hashset的原因。hashset如果已经在其中,就会拒绝添加值,这就是为什么循环是while loop。他一直试图添加一个随机值,直到添加足够的值为止,但每个值只会添加一次。在这方面,答案中的代码没有问题。我只是觉得它的性能非常差,但这只是我的看法。@LasseV.Karlsen你是对的,我的解决方案存在性能问题。但它是ver您不应该将我的解决方案用于生产和高负载系统。
public static class MyRandomGenerator
{
    private static Random random = new Random();

    public static int[] Generate(int inclusiveMinValue, int exclusiveMaxValue)
    {
        if (exclusiveMaxValue <= inclusiveMinValue)
            throw new ArgumentException(nameof(exclusiveMaxValue));

        var capacity = exclusiveMaxValue - inclusiveMinValue;
        var result = new HashSet<int>(capacity);

        while (result.Count < capacity)
        {
            result.Add(random.Next(inclusiveMinValue, exclusiveMaxValue));
        }

        return result.ToArray();
    }            
}