Python Tkinter Tutorial: build a jumbled words game from scratch

Aug 07, 2020 - 9 min read
Pratik Shukla
editor-page-cover


This article is part of a Python Tkinter series written by Pratik Shukla. Check out his Medium account to read his other articles. And stay tuned for more Tkinker articles from Pratik!

This series aims to introduce you to Tkinter, Python’s standard interface to the Tk GUI toolkit, and help you build interactive games you can add to your resume. To get up to speed on Tkinter, go read our first article in this series Python Tkinter Tutorial: build a number guessing game. Once you get down the basics, come back here to build a jumbled words game from scratch!

Today, we will cover:


Jumbled words game walkthrough

In this article, we’ll develop a cool game in which our program will generate jumbled words from the list of words provided. The user has to guess the actual word from the jumbled word. Our program will also count the amount of time taken to guess the correct word. Here we will use Tkinter module of python to use different widgets like entry, label, and button.


How to play

  • Run the program.
  • Enter your guess from jumbled word.
  • Check the result.
  • Play again or close.

Walkthrough

When the user runs the program, the user will see a jumbled word on the Tkinter window. Now the user has to guess the actual word from the jumbled word provided and enter their guess in the entry widget. Now, to check if the guessed word was correct, the user has to press the check button.

If the guessed word is correct, the label will transform its image to Win and the correct word will be shown to user. Our program will also show us the time taken by the user to guess the correct word.

If the user’s guess is wrong, then label will show a Lose image, and the entry widget will be cleared for to enter the word again. Our program will not show the correct word or time taken if the user’s guess is wrong.

If the user wants to play the game again, they wait for 3 seconds, and the new window will open with new word. If the user wants to terminate the game, they have to press the close button on the window. Our program will also play different sound files on various events.


Row-column representation in Tkinter

Final Result

1. This is the first screen the user will see when they run the program.

1 of 3


Implementation in Python (12 steps)

Now that we have a sense of what the jumbled words game will entail, let’s walk step-by-step through the process in Python. If you don’t yet know how to set up Tkinter, check out our first article in this series for a brief tutorial.


1. Import required libraries

#Import required libraries
from tkinter import *
import simpleaudio as sa 
import random
import tkinter.font as font
import time
  • tkinter: To add widgets in our application
  • simpleaudio: To play the sound files
  • random: To select a random word
  • tkinter.font: To change the properties of font
  • time: To calculate the time taken by user

2. Create main tkinter window

running = True

while running==True:
  #Calculate starting time
  start_time = time.time()

  root = Tk()
  root.geometry('+100+0')
  root.configure(bg="#000000")
  root.iconphoto(True,PhotoImage(file="Surprise.png"))
  root.title("JUMBLE WORDS")
  root.resizable(width=False,height=False)
  • First we create a variable called running and set its value to True. Our program will generate a new window when the variable is set to True. When the user presses the main close button in title bar, it will exit the loop.
  • root = Tk( ): This is used to initialize our tkinter module.
  • root.title( ): We use it to set the title for our application.
  • root.geometry( ): We use this to specify at which location our application window will open. In our case, it will open at 100 points to the left and 0 points to the down from the top-left corner.
  • root.configure( ): We use this to specify the background color for our application. In our case the background color will be black.
  • root.resizable( ): Here we are using it to prevent the users from resizing our main window.
  • root.iconphoto( ): We are using it to set the icon in the title bar for our application window. We are setting the first parameter to True, so that will ensure that all the other windows created from this application has the same icon.
  • Here we’re also creating a variable called start time, which stores the time value when the window was opened.

3. Loading sound files

#Load sound files
start = sa.WaveObject.from_wave_file("Start.wav")
one = sa.WaveObject.from_wave_file("Win.wav")
two = sa.WaveObject.from_wave_file("Lose.wav")
three = sa.WaveObject.from_wave_file("6.wav")

start.play()

Now we will use some sound files that will play at various events. When our program starts it will play start file. We’ll play the other three files when the user’s guess is correct, when the user’s guess is wrong and when user closes the application respectively.

One thing to notice is that it only accepts .wav files. First of all we need to load the sound file as an object. Then we can play it using .play( ) method when required.


4. Select a word randomly

#select a word from list
def random_word():
  words=["RAIN","CLOUD","NATURE","BEAUTIFUL","HOUSE"]
  pick = random.choice(words)
  return pick

