So, here's the deal.
I've set up an app for wp7 where there's an array with 50 quotes. When the user clicks a button, a random quote from the array is showed. Problem is, the quotes always appears in the same order. For example, quot开发者_开发知识库es are 1-50. The order is always 2, 4, 20, 31, 10,... Is there a way to solve this? I want that a random and different quote appear every time i use the app.
Here's the code:
string[] listaCantadas;
Random r1, r2;
public MainPage()
{
InitializeComponent();
listaCantadas = new string[]
{"//set of quotes
};
r1 = new Random(100);
r2 = new Random(r1.Next(0, 50));
}
//click event for display a random quote
int Cantada = r2.Next(0, listaCantadas.Length - 1);
txtBlockCantada.Text = listaCantadas[Cantada];
});
}
You create your first instance of Random
with Random(100)
i.e. a constant seed. So it will always return the same sequence. Which in turn means that the seed of your second instance of Random
will be constant too, and all the values it returns too.
Just create a single instance of Random
with the default constructor, i.e. new Random()
. This is seeded with the time, and thus will be likely different between different runs of the program.
Warning: Since the time only changes every few milliseconds (1-16ms on typical windows computers) if you create several instances of Random
with the default constructor in quick succession they will most likely all return the same sequence.
Another common pitfall is that Random
isn't thread-safe. But it doesn't look like you will hit this problem.
string[] listaCantadas;
Random r;//No need for more than one instance
public MainPage()
{
InitializeComponent();
listaCantadas = new string[]
{"//set of quotes
};
r = new Random();
}
//click event for display a random quote
int Cantada = r.Next(0, listaCantadas.Length - 1);
txtBlockCantada.Text = listaCantadas[Cantada];
});
}
You're explicitly stating the seed:
r1 = new Random(100);
r2 = new Random(r1.Next(0, 50));
r1
will always use the same seed (100), so r1.Next(0, 50)
will always give the same seed, so r2
will always use the same seed. You have no real randomness.
You should be creating a single instance of Random
and reusing it - whilst noting that Random
is not thread-safe. (If you're only going to use your instance from the UI thread, that's fine.)
See my article on random number generation in .NET for more information.
You shouldn't seed the random generator with a fixed seed unless you wanted repeatable sequences:
new Random(100);
should be
new Random();
Well you initialized the seed to always be 100 on your r1 randomizer. That of course means that acording to the seed you will get always the same numbers. Which means your r2 is always initialized with the same seed, so both r1 and r2 are always the same.
Random numbers are impossible for a PC, as strange as this sounds. So you need a "random" number to initialize your random generator.
Long story short. Remove the first random object and use the empty constructor on the second.
The default seed value is derived from the system clock and has finite resolution
You're seeding it with the same seed every time. Just use new Random()
. If that's not available on WP7, use a derivative of the current time as a seed.
The seed is always the same, even initialising from another random!
Try seeding another way:
new Random(unchecked((int) (DateTime.Now.Ticks)));
You have the same seed. Use something like a number generated from the current date
r1 = new Random(DateTime.Now.Year + DateTime.Now.Month + DateTime.Now.Day + DateTime.Now.Second); // etc
Simply use the following code;
Random r = new Random();
private void Form1_Load(object sender, EventArgs e)
{
string[] listaCantadas =
{
"q1",
"q2",
"q3",
"q4",
"q5"
};
//click event for display a random quote
txtBlockCantada.Text = listaCantadas[r.Next(0, listaCantadas.Length)];
}
精彩评论