Uk rain troll
Uk rain troll

Reputation: 1

Generating random values from ANY number of arrays

I have such a simple code to generate a character in a game.

string[] sex = new string[] { "Man", "Woman" };
string[] age = new string[] { "Child", "Teen", "Young", "Middle-aged", "Elderly", "Old" };
string[] beauty = new string[] { "Beautiful", "Pretty", "Normal", "Plain", "Ugly" };

Random i = new Random();
string sexR = sex[i.Next(0, sex.Length)];
string ageR = age[i.Next(0, age.Length)];
string beautyR = beauty[i.Next(0, beauty.Length)];
Console.WriteLine("{0} {1} {2}", sexR, ageR, beautyR);

While I have just three lines it's Ok. But I want to have many more character traits in the future. How can I make a function that will generate random values from ANY number of arrays I create in my program?

Upvotes: 0

Views: 146

Answers (3)

Nathan
Nathan

Reputation: 6531

I think we can first talk about clearer code for your use case. You clearly are creating some kind of person, so lets represent that with a person class. We've got quite a complex creation scenario, we could put it in the constructor, but I think the best thing to do is create a factory class for this.

Given that, we can use tricks like GetRandomElement to ease the syntax. However, I don't think we need to generalise further. I'm not keen on foreach-ing through the properties or anything like that, I think holding the arrays of your possible values distinct is more declarative.

public class Person{

    public string Sex { get;set;}
    public string Age {get;set;}
    public string Beauty { get;set;}    
}

public class RandomPersonFactory{

    private Random random;
    private string[] SexChoices = new[] { "Man", "Woman" };
    private string[] AgeChoices = new[] { "Child", "Teen", "Young", "Middle-aged", "Elderly", "Old" };
    private string[] BeautyChoices = new[] { "Beautiful", "Pretty", "Normal", "Plain", "Ugly" };

    public RandomPersonFactory(Random random){
        this.random = random;
    }

    public Person CreatePerson(){
        return new Person {
            Sex = GetRandomElement(this.SexChoices),
            Age = GetRandomElement(this.AgeChoices),
            Beauty = GetRandomElement(this.BeautyChoices)
        };
    }

    private T GetRandomElement<T>(T[] array){
        return array[this.random.Next(array.Length)];
    }
}

You could organize your code like this; But if you aren't genuinely changing the quantity and type of traits on individual persons at run time it's needless complexity and misdirection. Ask yourself whether you can have a person without a sex trait, or age trait etc. In this case I would write the factory in a similar way, but I would build up an collection of traits one trait at a time in the CreatePerson method and then create the person with that collection.

public class Person2{
   public IList<Trait> Traits {get;set;}
}

public class Trait{
    public string Name {get;set;}
    public string Value {get;set;}
}

Upvotes: 1

Servy
Servy

Reputation: 203829

If you want to be able to get the value of any number of lists, instead of just a single one, then write a method that accepts a collection of lists, and picks a random item of each one:

public static IEnumerable<T> ChooseFromAll<T>(
    IEnumerable<IList<T>> lists,
    Random generator)
{
    foreach (var list in lists)
        yield return list[generator.Next(list.Count)];
}

Upvotes: 1

David L
David L

Reputation: 33823

You can create a list of your arrays and loop through those arrays, storing each attribute separately and using a stringbuilder to output the result.

List<string[]> traits = new List<string[]> 
{
    new string[] { "Man", "Woman" },
    new string[] { "Child", "Teen", "Young", "Middle-aged", "Elderly", "Old" },
    new string[] { "Beautiful", "Pretty", "Normal", "Plain", "Ugly" }
};

Random i = new Random();
StringBuilder traitOutput = new StringBuilder();

foreach (string[] trait in traits)
{
    traitOutput.AppendFormat("{0} ", trait[i.Next(0, trait.Length)]);
}

Console.WriteLine(traitOutput);

Upvotes: 1

Related Questions