Develop a Dice Roll Simulator



So, it’s tabletop RPG night, and everyone else has their bag of dice, and you bring out—your laptop? Well, it’s a perfect time to show off that dice roll simulator you built in Python. This beginner project should teach you the basics of dice rolls and randomization.




Setting Up Our Project

This is going to be a pretty simple setup. I’ve already described how we set up Visual Studio for coding with Python, so we’ll use that for our basic setup. We’ll keep this as simple as possible, so we’ll start with our imports:

import tkinter as tk
from tkinter import ttk
import random

We used Tkinter before when we built our simple expense tracker; in this case, it’s the lightest solution. The library allows us to create a simple, modern, yet stylish GUI interface. The random library allows us the functionality for randomizing numbers between two values, which is the essence of a die roll. Let’s make things a little prettier.

Design Considerations With Our Dice Faces

We’re going to simulate a set of RPG dice. For stylistic flair, I made the four-sided dice (d4) and the six-sided dice (d6) a bit fancy to demonstrate ASCII art handling with Tkinter.


def __init__(self, root):
        self.root = root
        self.root.title("Dice Simulator")
        self.root.geometry("400x500")
        
        
        self.d4_faces = {
            1: " ╱▲╲\n ╱ 1 ╲\n╱ ╲\n",
            2: " ╱▲╲\n ╱ 2 ╲\n╱ ╲\n",
            3: " ╱▲╲\n ╱ 3 ╲\n╱ ╲\n",
            4: " ╱▲╲\n ╱ 4 ╲\n╱ ╲\n"
        }
        
        self.d6_faces = {
            1: "┌─────────┐\n│ │\n│ ● │\n│ │\n└─────────┘",
            2: "┌─────────┐\n│ ● │\n│ │\n│ ● │\n└─────────┘",
            3: "┌─────────┐\n│ ● │\n│ ● │\n│ ● │\n└─────────┘",
            4: "┌─────────┐\n│ ● ● │\n│ │\n│ ● ● │\n└─────────┘",
            5: "┌─────────┐\n│ ● ● │\n│ ● │\n│ ● ● │\n└─────────┘",
            6: "┌─────────┐\n│ ● ● │\n│ ● ● │\n│ ● ● │\n└─────────┘"
        }

I opted for this because I felt a GUI would be a lot more enticing. When we did our quiz app, we stuck to the terminal, but I’d like a little bit of flair in this app. Don’t get too worried about this piece of code. All it does is display our d6 with a face like an actual d6, and the same for a d4. This is also the start of our GUI, with the app title of “Dice Simulator” shown at the top of the window. Let’s look at how we’re going to do our input.

We want a place for the user to enter the number and type of dice they want to roll. To keep things simple, we’ll be maxing out the dice at five, so anything more than that we won’t handle. Our user interface will, therefore, have a die selector (for the dice type) and a number of dice entries if we’re rolling more than one.

I also want to implement a history system for our rolls, so I’ll put that in at the bottom and update it every time we roll a new set of dice. Our code snippet should look something like this:

        
        self.main_frame = ttk.Frame(self.root, padding="10")
        self.main_frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))

        
        ttk.Label(self.main_frame, text="Number of Dice:").grid(row=0, column=0, pady=5)
        self.num_dice = ttk.Spinbox(self.main_frame, from_=1, to=5, width=5)
        self.num_dice.set(1)
        self.num_dice.grid(row=0, column=1, pady=5)

        
        ttk.Label(self.main_frame, text="Dice Type:").grid(row=1, column=0, pady=5)
        self.dice_type = ttk.Combobox(self.main_frame, values=["d4", "d6", "d8", "d12", "d20"], width=5)
        self.dice_type.set("d6")
        self.dice_type.grid(row=1, column=1, pady=5)

        
        self.roll_button = ttk.Button(self.main_frame, text="Roll Dice!", command=self.roll_dice)
        self.roll_button.grid(row=2, column=0, columnspan=2, pady=10)

        
        self.result_text = tk.Text(self.main_frame, height=15, width=40, font=('Courier', 10))
        self.result_text.grid(row=3, column=0, columnspan=2, pady=10)

        
        ttk.Label(self.main_frame, text="Roll History:").grid(row=4, column=0, columnspan=2, pady=5)
        self.history_text = tk.Text(self.main_frame, height=5, width=40)
        self.history_text.grid(row=5, column=0, columnspan=2, pady=5)

        self.roll_history = []
        
        self.main_frame = ttk.Frame(self.root, padding="10")
        self.main_frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))

        
        ttk.Label(self.main_frame, text="Number of Dice:").grid(row=0, column=0, pady=5)
        self.num_dice = ttk.Spinbox(self.main_frame, from_=1, to=5, width=5)
        self.num_dice.set(1)
        self.num_dice.grid(row=0, column=1, pady=5)

        
        ttk.Label(self.main_frame, text="Dice Type:").grid(row=1, column=0, pady=5)
        self.dice_type = ttk.Combobox(self.main_frame, values=["d4", "d6", "d8", "d12", "d20"], width=5)
        self.dice_type.set("d6")
        self.dice_type.grid(row=1, column=1, pady=5)

        
        self.roll_button = ttk.Button(self.main_frame, text="Roll Dice!", command=self.roll_dice)
        self.roll_button.grid(row=2, column=0, columnspan=2, pady=10)

        
        self.result_text = tk.Text(self.main_frame, height=15, width=40, font=('Courier', 10))
        self.result_text.grid(row=3, column=0, columnspan=2, pady=10)

        
        ttk.Label(self.main_frame, text="Roll History:").grid(row=4, column=0, columnspan=2, pady=5)
        self.history_text = tk.Text(self.main_frame, height=5, width=40)
        self.history_text.grid(row=5, column=0, columnspan=2, pady=5)

        self.roll_history = []

