C# Dice Roll Code with Stats
This article provides some C# dice rolling code (with some dice images and a dice rolling sound). It has an easy to use C# dice class. The dice rolling class can be used when developing a simple C# dice game, or for any code that needs one or more dice. This includes using the code for a dice rolling simulator, demonstrating C# random number and probability concepts, or just needing a C# dice roll method for a program. The dice class collects some stats on the rolls performed. This can be useful for some applications.
Note: It is correct to say one die and two dice, but it is common to use dice for singular and plural. That's what this article will do.
To skip the tutorial part of the article, scroll down to all the source code at the end of the article. There is a download of the C# dice roll app code as a zip file. The code includes a Visual Studio (VS) solution. The C# code in this article was developed using Microsoft Visual Studio Community 2019.
Note: When you download VS files from the Internet, Windows may block their use due to security concerns. This may cause a message to display, for example, that a file has a mark of the web. This will need removing via the properties of the file. Use Windows File Explorer to open the file's properties and unblock the file. This may need to be done for multiple files.
Use a C# Windows Forms Application for the Dice Roll Code
This tutorial will use a single Form
Windows application with a C# dice class
. Start a new C# Windows Form Application in VS. If you need to get started with VS see the Tek Eye article Hello World in C#, A Starting WinForms Example. For this tutorial the VS solution and C# project was called Dice_Roll. The starting form was renamed from Form1 to FrmDiceRoll, and the form's Text
set to Dice Rolling Simulator.
The User Interface (UI) to test the dice roll code is shown above. This can be created by dragging controls from the Toolbox in VS onto the starting form. Alternatively, download the code in the provided zip file and open the solution in VS to browse the code. For this tutorial a GroupBox
was added to the form, a PictureBox
was dropped onto the GroupBox, along with twenty labels to display the dice class stats. The PictureBox displays a dice face image matching the value rolled. The GroupBox was then copied and pasted on the form and edited to create the UI for the second dice. The second GroupBox's Visible
property is set to false
as the application can roll one or two dice, but starts with one.
A CheckBox
determines if one or two dice are displayed. When checked it makes the second GroupBox's visible property true
(and false again when unchecked). A Button
is added to perform the dice roll, clicking the dice images will also perform the dice roll.
The Dice Rolling C# Class
A C# class contains all the code needed for a dice roll. The Dice class is added to the project (if not familiar with adding a class file use the Project and Add Class menu option). If your application requires only one dice then it can be made a static class. Four class variables are needed, a long
array to hold a count of each number rolled, an instance of the Random
class to generate the random values of the dice roll, and two integers to hold the rolled numbers, and the previously rolled number:
public class Dice
{
//Store number of rolls of each number
long[] rolls = { 0, 0, 0, 0, 0, 0 };
//Use random for rolling
readonly Random roller = new Random();
//Store the last rolled number
int lastRoll = 0;
//Store the previously rolled number
int previousRoll = 0;
}
The Dice class has a RollNumber method to perform the dice roll, added before the closing bracket. It saves the last roll to the previous roll integer, calls the Next method on the random class to generate the dice roll, and updates the number counts in the long array:
public int RollNumber()
{
//Save previous number
previousRoll = lastRoll;
//Roll the dice (die!)
lastRoll = roller.Next(0, 6) + 1;
//Update all rolls
rolls[lastRoll - 1]++;
return lastRoll;
}
The remaining properties and methods retrieve the rolled number, previous number and various stats. Here, using Linq notation (add using System.Linq; to the top of the class file):
//Get last rolled number
public int LastRoll => lastRoll;
The above is the same as:
//Get last rolled number
public int LastRoll()
{
return lastRoll;
}
The same for the previous rolled value and the counts of the rolls.
//Get previous rolled number
public int PreviousRoll => previousRoll;
//Totals of each number rolled
public long[] Rolls => rolls;
The total number of rolls performed is the sum of each number rolled (returned using a Linq expression):
//Total of all rolls performed
public long TotalRolls => rolls.Sum();
Storing the count of each number rolled allows the totals for each number can be calculated using Linq:
//Total value of all rolled numbers
public long[] TotalsOfRolledNumbers => rolls.Select((number, index) => number * (index + 1)).ToArray();
Where Select
stores the rolls array value in number and its index in index for each rolls entry, and for each entry performs the calculation number * (index + 1). This calculation produces the total value of that number's rolls (e.g. if 2 is rolled twice, stored in roll[1], then the calculation is 2 * (1 + 1), which is 4, i.e. 2 rolled twice. The ToArray is needed because Select returns an IEnumerable
.
Having calculated the totals of rolled numbers, the grand total and mean value can be calculated:
//Total of all values rolled
public long TotalValues => TotalsOfRolledNumbers.Sum();
//Mean number rolled (double cast required to prevent integer only division)
public double MeanValueRolled => TotalValues / (double)TotalRolls;
Loading the Dice Face Images and Dice Rolling Sound
The images used for the dice faces, and the dice rolling sound, are the same resources used in the Tek Eye article Android Dice Roller Source Code for Apps. The dice code in this tutorial is for a common six sided dice, each side of the cube (each face) has one of the numbers from one to six. Here six PNG images are used to show the dice roll result. Plus, there is a 3D image shown when the dice is rolled. The same 3D image is used for the app icon. The dice images are from Open Clip Art Library user rg1024.
The sound of a dice roll is by Mike Koenig and is from SoundBilble.com. However, the dice rolling sound has been converted from a MP3 to a Windows WAV file for the SoundPlayer class. The sound file and dice images are all added to the project and the Build Action set to Embedded Resource, meaning they will be added to the final executable file.
A Bitmap
array stores the images and the SoundPlayer is created at the module level in the form:
//Dice faces
Bitmap[] faces = new Bitmap[7]; //includes an image for rolling
SoundPlayer play = new SoundPlayer(); //For the dice roll sound
In the form constructor the dice images are loaded and the SoundPlayer configured with the WAV file. The images and sound files are in the same directory as the app's project file. The name of a media file then follows the apps namespace (Dice_Roll in this case), e.g., for one.png, the name of the image for the first face of the dice, it is referenced as Dice_Roll.one.png. A 3d dice is displayed when the dice is rolled (using dice3d160.png).
public FrmDiceRoll()
{
InitializeComponent();
//Load images for the dice
Assembly prog = Assembly.GetExecutingAssembly();
faces[0] = new Bitmap(prog.GetManifestResourceStream("Dice_Roll.dice3d160.png"));
faces[1] = new Bitmap(prog.GetManifestResourceStream("Dice_Roll.one.png"));
faces[2] = new Bitmap(prog.GetManifestResourceStream("Dice_Roll.two.png"));
faces[3] = new Bitmap(prog.GetManifestResourceStream("Dice_Roll.three.png"));
faces[4] = new Bitmap(prog.GetManifestResourceStream("Dice_Roll.four.png"));
faces[5] = new Bitmap(prog.GetManifestResourceStream("Dice_Roll.five.png"));
faces[6] = new Bitmap(prog.GetManifestResourceStream("Dice_Roll.six.png"));
//Load sound file
play.Stream = prog.GetManifestResourceStream("Dice_Roll.shake_dice.wav");
}
The top of the form file has System.Media and System.Reflection added:
using System.Media;
using System.Reflection;
When the form loads the two picture boxes (here called PBDice1 and PBDice2) are used to show the roll results, they are initialised with a dice roll image:
private void FrmDiceRoll_Load(object sender, EventArgs e)
{
//Put an image in the picture box to start
PBDice1.Image = faces[0];
PBDice2.Image = faces[0];
}
Rolling the Dice and Displaying the Result
In this tutorial one or two dice can be rolled, therefore, two instances of the dice class are required. The dice class can be declared for as many dice as required for your application. A long variable is used to count rolled doubles.
Dice dice1 = new Dice();
Dice dice2 = new Dice();
static long doubles = 0; //Count doubles when two dice
The dice can then be rolled and the number displayed.
//Roll the dice
private void ButRoll_Click(object sender, EventArgs e)
{
//Dice sound
play.Play();
//Roll the dice and update display
PBDice1.Image = faces[dice1.RollNumber()];
}
Using Async and Await to Enable UI Feedback
Ideally, when the dice is rolled the 3D dice image is displayed to show the roll taking place:
//Clear previous roll image
PBDice1.Image = faces[0];
//Dice sound
play.Play();
//Roll the dice and update display
PBDice1.Image = faces[dice1.RollNumber()];
However, this will not work as the UI thread cannot update the picture box whilst the new roll is executed. To overcome this issue the roll is performed on another thread using async
and await
. The new async roll method inserts a short delay to ensure the user sees the 3D dice image:
//Background roll, with pause, to allow a UI change
private async Task<int> Roll()
{
//Brief pause
await Task.Delay(500);
//Roll dice
return dice1.RollNumber();
}
The roll button click is updated to support the async and await:
//Roll the dice
private async void ButRoll_Click(object sender, EventArgs e)
{
//Clear previous roll image
PBDice1.Image = faces[0];
//Dice sound
play.Play();
//Roll the dice and update display
PBDice1.Image = faces[await dice1.RollNumber()];
}
Full C# Dice Rolling App Code
The full code for the dice rolling app can be downloaded as a zip file for opening in VS. The code shown her does not include the form designer code. If reproducing the dice app form yourself see the app screen at the top of the article for the layout. The names of the controls will need to be set appropriately (see the UpdateStats() function).
The dice roll class code covers all the basic functionality of a dice, and can be adapted for other dice sizes:
using System;
using System.Linq;
namespace Dice_Roll
{
public class Dice
{
//Store number of rolls of each number
long[] rolls = { 0, 0, 0, 0, 0, 0 };
//Use random for rolling
readonly Random roller = new Random();
//Store the last rolled number
int lastRoll = 0;
//Store the previously rolled number
int previousRoll = 0;
//Perform a dice roll
public int RollNumber()
{
//Save previous number
previousRoll = lastRoll;
//Roll the dice (die!)
lastRoll = roller.Next(0, 6) + 1;
//Update all rolls
rolls[lastRoll - 1]++;
return lastRoll;
}
//Get last rolled number
public int LastRoll => lastRoll;
//Get previous rolled number
public int PreviousRoll => previousRoll;
//Totals of each number rolled
public long[] Rolls => rolls;
//Total of all rolls performed
public long TotalRolls => rolls.Sum();
//Total value of all rolled numbers
public long[] TotalsOfRolledNumbers => rolls.Select((number, index) => number * (index + 1)).ToArray();
//Total of all values rolled
public long TotalValues => TotalsOfRolledNumbers.Sum();
//Mean number rolled (double cast required to prevent integer only division)
public double MeanValueRolled => TotalValues / (double)TotalRolls;
}
}
The app's form includes options for one or two dice, the click function for the roll button can be assigned to the picture boxes click function to enable a dice roll by clicking the dice images:
using System;
using System.Drawing;
using System.Media;
using System.Reflection;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Dice_Roll
{
public partial class FrmDiceRoll : Form
{
//Dice faces
Bitmap[] faces = new Bitmap[7]; //includes an image for rolling
SoundPlayer play = new SoundPlayer(); //For the dice roll sound
//Supports two dice
Dice dice1 = new Dice();
Dice dice2 = new Dice();
static long doubles = 0; //Count doubles when two dice
public FrmDiceRoll()
{
InitializeComponent();
//Load images for the dice
Assembly prog = Assembly.GetExecutingAssembly();
faces[0] = new Bitmap(prog.GetManifestResourceStream("Dice_Roll.dice3d160.png"));
faces[1] = new Bitmap(prog.GetManifestResourceStream("Dice_Roll.one.png"));
faces[2] = new Bitmap(prog.GetManifestResourceStream("Dice_Roll.two.png"));
faces[3] = new Bitmap(prog.GetManifestResourceStream("Dice_Roll.three.png"));
faces[4] = new Bitmap(prog.GetManifestResourceStream("Dice_Roll.four.png"));
faces[5] = new Bitmap(prog.GetManifestResourceStream("Dice_Roll.five.png"));
faces[6] = new Bitmap(prog.GetManifestResourceStream("Dice_Roll.six.png"));
//Load sound file
play.Stream = prog.GetManifestResourceStream("Dice_Roll.shake_dice.wav");
}
private void FrmDiceRoll_Load(object sender, EventArgs e)
{
//Put an image in the picture box to start
PBDice1.Image = faces[0];
PBDice2.Image = faces[0];
}
//Roll the dice
private async void ButRoll_Click(object sender, EventArgs e)
{
//Only one roll at a time
ButRoll.Enabled = false;
PBDice1.Enabled = false;
PBDice2.Enabled = false;
//Clear previous roll image
PBDice1.Image = faces[0];
if (ChkOneOrTwo.Checked)
//Roll dice two as well
PBDice2.Image = faces[0];
//Dice sound
play.Play();
//Roll the dice and update display
PBDice1.Image = faces[await Roll()];
if(ChkOneOrTwo.Checked)
//Roll dice two as well
PBDice2.Image = faces[dice2.RollNumber()];
UpdateStats();
//Can roll again
PBDice2.Enabled = true;
PBDice1.Enabled = true;
ButRoll.Enabled = true;
}
//Background roll, with pause, to allow a UI change
private async Task<int> Roll()
{
//Brief pause
await Task.Delay(500);
//Roll dice
return dice1.RollNumber();
}
//Update the various stats available
void UpdateStats()
{
LblTotalNumRolls1.Text = dice1.TotalRolls.ToString();
LblOnes1.Text = dice1.Rolls[0].ToString();
LblTwos1.Text = dice1.Rolls[1].ToString();
LblThrees1.Text = dice1.Rolls[2].ToString();
LblFours1.Text = dice1.Rolls[3].ToString();
LblFives1.Text = dice1.Rolls[4].ToString();
LbLSixes1.Text = dice1.Rolls[5].ToString();
LblSumRolls1.Text = dice1.TotalValues.ToString();
LblMeanValue1.Text = dice1.MeanValueRolled.ToString();
LblPreviousRoll1.Text = dice1.PreviousRoll.ToString();
//See if two dice are being rolled
if (ChkOneOrTwo.Checked)
{
//Update Dice Two Stats
LblTotalNumRolls2.Text = dice2.TotalRolls.ToString();
LblOnes2.Text = dice2.Rolls[0].ToString();
LblTwos2.Text = dice2.Rolls[1].ToString();
LblThrees2.Text = dice2.Rolls[2].ToString();
LblFours2.Text = dice2.Rolls[3].ToString();
LblFives2.Text = dice2.Rolls[4].ToString();
LblSixes2.Text = dice2.Rolls[5].ToString();
LblSumRolls2.Text = dice2.TotalValues.ToString();
LblMeanValue2.Text = dice2.MeanValueRolled.ToString();
LblPreviousRoll2.Text = dice2.PreviousRoll.ToString();
if (dice1.LastRoll == dice2.LastRoll)
LblTotalDoubles.Text= (++doubles).ToString();
}
}
//Show second dice?
private void ChkOneOrTwo_CheckedChanged(object sender, EventArgs e)
{
if (ChkOneOrTwo.Checked)
GrpDice2.Visible = true;
else
GrpDice2.Visible = false;
}
}
}
See Also
- The example project and source code as a zip file
- For a full list of the articles on Tek Eye see the website's index
Author:Daniel S. Fowler Published: