So I have been working on this dice roller for a while but am stuck.

My form looks like this, a comboBox1 where you can pick numberOfSides on the dice, a textbox1 where you type the numberOfTimes it shall roll the selected dice, a button1 and a richTextBox1 to display the rolls.

My problem now is to call this with the button and display the results in the richTextBox1 side by side like this 4 12 8 14 before it breaks it to next line.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace Dice
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            comboBox1.DataSource = Enum.GetValues(typeof(DiceValue));
        }

        public enum DiceValue
        {
            [Description("3 sided die")] Three = 3,
            [Description("3 sided die")] Four = 4,
            [Description("3 sided die")] Five = 5,
            [Description("3 sided die")] Six = 6,
        }
    public class RollDice
    {
        public static Random rndGen = new Random((int)DateTime.Now.Ticks);

        public static int RandomDice(Int32 numberOfSides, Int32 numberOfTimes)
        {
            int total = 0;

            for (int i = 0; i < numberOfTimes; i++)
            {
                // Upperbound is exclusive so add 1 to the number of sides
                total = total + rndGen.Next(1, numberOfSides + 1);
            }
            return total;
        }
        }

    private void button1_Click(object sender, EventArgs e)
    {
        var numberOfSides = comboBox1.SelectedItem;

        var numberOfTimes = textBox1.Text;

        int result = RollDice.RandomDice(numberOfSides, numberOfTimes);
    }    
    }
}

I guess I need to make the textBox1 to a Int32.TryParse or some kind of int but where or how? Then this code on the button does not really feel right except the int result line. Could someone please help me with this?

Recommended Answers

All 11 Replies

Are you saying you want to:
1) show each of the generated numbers in the text box
or
2) show each TOTAL in the text box?

I want to show each dice roll, so if I pick 3 sided dice and enter 2 in the textbox I want it to roll that dice two times and write out the first roll and then the second roll but as the code is now I can't seem to understand how to call it on my button and get the results into my richTextBox1

I belive everything should be correct with my dice rolling generator and all it's just when it comes down to this button :(

Then in the end I would like to expand it with another box that displays the sum of the dice rolls but I thought I try to get to that after this problem was solved :)

So I decided to switch out my textBox1 that was numberOfTimes to roll box to a numericUpDown1 and I got the rolls to work "kinda"

    private void button1_Click(object sender, EventArgs e)
    {
        var numberOfSides = (int)comboBox1.SelectedValue;

        var numberOfTimes = (int)numericUpDown1.Value;

        int result = RollDice.RandomDice(numberOfSides, numberOfTimes);

        richTextBox1.Text = Convert.ToString(result);
    }

Problem is that it will only display 1 result and it's the total of all rolls in my richTextBox1. I want it to display each of all rolls, not the total :( What am I missing?

You are missing the part where you add the individual roll to the list (or array) of rolls.
Once you have done that, you can return the list of rolls.
You can then display the list of rolls as a string inside a text box using string.Join()

...but the first thing is saving the roll before it is added to the total.

You got me, how do I save each roll?

What you might want to consider doing is moving the logic of dice rolling into another class and keep the form as just a manipulator of that class.

So, you could have a DiceRollLogger class that has a method RollEm(), a method ClearHistory(), and a property taht allows you to access the history. Then, you can implement the logic of rolling a die and saving it off in memory in the class.

When you press a button on the form, you just need to call _logger.RollEm() and update the rich text box with the history.

I've included a sample project that shows how this could be done. Take a look if you want. The DiceRollLogger looks like this:

using System;
using System.Collections.Generic;
using System.Text;

namespace DiceRoller
{
    class DiceRollLogger
    {
        private List<DiceSides> _history = new List<DiceSides>();

        private Random _random = new Random();

        public DiceSides RollEm()
        {
            var values = Enum.GetValues(typeof(DiceSides));

            DiceSides result = DiceSides.One;
            if (!Enum.TryParse<DiceSides>( values.GetValue(_random.Next(values.Length)).ToString(), out result))
            {
                throw new Exception("Could not parse random value into dicesides");
            }

            _history.Add(result);

            return result;
        }

