0

Apologies on the duplicate question, I viewed similar Qs and just got confused. I have a method that is prompting a user to enter 5 different attribute values and would like to return the values chosen to be used for later decisions in the program.

while (true)
{
    Console.Write("Please enter a value between 0-10 for ingenuity: ");
    inputIngenuity = Console.ReadLine();
    if (!UInt32.TryParse(inputIngenuity, out validIngenuity))
    {
        Console.WriteLine();
        Console.WriteLine("Input was not a valid value for ingenuity.");
    }
    else if (validIngenuity < 0 || validIngenuity > 10)
    {
        Console.WriteLine();
        Console.WriteLine("Input was not a valid value for ingenuity.");
    }
    else if (validIngenuity > (attributePoints - validStrength - validIntelligence - validPersonality - validSpeed))
    {
        Console.WriteLine();
        Console.WriteLine("You do not have enough attribute points remaining.");
    }
    else break;
}
Console.WriteLine();
Console.WriteLine("You have " + (attributePoints - validStrength - validSpeed - validPersonality - validIntelligence - validIngenuity) + " attribute points remaining");
Console.WriteLine();
Console.WriteLine(String.Format("Strength Value     =   {0}", validStrength));
Console.WriteLine(String.Format("Speed Value        =   {0}", validSpeed));
Console.WriteLine(String.Format("Intelligence Value =   {0}", validIntelligence));
Console.WriteLine(String.Format("Personaility Value =   {0}", validPersonality));
Console.WriteLine(String.Format("Ingenuity Value    =   {0}", validIngenuity));
Console.WriteLine();
Console.WriteLine("These are your attributes!");

while (true)
{

    Console.Write("Do you accept these? Type 1 for Yes, Type 2 for No. If No then choose again:  ");
    areYouHappyWithChoices = Console.ReadLine();
    if (!UInt32.TryParse(areYouHappyWithChoices, out validChoices))
        Console.WriteLine("Please try again. Enter 1 for Yes and 2 for No");
    else if (validChoices > 2 || validChoices < 1)
        Console.WriteLine("Please try again. Enter 1 for Yes and 2 for No");
    else if (areYouHappyWithChoices == "2")
        chooseAttributePoints(); //this method contains the whole routine
    else
        Console.WriteLine("We may now begin the game!");
    break;
}
UInt32[] attributePointArray = new UInt32[5] { validStrength, validSpeed, validIntelligence, validPersonality, validIngenuity };
return attributePointArray;

The while statement for ingenuity is repeated in the method for the other 4 attributes and works without issues. I'm envisioning later code that would have different results based on how strong the user is for example. Am I going in the right direction by trying to put the values into an array? Thank you.

Lemonseed
  • 1,644
  • 1
  • 15
  • 29
Yurconale
  • 49
  • 5
  • Does your code not work or are you just asking for advice on how to proceed? An array seems like a good way to return multiple values. – Jacobr365 Feb 10 '16 at 19:00
  • 2
    A key/value pair might do a better job in maintainability. Have you considered using a `Dictionary`? (that is; if you want to have it "non-strong-typed") – Stefan Feb 10 '16 at 19:00
  • 5
    Array works, another option is create a class with five properties – DanielVorph Feb 10 '16 at 19:00
  • Conventionally, unless your coding standards or self-imposed readability guidelines suggest otherwise, `UInt32` becomes `uint` in C#. – D. Ben Knoble Feb 10 '16 at 19:05
  • I'm getting an error as it's currently written on the last line "Cannot implicitly convert type 'uint[]' to 'uint'. I'm working my way through an intro to C# book and will also skip to the class creation chapter to give that suggestion a go. I just want to make sure that if, later in the game, a strength value of 6 is required to do something, the code can reference whatever value was chosen in this method and proceed accordingly. – Yurconale Feb 10 '16 at 19:06
  • If you've seen similar question you should link to that question and *explain* why your one is not duplicate. "got confused" is not an explanation of why your question is different as there is no way to know what you need help with (and only can add "too broad" as valid close reason). – Alexei Levenkov Feb 10 '16 at 19:19

2 Answers2

5

That would be one way to do it, however I think you'd be better off having a class or struct created to represent the data. This way you'll keep the "strong typey ness" and context of what your data is, rather than simply an array index.

example:

public class Person
{
    public int Strength { get; private set; }
    public int Speed { get; private set; }
    public int Intel { get; private set; }
    public int Personality { get; private set; }
    public int Ingenuity { get; private set; }

    public Person (int strength, int speed, int intel, int personality, int ingenuity)
    {
        this.Strength = strength;
        this.Speed = speed;
        this.Intel = intel;
        this.Personality = personality;
        this.Ingenuity = ingenuity;
    }
}

Then your assignment to array:

UInt32[] attributePointArray = new UInt32[5] { validStrength, validSpeed, validIntelligence, validPersonality, validIngenuity };
        return attributePointArray;

Gets updated to:

return new Person(validStrength, validSpeed, validIntelligence, validPersonality, validIngenuity);

and your return type needs to be changed from uint[] to Person

This way, rather than having to remember that returnedArray[1] is Speed (or whatever) - you would simply use returnedPerson.Speed.

Kritner
  • 13,557
  • 10
  • 46
  • 72
  • Thank you, I will give this a try – Yurconale Feb 10 '16 at 19:20
  • I created a new class and updated my code per your suggestion and am now getting errors on the return new Person line saying "Argument 1: cannot convert from 'uint' to 'int' and so on through Argument 5. I tried switching any uint variables to int and still had the error. What am I doing wrong? – Yurconale Feb 10 '16 at 20:50
  • You can't mix and match `int` and `uint` choose all of one of then and update your types accordingly. My code was only meant as an example, but given the error messages you should be able to figure it out. To better fit your currently posted code, my class should have been made up of `uint` properties. You didn't post the entirety of your method, so I can't give much more advice than that. – Kritner Feb 10 '16 at 21:24
3

You should create an object type that wraps the attributes you want to return. The return type of your method will be your newly-created object type.

Dan Forbes
  • 2,734
  • 3
  • 30
  • 60
  • 2
    But @Thomas, what if the type grows, or is needed for type-safety elsewhere? If it is truly a wrapper around simple attributes (i.e. fields) a struct might even make sense, like Kritner mentions in [his answer](http://stackoverflow.com/a/35323753/4400820) – D. Ben Knoble Feb 10 '16 at 19:04
  • 1
    I stopped using `Tuple`s. They're not at all expressive. Referring to the attributes as `Item1`, `Item2`, etc is confusing. Much better to create a class with descriptive attribute names like `Ingenuity`, `Intelligence`, etc. – Dan Forbes Feb 10 '16 at 19:11