I have a very strange problem that I never been in touch with in my entire life.
This is what I been up to:
I have programmed a game that involves you going to throw two dices and the sum of the two dices should be seven for you to win.
This is how the interface is built:
The textbox1 shows the value of first thrown dice.
The textbox2 shows the value of second thrown dice.
The textbox3 shows the sum of the both dices.
The button1 throws the dices.
This is the problem:
When i Debugg (F5) the application in Visual Studio 2013 Ultimate
the textboxes gets the exactly same value all the time. This is wrong, it shouldn't act like this.
When i Step Into (F11) the application/code the textboxes gets
different values, just as it should be, this is right, this is how the program should act.
Is there anyone that can help with this problem, i think that I have just missed a very small but a obvious thing that I have missed but I really can't find anything, I'm actually out of ideas!
Attachments
Here is all the files, I hope it will help you, the program is written in Swedish but I don't think that makes any problem, if it do, I can translate the whole solution to English.
The whole Solution: Throw_Dices.zip
The Code: Big picture on three screens of the code
From MSDN:
different Random objects that are created in close succession by a
call to the default constructor will have identical default seed
values and, therefore, will produce identical sets of random numbers
In your Kasta.cs, create a static instance of Random instead of multiple ones.
public class Tarning
{
private static Random ran = new Random();
int slump;
public int Kasta()
{
//Random ran = new Random();
slump = ran.Next(1, 6);
return slump;
}
}
Another possibility would be to create a seed manually. For instance like
public int Kasta()
{
byte[] seed = new byte[4];
new RNGCryptoServiceProvider().GetBytes(seed);
int seedInt = BitConverter.ToInt32(seed, 0);
Random ran = new Random(seedInt);
slump = ran.Next(1, 6);
return slump;
}
Instead of creating two Dice (Tarning ?)
Create one and roll it twice.
Or create both on start up, Or perhaps have a class that holds 2 dice.
and throw them again.
You should also google random and seeding, what's happening is from the same seed value, you get the same sequence of random numbers. Debugging is introducing enough of a delay between the new Random calls, that the seed (based on the clock) has changed between the two calls.
PS your button1Click handler
should set the three textbox values, not trigger textbox changed events which then set them. Imagine if you wanted to reuse your code, you'd have to create a UI to do it.
A better way would be to have a class that held two (or n) dice with a Roll method and a property that returned the result. Then you could reuse it without worrying about when and how.
Related
This question already has answers here:
Random number generator only generating one random number
(15 answers)
Closed 5 years ago.
Yesterday I wrote my first answer at Programming Puzzles & Code Golf. The question said this:
Given an input string S, print S followed by a non-empty separator
in the following way:
Step 1: S has a 1/2 chance of being printed, and a 1/2 chance for the program to terminate.
Step 2: S has a 2/3 chance of being printed, and a 1/3 chance for the program to terminate.
Step 3: S has a 3/4 chance of being printed, and a 1/4 chance for the program to terminate.
…
Step n: S has a n/(n+1) chance of being printed, and a 1/(n+1) chance for the program to terminate.
So I went and wrote this code (ungolfed):
Action<string> g = s =>
{
var r = new Random();
for (var i = 2; r.Next(i++) > 0;)
Console.Write(s + " ");
};
This code works fine, but then someone said that I could save a few bytes creating the r variable inline, like this:
Action<string> g = s =>
{
for (var i = 2; new Random().Next(i++) > 0;)
Console.Write(s + " ");
};
I tried but when I executed the code, it always went in one of two possibilities:
Either the program halted before printing anything (the first call to Next() returns 0), or
The program never stops (the calls to Next() never return 0).
When I reverted the code to my original proposal, the program stopped more randomly as expected by the OP.
I know that the new Random() constructor depends on time, but how much? If I add a Sleep() call, the code behaviour starts to seem really random (but not much, the strings returned are still longer than the ones returned by the initial code):
Action<string> g = s =>
{
for (var i = 2; new Random().Next(i++) > 0; Thread.Sleep(1))
Console.Write(s + " ");
};
If I increment the sleep time to 10 ms, now the code really behaves like the original one.
So why is this? How much does the Random class depends on time? How exactly does the Random class seeds the number generator when calling the empty constructor?
Note: I know that creating a single Random object is the best practice, I just wanted to know a bit more than what the MSDN says:
The default seed value is derived from the system clock and has finite resolution.
What is that "finite resolution" the Random class default constructor uses as seed? How much time should we separate the construction of two Random objects to get different sequences? How much would those two different sequences differ when creating the Random instances too close in time?
What is that "finite resolution" the Random class default constructor uses as seed?
It uses Environment.TickCount which has a resolution of one millisecond.
How much time should we separate the construction of two Random objects to get different sequences?
As per the previous section, by at least one millisecond - or manually feed another seed to the constructor each time (or, well, reuse the same generator?)
How much would those two different sequences differ when creating the Random instances too close in time?
Matt Moss did a nice visualization in his Random Headaches from System.Random blog post:
Each row of the bitmap represents five first generated numbers with that seed (without preserving generated order):
As you can see, numbers are being selected from distinct but related sequences. As MSDN on Random says, "The chosen numbers... are sufficiently random for practical purposes."
In my game I'm going to use random values to pick the reward the player gets from a chest. The problem is that you can quick save and quick load and that means they can keep reloading to re-randomize until they get what they want. Is there some way that I could get the current seed value of my Random object and possibly return to that same point when they load so that they couldn't abuse the randomization?
This is not possible.
Instead, you can serialize the Random instance using binary serialization.
Random is [Serializable], and the seed and internal state will persist.
Note, however, that saving the random seed allows your players to predict the future, which is very useful if you allow saving in battle.
Also note that users can still save, open the chest, load, perform an action that generates a random number, then get a different item from the chest.
Not sure on getting the seed, but you could save the value you give to the Random object. Remember, there are two constructors. The second is Random(Int32), so if you set the seed yourself (an easy enough value is Environment.TickCount), you could store that value somewhere before you pass it to the constructor. If you haven't read it yet, check out the MSDN documentation at https://learn.microsoft.com/en-us/dotnet/api/system.random.
Indeed, the Seed isn't stored as it is not relevant for the algorithm after initialization. One of its derivatives, mj, is stored in the SeedArray though, you can check that using Reflection to compare both Random instances:
int subtraction = (Seed == Int32.MinValue) ? Int32.MaxValue : Math.Abs(Seed);
mj = MSEED - subtraction;
SeedArray[55]=mj;
So all you have to do is to check the last element (index 55) in the SeedArray. This is the only place Seed is used.
[Moved answer from deleted question How to determine if two Random instances have the same seed?]
You can calculate the random reward as a hash function of:
some seed that is assigned when you begin a new game, and is persisted in saved games; and
some constant property of a chest that is invariant across all games (e.g. a fixed ID, or its position if it never moves).
This method has the advantage that a given chest will always yield the same reward in a given game, no matter how many times you save and replay, even if chests are opened in different orders, or other 'random' events are triggered in different orders. Also each chest's reward is independent of other chests' rewards, so long as the chest's property used in the hash is independent.
In the following example GetRewardId generates a reward ID as a hash of the game seed XORed with the x coordinate of a chest. It uses Random to perform the hash, by using the hash input as the Random object's seed, and taking the first randomly generated number as the output.
private static int GetRewardId(int seed, float coord, int numRewards)
{
int tempSeed = BitConverter.ToInt32(BitConverter.GetBytes(coord), 0) ^ seed;
return new Random(tempSeed).Next(numRewards);
}
int seed = new Random().Next();
int numDifferentRewards = 5;
float xCoordinate = chest.Position.X;
int rewardId = GetRewardId(seed, xCoordinate, numDifferentRewards);
If many of your chests are likely to be aligned in sace, you may want to choose a different property, or use additional dimensions, by XORing with the y and/or z coordinates too.
I'd probably just use this as per MSDN: http://msdn.microsoft.com/en-us/library/ctssatww.aspx
Random(seed)
where seed is some value I've loaded from storage.
This is only related on a tangent, but in case anyone is wondering why Random doesn't have a property called Seed or a method called GetSeed(), I'm willing to wager that it's likely due to security concerns: Would you want to expose the inner workings of your "random" number generator to the outside world? Absolutely not! Otherwise, some client code could poke around until it got the values you were using and then do nasty and unintended things with them.
Unfortunately, in the reference implementation from Microsoft, the no arg ctor's seed value is not even saved, let alone exposed for access:
http://referencesource.microsoft.com/#mscorlib/system/random.cs,bb77e610694e64ca
However, as you can also see in the reference implementation, the value you can pass in (probably should -- I know I do), just like they do, is: Environment.TickCount
So save that to a variable, then pass that variable in to the ctor that takes an arg and you now know the seed. Not after the fact, but this should be sufficient for whatever your intent is.
I recommend you to generate a random number and use it as a seed number to your real random number generator. By this method you have a seed number that is actually a random number and you can save your seed number for further using.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
random string generation - two generated one after another give same results
I am writing a simple dice game for windows phone 7, that involves rolling two dice at the same time. Here is my Dice Roll Code:
private int DiceRoll()
{
int result;
Random rnd = new Random();
result = rnd.Next(1, 7);
return result;
}
I then have this code that rolls the dice when a button is clicked:
private void roll_Click(object sender, RoutedEventArgs e)
{
roll1 = DiceRoll();
roll2 = DiceRoll();}
My problem is that both die get the same result.
Any idea how I can get a rolling algorithm that will usually return different results, but occasionally return the same?
The default seed for Random is based on the current time. To quote the documentation,
As a result, different Random objects that are created in close succession by a call to the default constructor will have identical default seed values and, therefore, will produce identical sets of random numbers. This problem can be avoided by using a single Random object to generate all random numbers.
That is exactly what you should do: create one instance of Random and use it to generate all your random numbers.
You need to keep one Random object around and reuse it; every time you create a new Random object, you effectively reset the sequence of numbers to begin in the same place. Store the Random object as a member variable someplace. You'll also want to seed it with a different value each time you run the program -- for example, a value based on the system clock time.
The clear majority of 'random number' tools I've seen fail badly if you allocate two or more random objects in a single application. You're allocating a new Random object for every invocation, and each time they are going to be seeded with something pretty weak, and maybe even identical seeds.
So, generate a single Random object and use it over the life of your application.
I know C# has the Random class and probably a few classes in LINQ to do this, but if I was to write my own code to randomly select an item from a collection without using any built in .NET objects, how would this be done?
I can't seem to nail the logic required for this - how would I tell the system when to stop an iteration and select the current value - at random?
EDIT: This is a hypothetical question. This is not related to a production coding matter. I am just curious.
Selecting a random element from a collection can be done as follows.
Random r = new Random();
int randomIndex = r.Next(0, myCollection.Size -1);
var randomCollectionItem = myCollection[randomIndex];
Unless you have a VERY good reason, writing your own random generator is not necessary.
My advice to you is DON'T DO IT. Whatever reason you think you may have for not wanting to use the built-in library, I am pretty sure you misunderstood something. Please go back to the drawing board.
All of the advice above is technically accurate, but is kind of like giving a chemistry textbook to someone who wants to refine his own oil to use in his car.
There are many pseudo-random number generators. They aren't truly random, but they come at different quality, distinguished by their statistical and sequential properties and what purpose they are applicable for.
It very much depends on "how random you need it". If it just needs to "look random to a human", simple generators look like that:
rnd = seed; // some starting value
rnd = (a * rnd + b) % c; // next value
...
For well chosen values of a, b, and cthese generators are ok for simple statistical tests. A detailed discussion and common values for these you find here.
One interesting approach is to collect as much "external" data as possible - like time between keypresses, mouse movements, duration of disk reads etc. -, and use an algorithm that accumulates randomness while discarding dependency. That is mathematically tricky though (IIRC not long ago a critical attack surfaced based on one of these not being as random as thought).
Only a very few special applications use a truly random external hardware source - anything between a open-imput amplifier and radioactive decay.
You need to use a seed, something semi random provided by the computer itself.
Maybe use very fine resolution time and use the last couple microseconds when the method is called. That should be random enough to generate anything from 00 to 99, you can then go from there.
It sounds like your problem isn't in calculating a random number, but in how to use that random number to select an item from a list. Assuming you can create a random number somehow, all you need to do is use it as the argument to the list's indexer.
int index = customRandomGenerator.Next();
var selection = items[index];
Assuming that your presupposition about having to iterate through the list is correct (or the collection doesn't have an indexer) then you could do:
int index = customRandomGenerator.Next();
Item selection = null;
for (int i = 0; i < items.Length; i++)
{
if (i == index)
{
selection = items[i];
break;
}
}
The only true "cryptographically strong" random number generator in the .Net Framework is in System.Cryptography.RandomNumberGenerator - run this through Reflector to see what is does? Looking at your problem you would need a to know the Count of the collection otherwise you may never retrieve an item - you would need to specify a start and end value to draw random numbers from - the Random class would work best - pop it through Reflector.
Well, I never thought about implementing that myself as it seems like reinventing the wheel but you may have a look on this wikipedia article, hope it helps you do what you want
Random Number Generator
I have a simple piece of code:
public string GenerateRandomString()
{
string randomString = string.Empty;
Random r = new Random();
for (int i = 0; i < length; i++)
randomString += chars[r.Next(chars.Length)];
return randomString;
}
If i call this function to generate two strings, one after another, they are identical... but if i debug through the two lines where the strings are generated - the results are different.
does anyone know why is it happening?
This is happening, because the calls happen very close to each other (during the same milli-second), then the Random constructor will seed the Random object with the same value (it uses date & time by default).
So, there are two solutions, actually.
1. Provide your own seed value, that would be unique each time you construct the Random object.
2. Always use the same Random object - only construct it once.
Personally, I would use the second approach. It can be done by making the Random object static, or making it a member of the class.
The above answers are correct. I would suggest the following changes to your code though:
1) I would suggest using a StringBuilder instead of appending to the string all the time. Strings are immutable, so this is creating a new string each time you add to it. If you have never used StringBuilder, look it up. It is very useful for this sort of work.
2) You can make your method easier to reuse if you pass the length into the method itself. You could probably pass the chars array in as well, but I've left that out.
3) Use the same random object each time, as suggested above.
public string GenerateRandomString(int length)
{
StringBuilder randomString = new StringBuilder(length);
for (int i = 0; i < length; i++)
randomString.Append(chars[(int)(_RandomObj.Next(chars.Length))].ToString());
return randomString.ToString();
}
It's because you're creating two random objects at the same time. This is giving it the same seed, so you're going to get the same numbers.
When you debug it, there's time between the creation of the random objects which allow them to get different seeds.
The default constructor for Random (the one you're using) seeds the generator with a value based on the current time. If the time in milliseconds doesn't change between the first and second call of the function, it would use the same random seed.
My suggestion is to use a static Random object and only initialize it once.
Since the Random generator is tied with the system clock you are probably displaying the same results with that time period. There are several ways to correct. If you are using loops place the Random rnd = new Random(); outside of the loop.
Place the Random rnd = new Random(); line where you declare your variables and use the same variable throughout your program (rnd for this example).
This will work in most cases.