        public void ClearHistory()
        {
            _history.Clear();
        }

        public List<DiceSides> History
        {
            get
            {
                return _history;
            }
        }

        public string CSVHistory
        {
            get
            {
                var builder = new StringBuilder();

                for (var i = 0; i < _history.Count; i++ )
                {
                    builder.Append(Enum.Format(typeof(DiceSides), _history[i], "D"));

                    if (i < _history.Count - 1)
                    {
                        builder.Append(", ");
                    }
                }

                return builder.ToString();
            }
        }

    }
}

I have not fully tested this, but it returns an array of rolls based on the number of dice and the number of sides.

using System;
using System.Linq;

namespace TestCheapRoller
{
   public class CCheapRoller
   {
      private static Random _rnd = new Random((int)DateTime.Now.Ticks);
      public static int[] GetRoll(int intNumDice, int intNumSides)
      {
         return Enumerable.Range(0, intNumDice)
            .Select(i => _rnd.Next(1, intNumSides)).ToArray();
      }
   }

   class Program
   {
      static void Main(string[] args)
      {
         CCheapRoller.GetRoll(7, 6).ToList().ForEach(i => Console.WriteLine(i));
      }
   }
}

Here's how I would roll that 5 times.

using System;
using System.Linq;

namespace TestCheapRoller
{
   public class CCheapRoller
   {
      private static Random _rnd = new Random((int)DateTime.Now.Ticks);
      public static int[] GetRoll(int intNumDice, int intNumSides)
      {
         return Enumerable.Range(0, intNumDice)
            .Select(i => _rnd.Next(1, intNumSides)).ToArray();
      }
   }

   class Program
   {
      static void Main(string[] args)
      {
         Enumerable.Range(0, 5).ToList().ForEach(j =>
         {
            Console.WriteLine(string.Join(",",
                  CCheapRoller.GetRoll(7, 6).Select(i => i.ToString()).ToArray()));
         });
      }
   }
}

So basicly nothing that I wrote can be used to take get each die roll value out? All code suggestions I see here is a complete rewrite of what I have so far.

So capturing each roll inside my code is not possible at all? Been trying to think of a way to put in an array but no luck so far.

The best programmers I have ever worked with often take what they initially tried, throw it out, and start over. The initial version isn't a waste though, it is always necessary to learn what works and what doesn't work.

If you don't want to start over, if you just create a private list of ints on the form and then add to the list on every roll, you will have the saved. See below.

using System;
using System.Collections.Generic;
using System.ComponentModel;
namespace Dice
{
    public partial class Form1 : Form
    {
        private List<int> _results = new List<int>();

        public Form1()
        {
            InitializeComponent();
            comboBox1.DataSource = Enum.GetValues(typeof(DiceValue));
        }
        public enum DiceValue
        {
            [Description("3 sided die")]
            Three = 3,
            [Description("3 sided die")]
            Four = 4,
            [Description("3 sided die")]
            Five = 5,
            [Description("3 sided die")]
            Six = 6,
        }
        public class RollDice
        {
            public static Random rndGen = new Random((int)DateTime.Now.Ticks);
            public static int RandomDice(Int32 numberOfSides, Int32 numberOfTimes)
            {
                int total = 0;
                for (int i = 0; i < numberOfTimes; i++)
                {
                    // Upperbound is exclusive so add 1 to the number of sides
                    total = total + rndGen.Next(1, numberOfSides + 1);
                }
                return total;
            }
        }
        private void button1_Click(object sender, EventArgs e)
        {
            var numberOfSides = comboBox1.SelectedItem;
            var numberOfTimes = textBox1.Text;
            int result = RollDice.RandomDice(numberOfSides, numberOfTimes);

            _results.Add(result);

        }
    }
}
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.