我有一个图表,每个节点有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;
}
但有时,Random不能按预期工作。 “new Random()。Next(4)”继续生成0.因此,它总是第一个子节点被选择,并且一个非常长的重复序列,如node1-&gt; node2-&gt; node1-&gt; node2 ...是生成并最终发生内存不足异常。
有没有办法让Random类正常工作?
答案 0 :(得分:12)
原因是因为Random是根据当前时间初始化的(计算机中没有真正的随机...只有伪随机)。 while循环迭代太快,系统时间没有记录变化。所以你要重新初始化一个以相同值开头的新Random对象。
尝试创建一个在整个方法中重复使用的Random对象:
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;
}
答案 1 :(得分:5)
初始化外部循环的随机实例,例如:
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;
}
答案 2 :(得分:0)
您提到在多个线程中调用该方法。一个解决方案是每个线程有一个随机数generartor,由静态rng播种。
我还删除了常量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;
}
答案 3 :(得分:0)
这里有一些对你不利的事情。第一个是你每次要求一个时都期望一个不同的数字,但这不是这个类所做的,也不是随机的定义。所以,这个类实际上正常工作。
现在,本课程尽力为每个选项提供平等的选择机会。因此,当您想到随机时,请确保您将该术语的定义置于上下文中。但是,请记住,此类不会像人类一样工作。
现在,为了解决你经常得到零的事实,这有两个原因。首先,您将在每次迭代中创建一个new
Random类。但更重要的是,你的范围太小,因为你期望它每次只在4个选项范围内给你一个不同的数字,并且因为它是伪随机的,就像MSDN表明你得到了经常回答同样的问题。
我意识到你只给它4个选项的原因,但我认为你可能需要重新考虑你正在寻找的功能类型,因为它可能会减少挫折感。
答案 4 :(得分:0)
这是一篇关于C#中随机数的非常有趣的文章,问题与Stackoverflow上的问题完全相同:)