How do I display random pictures (dice) on pygame and assign them a value?

Viewed 546

currently I am challenging myself over the summer to learn to code and I started on pygame. I am trying to make a program where you click the screen to roll a dice and compete with an opponent(the computer) to see who rolled the bigger number. I just have no clue how to display the dice. In theory if I click the screen my dice is shown on the top and the opponents on the bottom with text that tells which person rolled higher. I know this is probably a very complex and tedious question but I don't know where else to go so I greatly appreciate it. Here's my code for reference.

import pygame
import os
import time
import random


pygame.font.init()

WIDTH, HEIGHT = 750, 750
WIN = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Dice Game")


# Load images
Dice1 = pygame.image.load(os.path.join("assets", "Dice1.png"))
Dice2 = pygame.image.load(os.path.join("assets", "Dice2.png"))
Dice3 = pygame.image.load(os.path.join("assets", "Dice3.png"))
Dice4 = pygame.image.load(os.path.join("assets", "Dice4.png"))
Dice5 = pygame.image.load(os.path.join("assets", "Dice5.png"))
Dice6 = pygame.image.load(os.path.join("assets", "Dice6.png"))



# Background
BG = pygame.transform.scale(pygame.image.load(os.path.join("assets", "GameBoard1.png")), (WIDTH, 
HEIGHT))

pygame.display.set_icon(Dice6)

def main():

running = True
FPS = 60
clock = pygame.time.Clock()

def redraw_window():
    WIN.blit(BG, (0,0))
    pygame.display.update()
    while running:
        clock.tick(FPS)
        redraw_window()

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                quit()
def dice():

player = random.randint(Dice1, Dice2, Dice3, Dice4, Dice5, Dice6)
pygame.blit(player, (WIDTH/2 + 50))

opponent = random.randit(Dice1, Dice2, Dice3, Dice4, Dice5, Dice6)
pygame.blit(opponent, (WIDTH/2 - 50))

opponent = random.randint(0, 5)
if opponent > player:
    print(f"opponent won. They rolled a {opponent}")
elif opponent < player:
    print(f"You win! They rolled a {opponent}")

elif opponent == player:
    print("tied!")

def main_menu():
title_font = pygame.font.SysFont("comicsans", 70)
running = True
while running:
    WIN.blit(BG, (0, 0))
    title_label = title_font.render("Would You like to roll? Y/N", 1, (255, 255, 255))
    WIN.blit(title_label, (WIDTH/2 - title_label.get_width()/2, 350))
    pygame.display.update()
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        if event.type == pygame.K_y:
            main()
pygame.quit()

main_menu()

1 Answers

Your code is a bit mixed up! It looks like there was trouble during pasting, and there's also a couple of syntax issues. So I've taken what I can from it, and re-worked it back into a reasonably readable example.

So basically you need to generate random numbers representing a dice-face (die-face?), and show the user a bitmap representation of that face.

The call to random.randint() looked like you were attempting to call something like random.choice(). In this case you wanted something like:

random.choice( [ dice1, dice2, dice3, ... dice6 ] )

But since we're just dealing with numbers:

random.randint( 1, 6 )

Is simpler. Some of the python random functions return a result (0 → N-1) so you need to be a little careful of this. Otherwise your random number range might gave been 1 → 5.

So in this dice game it seems we need a roll for the player, and the opponent. I modified your dice() function to simply generate two random numbers and return them:

def rollDice():
    player_roll   = random.randint( 1, 6 )
    opponent_roll = random.randint( 1, 6 )

    return player_roll, opponent_roll

This allows us to write:

    elif event.type == pygame.KEYDOWN:               # when a key is pressed
        if event.key == pygame.K_y:                  #  and that key is [y]
            player_roll, opponent_roll = rollDice()  # Get a new set of dice rolls

Where player_roll and opponent_roll will be random numbers between 1 and 6 (inclusive).

Once the dice are rolled, the result needs to be put on the screen. Your code already has the the images Dice1, Dice2, ... Dice6. I took these and put them into a list (de-capitalised to meet PEP-8):

all_dice = [ None, dice1, dice2, dice3, dice4, dice5, dice6 ]