This gives us a basic UI setup for our dice-rolling app. Let’s move on to simulating the rolls.


Rolling Dice Through a Computer

If you’ve ever played any RPG video game, you’ve experienced simulated dice rolls. Dice shape how tabletop RPGs play, their ebbs and flows and what happens to characters. A die roll is a randomized number produced between two values, minimum and maximum. In Python, we can use the random library to simulate those rolls. Here’s our code:

    def roll_single_die(self, sides):
        """Simulate rolling a single die with given number of sides."""
        return random.randint(1, sides)

    def get_dice_face(self, value, dice_type):
        """Get ASCII art representation of a die face."""
        if dice_type == 4:
            return self.d4_faces.get(value, str(value))
        elif dice_type == 6:
            return self.d6_faces.get(value, str(value))
        return str(value)

    def roll_dice(self):
        """Handle the dice rolling action and update the display."""
        try:
            num_dice = int(self.num_dice.get())
            dice_type = int(self.dice_type.get()[1:])
            
            
            self.result_text.delete(1.0, tk.END)
            
            
            rolls = [self.roll_single_die(dice_type) for _ in range(num_dice)]
            total = sum(rolls)
            
            
            if dice_type in [4, 6]:
                for roll in rolls:
                    self.result_text.insert(tk.END, self.get_dice_face(roll, dice_type) + "\n")
            else:
                roll_str = ", ".join(str(roll) for roll in rolls)
                self.result_text.insert(tk.END, f"Rolls: {roll_str}\n")
            
            self.result_text.insert(tk.END, f"\nTotal: {total}")
            
            
            roll_record = f"{num_dice}d{dice_type}: {rolls} = {total}"
            self.roll_history.append(roll_record)
            if len(self.roll_history) > 5:
                self.roll_history.pop(0)
            
            
            self.history_text.delete(1.0, tk.END)
            for record in self.roll_history:
                self.history_text.insert(tk.END, record + "\n")

        except ValueError:
            self.result_text.delete(1.0, tk.END)
            self.result_text.insert(tk.END, "Please enter valid numbers")

This provides us with the basic code for simulating our dice rolls. To make the program run, we just need to call our core function:

if __name__ == "__main__":
    root = tk.Tk()
    app = DiceSimulator(root)
    root.mainloop()

And that should do it. We now have a dice roll simulator!

Suggestions for Upgrades and Updates

When you run the app, you should see something like this:


The app has a few limitations that I intentionally left out to offer you something to expand the app with. There’s no support for d10s or d100s (which can be simulated by either rolling 2d10 or rolling 1d100). You can add those yourself if you want to expand the app. Additionally, you could extend this into a networked dice roller and make the UI a bit prettier with some skinning. As usual, all the code for this app is available on my GitHub. Any comments about the code or my approach are always welcome.



Source link

Previous articleMobvoi Home Walking Treadmill review: the smart features stressed me out
Next articleUnifyDrive UT2 review: pocket-sized powerhouse