LucidFox LucidFox - 3 months ago 11
C# Question

Generating random outputs with seed value defined and changed at run-time

I am writing a random names generator in C#.
It is a WPF application written in Visual Studio 2015.

A WPF Window screenshot to illustrate:

A WPF Window screenshot to illustrate

The trouble I have occurs when I try to generate names from seed values set by the user at run-time. Before, I had the random method, that supplied all of the names generating logic, declared as static and the seed value was unchanged for the whole time the program ran. This worked well, generating different output every time I clicked Generate Name button.

I wanted, however, to add the functionality of changing the seed number of the built-in random method when the program runs. In order to do this, I had to change the declaration to non-static and make the Random a part of the NamesGenerator object instance. Now, every time I change the seed value, a different name is created as it should, but when I leave the seed value the same, each click on the Generate Name button creates the same output. (You can see this on the WPF Window screenshot.)

What I am trying to end up with is a program that can generate the same outputs (hence I am using seed values), but I want for each seed value to have a set of names available (as there was when the random method was static) not just one name generated all the time.

I am not sure this is even possible, and if it is, it is clearly out of my league for now, that is why I am asking for help. I tried to search for similar issues on the web and SO, but I could not find anything helpful.

Here, I supply some of my code:

class NamesGenerator
{
Random randomNumber; //I tried to have this static and non-static, to no avail

...NAMES GENERATING CODE...

//SetSeedValue is called from the WPF Window and instantiates a new Random instance with seed value.
public void SetSeedValue(int seedValue)
{
randomNumber = new Random(seedValue);
}
public string GenerateName()
{
// determines if the name is male or female (unlike in English, there is a whole lot of differences in Russian related to this)
bool genderValue = equalDistributionMechanism(); // returns true if the name is masculine, false if it is not

string name;

name = makeTestName((randomNumber.Next(1, 2)), genderValue); //first name

name += " " + makeTestName((randomNumber.Next(1, 2)), genderValue)
+ addSuffix((randomNumber.Next(1, 7)), gender: genderValue); //last name

return name;
}


My thought on how to solve my problem would be to check if randomNumber has already been instantiated with given seedValue, and if yes, not create another instance of randomNumber in SetSeedValue method, but I have no idea on how to check for this.

A WPF code I am using:

public partial class MainWindow : Window
{
NamesGenerator namesGenerator = new NamesGenerator();

public MainWindow()
{
InitializeComponent();
}

private void GenerateNameButton_Click(object sender, RoutedEventArgs e)
{
int seedValue;

try
{
seedValue = int.Parse(SeedNumberTextBox.Text);
}
catch
{
MessageBox.Show("Not a valid seed number. Try again.", "Invalid Seed Number", MessageBoxButton.OK, MessageBoxImage.Warning);
return;
}

namesGenerator.SetSeedValue(seedValue);
AddNewName(namesGenerator.GenerateName());
}
}


Thanks for your time and any thoughts on how to accomplish this :).

EDIT:
Adding the GenerateName method due to a request from Hüseyin BurakKaradag.

Answer

Before you edited your question, you had:

private void GenerateNameButton_Click(object sender, RoutedEventArgs e)
    {
        int seedValue;

        try
        {
            seedValue = int.Parse(SeedNumberTextBox.Text);
        }
        catch
        {
            MessageBox.Show("Not a valid seed number. Try again.", "Invalid Seed Number", MessageBoxButton.OK, MessageBoxImage.Warning);
            return;
        }

        namesGenerator.SetSeedValue(seedValue);
        AddNewName(namesGenerator.GenerateName());
    }

So, every time the button was pressed, the seed value was set to the same value (unless the textbox text was changed, that is). This causes Random to generate the same number over and over.

You can either add a button that sets the seed value and not set the seed value in the generate names button or if you want to keep the single button then cache the current seed value and only create a new Random when it changes. Like this:

class NamesGenerator
{
    Random randomNumber;
    int currentSeed = -1;

    public void SetSeedValue(int seedValue)
    {
        if (currentSeed == seedValue)
            return;
        currentSeed = seedValue;
        randomNumber = new Random(seedValue);
    }
}

Or cache the TextBox's text so you don't have to parse it each button press.