This allows the code to lookup which image to use by the number in the player_roll variable. So if player_roll is 1, the code can say all_dice[player_roll] and get the bitmap dice1. Obviously the first item in a list is index-0, and there's no zero-face, so we just put None at index-0.

So this list is just an easier way to pick the correct image, rather than a 12-line list of:

if player_roll == 1:
    dice_face = dice1
elif  player_roll == 2:
    dice_face = dice2
...  too much code!

So this allows the code to have:

if event.key == pygame.K_y:
    player_roll, opponent_roll = rollDice()       # get a pair of numbers
    player_face   = all_dice[ player_roll ]       # Player dice bitmap
    opponent_face = all_dice[ opponent_roll ]     # Opponent dice bitmap

This may seem like an unnecessary bit of complication, but what about when your program is extended to use 20-sided dice!? I wouldn't want to type out another 28 lines worth of if..elifs. And what about 100-sided dice!

So, once you have a bitmap, this can be painted to the window with the Surface.blit() function, same as you already coded with the background image:

# Paint the dice faces
if ( player_face != None ):
    window.blit( player_face, ( QUARTER_WIDTH, MIDDLE_HEIGHT ) )
if ( opponent_face != None ):
    window.blit( opponent_face, ( 3*QUARTER_WIDTH, MIDDLE_HEIGHT ) )

dice game example

Dice-face images used from: http://www.clker.com/clipart-7188.html (permissive licence)

Reference Code:

import pygame
import random
import os
import os.path

WIDTH  = 750
HEIGHT = 750
FPS    = 60
QUARTER_WIDTH = WIDTH//4
MIDDLE_HEIGHT = HEIGHT//2

pygame.init()
pygame.font.init()
window = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Dice Game")

# Fonts and Text
title_font  = pygame.font.SysFont("comicsans", 70)
title_label = title_font.render("Would You like to roll? Y/N", 1, (255, 255, 255))

# Load images
dice1 = pygame.image.load(os.path.join("assets", "dice_1.png"))
dice2 = pygame.image.load(os.path.join("assets", "dice_2.png"))
dice3 = pygame.image.load(os.path.join("assets", "dice_3.png"))
dice4 = pygame.image.load(os.path.join("assets", "dice_4.png"))
dice5 = pygame.image.load(os.path.join("assets", "dice_5.png"))
dice6 = pygame.image.load(os.path.join("assets", "dice_6.png"))
 
# Indexed list to reference all the faces
all_dice = [ None, dice1, dice2, dice3, dice4, dice5, dice6 ]
pygame.display.set_icon( dice6 )

# Game Background
background = pygame.transform.scale(pygame.image.load(os.path.join("assets", "dice_board.png")), (WIDTH, HEIGHT))

               
### Function to perform the random parts of the game               
def rollDice():
    """ Generate the two random numbers, one for the Player and Opponent """
    player_roll   = random.randint( 1, 6 )
    opponent_roll = random.randint( 1, 6 )

    return player_roll, opponent_roll



### Main Loop
clock         = pygame.time.Clock()
running       = True
player_face   = None  # No dice before first roll
player_roll   = 0
opponent_face = None  # No dice before first roll
player_roll   = 0
while running:

    # handle user input
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_y:
                player_roll, opponent_roll = rollDice()
                player_face   = all_dice[ player_roll ]
                opponent_face = all_dice[ opponent_roll ]

                # Debug prints
                if opponent_roll > player_roll:
                    print(f"opponent won. They rolled a {opponent_roll}")
                elif opponent_roll < player_roll:
                    print(f"You win! They rolled a {opponent_roll}")
                elif opponent_roll == player_roll:
                    print("tied!")

    # Reapint the screen
    window.blit( background, (0, 0))
    window.blit(title_label, (WIDTH//2 - title_label.get_width()//2, 250))
    
    # Paint the dice faces
    if ( player_face != None ):
        window.blit( player_face, ( QUARTER_WIDTH, MIDDLE_HEIGHT ) )
    if ( opponent_face != None ):
        window.blit( opponent_face, ( 3*QUARTER_WIDTH, MIDDLE_HEIGHT ) )
    
    # flush display changes
    pygame.display.flip()
            
    # Constrain FPS
    clock.tick( FPS )

pygame.quit()
Related