C#Random不像Random那样工作

C#Random不像Random那样工作,c#,.net,random,C#,.net,Random,我有一个图,每个节点有4个子节点。我编写了一个算法来生成从开始节点到结束节点的随机路径。在每个节点上,它随机选择下一个节点。可以重新访问已访问的节点 代码如下所示: public List<Node> GetPath(Node begin, Node end) { var nodes = new List<Node>(); var node = begin; while (node != end) { nodes.Add(n

我有一个图,每个节点有4个子节点。我编写了一个算法来生成从开始节点到结束节点的随机路径。在每个节点上,它随机选择下一个节点。可以重新访问已访问的节点

代码如下所示:

public List<Node> GetPath(Node begin, Node end)
{
    var nodes = new List<Node>();
    var node = begin;
    while (node != end)
    {
        nodes.Add(node);
        var next = node.Children[new Random().Next(4)];
        node = next;
    }

    nodes.Add(end);

    return nodes;
}
public List GetPath(节点开始,节点结束)
{
var节点=新列表();
var节点=开始;
while(节点!=结束)
{
nodes.Add(node);
var next=node.Children[new Random().next(4)];
节点=下一个;
}
节点。添加(结束);
返回节点;
}
但有时,随机性并不像预期的那样起作用。“new Random().Next(4)”继续生成0。所以它总是第一个子节点被选中,并且有一个很长的重复序列,比如node1->node2->node1->node2。。。生成,并最终发生内存不足异常


有没有办法使Random类正常工作?

在循环外初始化Random实例,例如:

public List<Node> GetPath(Node begin, Node end)
{
    var nodes = new List<Node>();
    var node = begin;

    var random = new Random();

    while (node != end)
    {
        nodes.Add(node);
        var next = node.Children[random.Next(4)];
        node = next;
    }

    nodes.Add(end);

    return nodes;
}
public List GetPath(节点开始,节点结束)
{
var节点=新列表();
var节点=开始;
var random=新的random();
while(节点!=结束)
{
nodes.Add(node);
var next=node.Children[random.next(4)];
节点=下一个;
}
节点。添加(结束);
返回节点;
}

原因是Random是基于当前时间初始化的(计算机中没有真正的Random…只有psuedo Random)。while循环迭代过快,并且系统时间未记录更改。因此,您正在初始化一个新的随机对象,该对象以相同的值开始

尝试创建一个在整个方法中重复使用的随机对象:

public List<Node> GetPath(Node begin, Node end)
{
    var nodes = new List<Node>();
    var node = begin;

    Random r = new Random();
    while (node != end)
    {
        nodes.Add(node);
        var next = node.Children[r.Next(4)];
        node = next;
    }

    nodes.Add(end);

    return nodes;
}
public List GetPath(节点开始,节点结束)
{
var节点=新列表();
var节点=开始;
随机r=新随机();
while(节点!=结束)
{
nodes.Add(node);
var next=node.Children[r.next(4)];
节点=下一个;
}
节点。添加(结束);
返回节点;
}

您提到在多个线程中调用该方法。一种解决方案是,静态rng为每个线程播种一个随机数Generator

我还删除了常量4,并将其更改为
node.Children.Count

static Random seed = new Random();
[ThreadLocal] static Random rng;

public List<Node> GetPath(Node begin, Node end)
{
var nodes = new List<Node>();
var node = begin;

if (rng == null)
   rng = new Random(seed.Next());

while (node != end)
{
    nodes.Add(node);
    var next = node.Children[rng.Next(node.Children.Count)];
    node = next;
}

nodes.Add(end);

return nodes;
}
static Random seed=new Random();
[ThreadLocal]静态随机rng;
公共列表GetPath(节点开始,节点结束)
{
var节点=新列表();
var节点=开始;
如果(rng==null)
rng=新随机(seed.Next());
while(节点!=结束)
{
nodes.Add(node);
var next=node.Children[rng.next(node.Children.Count)];
节点=下一个;
}
节点。添加(结束);
返回节点;
}

这里有一些事情对你不利。首先,每次你要求一个数字时,你都会期望一个不同的数字,但这不是这个类所做的,也不是随机数的定义。所以,这个类实际上工作正常

随机变量的定义
  • 未经方法或有意识的决定而做出、完成、发生或选择的:“100户随机抽样”
  • 由每个项目的平等机会决定的,或涉及每个项目的平等机会的
  • 现在,这门课在给每个选项一个被选择的平等机会方面做得最好。所以,当你想到“随机”这个词时,一定要把它的定义放在上下文中。但是,请记住,这门课不像人脑那样工作

    现在,为了解决你经常得到零的事实,它的发生有两个原因。首先,在每次迭代中创建一个
    新的
    随机类。但更重要的是,你的范围太小了,因为你希望它在只有4个选项的范围内每次给你一个不同的数字,而且因为它是伪随机的,就像你经常得到相同的答案一样


    我知道你只给它4个选项的原因,但我认为你可能需要重新考虑你正在寻找的功能类型,因为这可能会减少挫折感。

    谢谢。这确实解决了问题。但我还有一个问题。实际上,我在多线程中调用这个方法来生成一组路径。如果在循环外使用随机变量。将生成许多相同的路径。我认为这是因为同样的原因,为什么在循环中使用new Random会生成很长的序列。@Ryan:如果在循环中多次调用此函数,那么每个线程只需使用一个
    Random
    ,最好基于全局共享
    Random
    的种子进行初始化(注意:
    Random
    不是线程安全的,因此需要在共享的
    Random
    周围锁定)。可能存在重复的