我一直在游戏中使用相同的对象填充我的所有数组,该对象使用此数组来跟踪生成的对象列表。它的代码基本上是:
for(int i = 0; i < wildPets.Length; i++)
{
Pet pet = new Pet();
wildPets[i] = pet;
}
现在当我运行代码时,所有的宠物都是一样的,因为它只是做了一个新的宠物并将它分配给数组的每个索引(同名,id,hp等)。我使用断点功能来检查为什么会发生这种情况,并注意到当我单步执行代码时,对象总是不同的,但是没有断点就会发生错误。我认为断点是一个非常有用的功能,但现在我不知道它是否真正准确地代表了我的代码。我有什么东西在这里失踪。我有可以发布的示例代码
构造
public Pet()
{
Random r = new Random();
type = ToType(r.Next(10));
double temp = (GetHP(type, r));
if (temp > 0)
{
hp5 = temp;
}
temp = (GetSpeed(type, r));
if (temp > 0)
{
speed5 = temp;
}
level = r.Next(5, 16);
rarity = r.Next(100);
rarityLevel = GetRarity();
DisplayImage = frmMain.petImages[petID];
abilities = FillAbilities(type, abilities);
}
它制作了一个具有随机级别,稀有性,ID和其他东西的新宠物。我使用手表部分是视觉工作室。两个图像显示了在后台运行的方法以及数组中包含的内容,以及当我设置断点并逐行逐步执行时。一个人有一个充满宠物的阵列,ID相同(同样的一切,ID只是一个快速的注释方式),另一个有一个充满新的不同宠物对象的数组,就像代码应该如何运行一样。
答案 0 :(得分:1)
原因是每次调用时都会在构造函数中创建一个新的Random
对象。 Random()
构造函数使用当前系统时间生成新的随机种子。当您逐步调试调试器中的代码时,每次连续调用之间会有足够的时间来为每个Pet生成一个新的种子。但是,在没有调试的情况下运行代码时,代码执行得足够快,随机种子不会发生变化。
将Random
对象的创建移到构造函数之外。例如:
public class Pet
{
private static readonly Random _rand = new Random();
public Pet()
{
type = ToType(_rand.Next(10));
// ...
}
}
您可以考虑将随机种子或随机对象作为参数传递给构造函数(或初始化对象的静态方法或工厂方法)。这将允许您在需要时确定性地创建Pet对象。
更好的方法是创建一个随机数生成接口并将其传递给构造函数,允许随后更改随机数生成器或模拟测试用途。