【问题标题】:My random always gives me 4 and I don't know why [duplicate]我的随机数总是给我4,我不知道为什么[重复]
【发布时间】:2020-06-16 01:55:38
【问题描述】:

首先这里是代码。随机声明在第 3 行,随机使用在第 15 行左右。

public static void wildPokemonEncounter(string pokemonRegion)
{
    Pokemon wildPokemonEncountered = null;
    Random rnd = new Random();
    int possiblePokemon = 0;

    foreach (KeyValuePair<string, pokemonStats> kvp in GameReference.pokemonInformation)
    {
        if (kvp.Key != "Bublbasuar" && kvp.Key != "Squirtle" && kvp.Key != "Charmander")
        {
            if (pokemonRegion == "Plain")
            {

                if ((kvp.Value.typeOfPokemon == "Plant" || kvp.Value.typeOfPokemon == "Normal" || kvp.Value.typeOfPokemon == "Bug") && kvp.Value.evolutionNumber==1)
                {
                    possiblePokemon += 1;
                }
            }
        }
    }
    int whichPokemon = rnd.Next(1, possiblePokemon);
    int i = 1;
    Console.WriteLine(possiblePokemon+" "+ i + " " + whichPokemon);
    foreach (KeyValuePair<string, pokemonStats> kvp in GameReference.pokemonInformation)
    {
        if (kvp.Key != "Bulbasuar" && kvp.Key != "Squirtle" && kvp.Key != "Charmander")
        {
            if (pokemonRegion == "Plain")
            {
                pokemonStats thisPokemonsStats = GameReference.pokemonInformation[kvp.Key];
                if ((thisPokemonsStats.typeOfPokemon == "Plant" || thisPokemonsStats.typeOfPokemon == "Normal" || thisPokemonsStats.typeOfPokemon == "Bug") && thisPokemonsStats.evolutionNumber == 1)
                {
                    if (i == whichPokemon)
                    {
                        wildPokemonEncountered = new Pokemon(kvp.Key, kvp.Value);
                        slowTyper("`");
                        slowTyper("You found a Pokemon! Its a " + wildPokemonEncountered.name + "! Its level " + wildPokemonEncountered.level + " and of the type " + wildPokemonEncountered.typeOfPokemon + ".~");
                        Battle B = new Battle();
                        slowTyper("You enter into battle with the opposing Pokemon.");
                        Pokemon your_active_pokemon = null;
                        foreach (Pokemon pok in GameReference.pokemonInBag)
                        {
                            if (pok.is_Starting_Pokemon == true)
                            {
                                your_active_pokemon = pok;
                            }
                        }
                        B.PokemonBattle(wildPokemonEncountered, your_active_pokemon);
                        break;
                    }
                    else
                    {
                        i += 1;
                    }
                }
            }
        }
    }
}

我已经测试了只是放入一个 while true 循环,以检查随机是否由于某种原因在代码的这个区域中不起作用,但它起作用了。但是,出于某种原因,每次我运行它时,我都会得到一个 4 导致 Rattata 产生。有什么想法吗?

【问题讨论】:

  • 这种情况经常发生。 new Random() 使用时间来初始化它。这已经足够好了,除非你在一个循环中调用它——然后得到很多循环,它们都会给你完全相同的序列,总是从中得到第一个数字。你最好把它移开。鉴于您的方法是静态的,请在类加载时声明一个静态变量 OUTSIDE 并初始化 rnd ONCE,然后每次调用 Random() 都会在序列中为您提供另一个数字。现在它会给你下一个数字 - 在 0 到 15ms 之间的某个地方之后,这是很多循环。
  • 请注意,Random() 的这一特殊“功能”已在 .Net Core 中修复。
  • @Pac0 - 如果您使用默认构造函数,Random 类会从与时间相关的值中获取其种子。
  • @TomTom - 它没有解释为什么他每次总是得到 4。 Random 是根据当前时间播种的,因此我们创建对象时存在一定程度的随机性。
  • 顺便说一下,rnd.Next 函数是在 for 循环之外调用的,并且每次都使用 new Random() 对象。我看不出这是如何重复的,或者他的问题是如何解决的。重新开放投票。

标签: c#


【解决方案1】:

有多个 stackoverflow 来源,提到创建 new Random() 的时间太近,导致几乎相同的种子(我无法从文档中验证这一点)