This function will select a word randomly from the list of words provided. It can contain as many words as you want. The random.choice( ) method randomly selects a word from of list of word. Then we’ll return that word to use it in other functions.


5. Jumble the selected word

# Jumble the selected word
def jumbled_word(word):
  word = ranom.sample(word,len(word))
  word_jumbled = "".join(word)
  return word_jumbled

Now that our program has selected a word, we need to jumble it for our game. This function takes into input the word selected by our previous function. The random.sample( ) function takes a word, jumbles it, and gives list of letters. We can specify the length of the word, but in our case, it’ll be same as the original word. Then we need to join the jumbled letters to make a string. Finally, it will return the jumbled word so that we can use it in next function.


6. Arrange the letters

# Randmoly selected word
pick = random_word()

# Jumbled word
jumbled = jumbled_word(pick)

# Get the letters from the jumbled word
list1 = list(jumbled)
len_list1 = len(list1)

# Get the Images for our letters
for i in range(len_list1):
  list1[i] = PhotoImage(file=str(list1[i])+str("_P.png"))

row_0 = 0
col_0 = 0
 
# Arrange the letters on the main window
for i in range(len_list1):
  B = Label(root,image=list1[i])
  B.grid(row=row_0,column=col_0)
  col_0 = col_0 + 1
  • The randomly selected word will be stored in pick variable.
  • The jumbled word will be stored in jumbled variable.
  • List1 will convert our string into a list of letters. len_list1 gives us the length of the word.
  • Then we load the images for our letters. Our images are stored as A_P.png, B_P.png, C_P.png, and so on.
  • We want the letter images to show as label and it should be on one row. We’ll increase the column values as new letter arrives. The final result will be the jumbled word represented as labels of images.

7. Load other required images

# Blank space for row_1
root.gird_rowconfigure(1, minsize=10)

# Modify font
myFont = font.Font(family='Calibri', weight='bold')

# For label image
your_choice = PhotoImage(file"YOUR_GUESS.png")
surprise = PhotoImage(file="suprprise.png")
win = PhotoImage(file="WINNN.png")
lose = PhotoImage(file="LOSEEE.png")
check = PhotoImage(file="CHECKK.png")
close = PhotoImage(file="CLOSEE.png")
  • After we have added the word, we’ll add a blank row to make it less congested.
  • Now, we will modify the fonts to use later in our entry widget.
  • Now we need various images for the main label, win, lose, check, close, etc. So, here we are loading them into variables to use it later.

8. Add Entry widget

 #Entry label
label = Label(root,image=your_choice)
label.grid(row=2,column=0,columnspan=len_list1)
label["font"] = myFont
    
#Add blank space
root.grid_rowconfigure(3, minsize=10) 
    
#Add entry widget
e1 = Entry(root,bd=5,bg="#9ca1db",justify=CENTER,font=myFont,fg="#000000")
e1.grid(row=4,column=0,columnspan=len_list1)

#Add blank space
root.grid_rowconfigure(5, minsize=10) 
  • Now we are going to add a label that says enter your guess. Here we’re using the modified fonts we made in the previous point.
  • After that, we are just adding blank space.
  • Now we are adding the entry widget, where the user will enter their guessed word. Here we’re using columnspan to make that into center.
  • Now we add a blank space again.

9. Original word images

#Check button 
button =Button(root,image=check,command=lambda:result())
button.grid(row=6,column=0)
        
#Close button 
Btn = Button(root,image=close,command=lambda:reset())
Btn.grid(row=6,column=len_list1-1)
    
#Add blank space 
root.grid_rowconfigure(7, minsize=10) 

Now, we need to add the check button and close button. Pressing these buttons will trigger the result( ) and reset( ) functions respectively. The Check button will be on the first column, and the close button will be on the last column.


10. Result and time label

 #Label that will display result 
label2 = Label(root,image=surprise)
label2.grid(row=8,column=0,columnspan=len_list1)
    
root.grid_rowconfigure(9, minsize=10)
    
    
#Modify the fonts 
myFont = font.Font(family='Comic Sans MS',weight='bold')
    
#Label to show time taken 
label3= Label(root,text="TIME : ",width=12,bg="#f5ab55",justify=CENTER,font=myFont,fg="#000000",relief=RAISED)
label3.grid(row=12,column=0,columnspan=len_list1)
  • Here we’re adding one more label that will display the result for user’s guess.
  • We. are also modifying the fonts again to use in the time label. The time label will display the time taken by the user to guess the correct answer.

