Search code examples
c#listobjectgetset

List resetting when adding new items (Edited title to reflect actual issue)


Original Title: Get-Set to add Object w/multiple properties into a list C#

Edit: I had originally thought the issue was in setting up properties for the list objects, when it was an issue with regards to where I had initialized the list in my main code class.

Original Post:

New to coding, taking a C# course. We're working on encapsulation and get:set/properties.

The assignment says that we have to build a class that creates a die with an input number of sides, and "roll" the die for a random number. Easy!

In a second class, we have to build a function to add or remove any number of dice to the pool, and then roll them all for a result.

I'm assuming they want the dice pool to be a list that is private.

My logic going in was to create the single OneDie class, and then using a xDy notation in the main program prompt to add x number of die with y sides to the list. (ie: add 2d6)

I've built an AddDie function that should do that, but when I check my list count after it's done, the count is 0. The private list (_dicePool) seems to be re-setting to zero every time I try to add a new object to the list. I suspect I'm not building my property DicePool's get/set functionality correctly, but I'm not sure how to call my 2-parameter AddDice function from inside the DicePool{set}, or even if that's the approach I should take.

enter image description here

Assuming the list should be private, am I missing something to permanently add new objects to the list?

Edit to add: OR, would it be better to create a ManyDice object? But how do I build this.Sides and this.Roll from the OneDie object?

Here's my code that's applicable to adding objects (dice) to the list (dicepool).

class ManyDice
{
    private List<OneDie> _dicePool = new List<OneDie>();

   //What I think I might have to do:
   public List<OneDie> DicePool
    {
        get 
        { 
            return this._dicePool; 
        }
        set 
        {
            //???????????? how do I call AddDice, when I need 2 parameters for it?
        }
        
    }


    public void AddDie(int number, int sides)
    {

        for (int i = 0; i < number; i++)
        {
            this.dicePool.Add(new OneDie(sides));

        }
    }
}
class OneDie
{
    private int _sides, _rolledValue;

    public int Sides
    {
        get
        {
            return this._sides;
        }
        set
        {
            this._sides = value;
        }
    }
    public int RollValue
    {
        get
        {
            return this._rolledValue;
        }
        set
        {
            this._rolledValue = value;
            RollIt(value);
        }
    }
    public OneDie()
    {

    }
    public OneDie(int sides)
    {
            this.Sides = sides;
            this.RollValue = sides;
    }

    private int RollIt (int sides)
    {
        Random random = new Random((int)DateTime.Now.Ticks);
        return random.Next(1, (sides + 1));
    }

}
class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("Let's roll some dice!");
        Console.WriteLine("Please enter the number of dice you want to roll in the following format:");
        Console.WriteLine("xdy, where \"x\" is the number of dice you want and \"y\" is how many sides they have.");
        Console.WriteLine("Example: 2d6 is 2 6-sided dice. Perfect for playing Catan! (or Monopoly)");
        Console.WriteLine("Please limit your dice to d4, d6, d8, d10, d12, d20");

        Console.WriteLine("To add a die, type \"add xdy\" to add x number of y sided dice.");
        Console.WriteLine("To remove a die, type \"remove xdy.\"  to remove x number of y sided dice.");
        Console.WriteLine("Type \"dice\" to see a list of all the dice in the pile.");
        Console.WriteLine("Type \"roll\" to roll all the dice and see the results!");
        Console.WriteLine("Type \"clear\" to clear all the dice and start agin!");
        Console.WriteLine("Type \"exit\" to exit program\n");
        PlayDice();
        Console.ReadKey();
    }


    static void PlayDice() 
    { 
        do 
        {
            string[] xDy = null;
            int numberOfDice = 1;
            int numberOfSides=1;
            Console.WriteLine("\nEnter your command:");
            string option = Console.ReadLine();
            option = option.ToLower().Trim();
            string[] words = option.Split(' ');
            string command = words[0];
            //CheckCommand(command);
            if (words.Length > 1)
            {
            xDy = words[1].Split('d');
            numberOfDice = int.Parse(xDy[0]);
            numberOfSides = int.Parse(xDy[1]);
            }
            ManyDice die = new ManyDice();

            if (command == "exit") 
            {
                Console.WriteLine("Thank you, play again, soon!");
                break;
            }
            else if (command == "add") 
            {
                //numberOfSides=CheckDice(numberOfSides);
                
                die.AddDie(numberOfDice, numberOfSides);
                Console.WriteLine("You have {0}ed {1} {2}-sided dice.", command, numberOfDice, numberOfSides);
            }
            else if (command == "remove")
            {
                Console.WriteLine("You have {0}d {1} {2}-sided dice.", command, numberOfDice, numberOfSides);
            }
            else if (command == "dice")
            {
                Console.WriteLine("These are your dice:");
                die.Display();
            }
            else if (command == "roll")
            {
                Console.WriteLine("Here is your roll:");
            }
            else if (command == "clear")
            {
                Console.WriteLine("All dice have been cleared.");
            }
        } while (true);            
    }
    static int CheckDice(int sides)
    {
        List<int> check = new List<int> {4,6,8,10,12,20};
        while (!check.Contains(sides))
        {
            Console.WriteLine("{0}-sided dice are not available.\nPlease enter 4,6,8,10,12 or 20");
            sides = int.Parse(Console.ReadLine());                   
        }
           return sides;            
    }
    static string CheckCommand(string instructions)
    {
        List<string> check = new List<string> { "add", "remove", "dice", "roll","clear", "exit" };
        while (!check.Contains(instructions))
        {
            Console.WriteLine("Command not recognized.\nPlease enter \"add\", \"remove\", \"dice\", \"roll\",\"clear\", or \"exit\"");
            instructions = Console.ReadLine();
        }
        return instructions;
    }

    
}

Solution

  • New Answer based on comments and updated question:

    The line ManyDice die = new ManyDice(); is wiping your dice list clean every loop through your program. It's replacing your variable with a new instance of the class, with a fresh list and all.

    Simply move that line before the start of the loop:

    before the line do {

    and then every iteration will use the same instance of ManyDice, and will all share the variable die, without overwriting it.

    OLD ANSWER: From what I can see, your program only runs once. And then you need to start it again to put in another dice. Your main function only asks for input once. Whenever you start the program again, all the memory used in the program gets cleared. Unless I’m missing something, that is why your list continues to be reset. You’re actually running a completely new program the next time you try to add dice. So it has no knowledge of the previous runs.

    One solution is to say (pseudo code)

    While (running) {
         // what you have now
    
         if (option == “done”) running = false;
    
        if (option == “roll”) // roll all dice. 
    }
    

    This will keep prompting the user for commands until they type done. And it remains the same program so that you don’t lose the data from earlier commands.

    Update based on comment: you’re recreating the ManyDice instance on each iteration, effectively starting from scratch. Save the instance outside the while loop and then reuse it.

    Hint:

    Your rolling should probably be done by manyDice.RollAll() And maybe should return a List of RollResults.