Random number generator only generating one random number

还有人说如果过了一个毫秒就没事了:How much does new Random() depends on time?

在实践中,我能想到的唯一能解决您的问题的方法是确实使用这样的静态随机变量:

private static Random rnd = new Random();

public static void wildPokemonEncounter(string pokemonRegion)
{
    Pokemon wildPokemonEncountered = null;

    int possiblePokemon = 0;

    foreach (KeyValuePair<string, pokemonStats> kvp in GameReference.pokemonInformation)
    {
        if (kvp.Key != "Bublbasuar" && kvp.Key != "Squirtle" && kvp.Key != "Charmander")
        {
            if (pokemonRegion == "Plain")
            {

                if ((kvp.Value.typeOfPokemon == "Plant" || kvp.Value.typeOfPokemon == "Normal" || kvp.Value.typeOfPokemon == "Bug") && kvp.Value.evolutionNumber==1)
                {
                    possiblePokemon += 1;
                }
            }
        }
    }
    int whichPokemon = rnd.Next(1, possiblePokemon);
    int i = 1;
    Console.WriteLine(possiblePokemon+" "+ i + " " + whichPokemon);
    foreach (KeyValuePair<string, pokemonStats> kvp in GameReference.pokemonInformation)
    {
        if (kvp.Key != "Bulbasuar" && kvp.Key != "Squirtle" && kvp.Key != "Charmander")
        {
            if (pokemonRegion == "Plain")
            {
                pokemonStats thisPokemonsStats = GameReference.pokemonInformation[kvp.Key];
                if ((thisPokemonsStats.typeOfPokemon == "Plant" || thisPokemonsStats.typeOfPokemon == "Normal" || thisPokemonsStats.typeOfPokemon == "Bug") && thisPokemonsStats.evolutionNumber == 1)
                {
                    if (i == whichPokemon)
                    {
                        wildPokemonEncountered = new Pokemon(kvp.Key, kvp.Value);
                        slowTyper("`");
                        slowTyper("You found a Pokemon! Its a " + wildPokemonEncountered.name + "! Its level " + wildPokemonEncountered.level + " and of the type " + wildPokemonEncountered.typeOfPokemon + ".~");
                        Battle B = new Battle();
                        slowTyper("You enter into battle with the opposing Pokemon.");
                        Pokemon your_active_pokemon = null;
                        foreach (Pokemon pok in GameReference.pokemonInBag)
                        {
                            if (pok.is_Starting_Pokemon == true)
                            {
                                your_active_pokemon = pok;
                            }
                        }
                        B.PokemonBattle(wildPokemonEncountered, your_active_pokemon);
                        break;
                    }
                    else
                    {
                        i += 1;
                    }
                }
            }
        }
    }
}

希望有人可以验证其中一个并为您解释相同的值。

编辑 1

根据fiddle here 证明两个答案都是正确的

using System;
using System.Collections.Generic;

public class Program
{
    private static HashSet<int> randomValues = new HashSet<int>();

    public static void Main()
    {
        for(int i = 0; i < 2000; i++)
        {
            wildPokemonEncounter();
        }

        Console.WriteLine("1st iteration results");
        foreach(int rnd in randomValues) {
            Console.WriteLine(rnd);
        }

        randomValues.Clear();

        for(int i = 0; i < 20000; i++)
        {
            wildPokemonEncounter();
        }

        Console.WriteLine("2nd iteration results");
        foreach(int rnd in randomValues) {
            Console.WriteLine(rnd);
        }
    }

    //static Random rnd = new Random();

    public static void wildPokemonEncounter()
    {
        int possiblePokemon = 4;
        Random rnd = new Random();
        int whichPokemon = rnd.Next(1, possiblePokemon);
        if(!randomValues.Contains(whichPokemon)) {
            randomValues.Add(whichPokemon);
        }


    }
}

结果:

第一次迭代结果 3 第二次迭代结果 3 1 2

只是太快了,所有的迭代都在1毫秒内完成。

【讨论】:

  • 这是一个演示问题的 dotnetfiddle:dotnetfiddle.net/TEpgO3
  • 是的,我只是将它贴在我的文档顶部,现在我在该文档中使用的所有随机数都在运行它。
  • 我运行了一些测试,似乎毫秒数太多了 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-08-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-16
相关资源
最近更新 更多