11. Main function to calculate the decision

#Function to check whether the user's guess is correct or not 
def result():
#Get the entry value in upper case 
    answer = (e1.get()).upper()
        
    if answer == pick:
        #Caculate the time consumed 
        time_taken = time.time() - start_time
        time_taken = int(time_taken)
            
        #Change the label 
        label3.configure(text="TIME : "+str(time_taken)+" Sec")
            
        #Play win sound 
        one.play()
            
        #Change label image to win 
        label2.configure(image=win)
            
        #Showing original word 
        col_2=0
        row_2=10
            
        #Display the origianl word 
        for i in range(len_list1):
            B = Label(root,image=list2[i])
            B.grid(row=row_2,column=col_2)
            col_2 = col_2+1
                
        #Add blank space 
        root.grid_rowconfigure(11, minsize=10) 
            
        #To play again after 3 sec 
        root.update_idletasks()
        root.after(3000)
        root.destroy()
        
    else:
        #Play a sound file 
        two.play()
            
        #Change the label 
        label2.configure(image=lose)
            
        #Change back to original label image 
        root.update_idletasks()
        root.after(500)
        label2.configure(image=surprise)
            
        #Clear the entry 
        e1.delete(0,"end")
  • First, we take the value entered by user in the entry widget.
  • Then, we are checking if the word entered by user is correct. If the word is correct, it will calculate the time taken by user to guess the word. Then, it’s going to change the text of time label to display the time taken by user.
  • After that, it’s going to play a sound file. Here the label will show the WIN image. Now we will display the image label for the actual word. Our program will wait for 3 seconds, close the current window, and open a new one.
  • If the user has entered the wrong word, the label will show lose image, and the entry widget will be cleared for user to reenter the word. After 0.5 seconds, the Lose label will go back to its original image.

12. Reset( ) function and enter the main loop

def reset():
  #Play a sound file :
    three.play()
        
  #Change the running value to false :
      global running
      running=False
        
  #CLose the main window :
      root.destroy()

    
#Enter the main loop :
root.mainloop()
  • If the user presses the close button, then the reset( ) function will trigger. It will set the running variable to False so that our program can’t open a new window.
  • We then have to enter the main loop to run the program. If our program doesn’t have this line, it will not work.

Putting it all together

Take a look at the complete code for this Python Tkinter game.

Want to download the code and images? You can download all the necessary images and code here.

#Import required libraries :
from tkinter import *
import simpleaudio as sa
import random
import tkinter.font as font
import time


running = True

while running==True:
    #Calculate starting time :
    start_time = time.time()
    
    root = Tk()
    root.geometry('+100+0')
    root.configure(bg="#000000")
    root.iconphoto(True,PhotoImage(file="Surprise.png"))
    root.title("JUMBLE WORDS")
    root.resizable(width=False,height=False)

    #Load sound files :
    start = sa.WaveObject.from_wave_file("Start.wav")
    one = sa.WaveObject.from_wave_file("Win.wav")
    two = sa.WaveObject.from_wave_file("Lose.wav")
    three = sa.WaveObject.from_wave_file("6.wav")
    
    start.play()
    
    #Select a word from list :
    def random_word():
        words=["RAIN","CLOUD","NATURE","BEAUTIFUL","HOUSE"]
        pick = random.choice(words)
        return pick

    #Jumble the selected word :
    def jumbled_word(word):
        word = random.sample(word,len(word))
        word_jumbled = "".join(word)
        return word_jumbled
    
    #Randomly selected word :
    pick = random_word()
    
    #Jumbled word :
    jumbled = jumbled_word(pick)
    
    #Get the letters from jumbled word :
    list1 = list(jumbled)
    len_list1 = len(list1)
    
    #Get the PhotoImages for our letters :
    for i in range(len_list1):
        list1[i] = PhotoImage(file=str(list1[i])+str("_P.png"))

    row_0 = 0
    col_0 = 0

    #Arrange the letters on the main window :
    for i in range(len_list1):
        B = Label(root,image=list1[i])
        B.grid(row=row_0,column=col_0)
        col_0 = col_0 + 1

    #Blank space for row_1 :
    root.grid_rowconfigure(1, minsize=10)
    
    #Modify font :
    myFont = font.Font(family='Calibri',  weight='bold')
    
    #For label image :
    your_choice = PhotoImage(file="YOUR_GUESS.png")
    surprise = PhotoImage(file="surprise.png")
    win = PhotoImage(file="WINNN.png")
    lose = PhotoImage(file="LOSEEE.png")
    check = PhotoImage(file="CHECKK.png")
    close = PhotoImage(file="CLOSEE.png")

    #To arrange the labels in center :
    #x = math.floor(len_list1/2)

    #Entry label :
    label = Label(root,image=your_choice)
    label.grid(row=2,column=0,columnspan=len_list1)
    label["font"] = myFont
    
    #Add blank space :
    root.grid_rowconfigure(3, minsize=10) 
    
    #Add entry widget :
    e1 = Entry(root,bd=5,bg="#9ca1db",justify=CENTER,font=myFont,fg="#000000")
    e1.grid(row=4,column=0,columnspan=len_list1)

    #Add blank space :
    root.grid_rowconfigure(5, minsize=10) 
    
    #Get the entry value in upper case :
    answer = (e1.get()).upper()
  
    #Make list of correct word :
    list2=list(pick)

    #Load images for correct word :
    for j in range(len(list2)):
        list2[j] = PhotoImage(file=str(list2[j])+str("_P.png"))

    #Check button :
    button =Button(root,image=check,command=lambda:result())
    button.grid(row=6,column=0)
        
    #Close button :
    Btn = Button(root,image=close,command=lambda:reset())
    Btn.grid(row=6,column=len_list1-1)
    
    #Add blank space :
    root.grid_rowconfigure(7, minsize=10) 

    
    #Label that will display result :
    label2 = Label(root,image=surprise)
    label2.grid(row=8,column=0,columnspan=len_list1)
    
    root.grid_rowconfigure(9, minsize=10)
    
    
    #Modify the fonts :
    myFont = font.Font(family='Comic Sans MS',weight='bold')
    
    #Label to show time taken :
    label3= Label(root,text="TIME : ",width=12,bg="#f5ab55",justify=CENTER,font=myFont,fg="#000000",relief=RAISED)
    label3.grid(row=12,column=0,columnspan=len_list1)
    
    #Function to check whether the user's guess is correct or not :
    def result():
        #Get the entry value in upper case :
        answer = (e1.get()).upper()
        
        if answer == pick:
            #Caculate the time consumed :
            time_taken = time.time() - start_time
            time_taken = int(time_taken)
            
            #Change the label :
            label3.configure(text="TIME : "+str(time_taken)+" Sec")
            
            #Play win sound :
            one.play()
            
            #Change label image to win :
            label2.configure(image=win)
            
            #Showing original word :
            col_2=0
            row_2=10
            
            #Display the origianl word :
            for i in range(len_list1):
                B = Label(root,image=list2[i])
                B.grid(row=row_2,column=col_2)
                col_2 = col_2+1
                
            #Add blank space :
            root.grid_rowconfigure(11, minsize=10) 
            
            #To play again after 3 sec :
            root.update_idletasks()
            root.after(3000)
            root.destroy()
        
        else:
            #Play a sound file :
            two.play()
            
            #Change the label :
            label2.configure(image=lose)
            
            #Change back to original label image :
            root.update_idletasks()
            root.after(500)
            label2.configure(image=surprise)
            
            #Clear the entry :
            e1.delete(0,"end")


    #Function that triggers by pressing CLOSE button :
    
    def reset():
        #Play a sound file :
        three.play()
        
        #Change the running value to false :
        global running
        running=False
        
        #CLose the main window :
        root.destroy()

    
    #Enter the main loop :
    root.mainloop() 

Wrapping up and resources

Congrats! You’ve reached the end and built a successful Python Tkinter game. Great work applying your Python knowledge. I hope you enjoyed this article and learnt something new from it. Python is such an intuitive programming language that the easiest way to master it is through hands-on practice like this. Keep up the work and keep building!

In this series on Tkinter, we’ll be developing a total of Five games using Tkinter. So, hang tight! If you have any doubts, questions, or thoughts regarding this article, feel free to contact me at shuklapratik22@gmail.com


Continue learning


WRITTEN BYPratik Shukla

Join a community of 270,000 monthly readers. A free, bi-monthly email with a roundup of Educative's top articles and coding tips.