Python Tkinter Tutorial: Create a F.L.A.M.E.S. game from scratch

Sep 22, 2020 - 8 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 further your knowledge of Tkinter, Python’s standard interface to the Tk GUI toolkit by building 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 F.L.A.M.E.S. from scratch!

Today, we will cover:


F.L.A.M.E.S. game walkthrough

In this article, we will develop the famous childhood game called F.L.A.M.E.S. In this relationship calculator, the user will enter two names, and as an output our program will tell us that whether they are:

  • Friends
  • Lovers
  • Affectionate
  • Married
  • Enemies
  • Siblings

Let’s develop the same game using Python 3 and Tkinter!


Rules and how to play

  1. Run the program.
  2. Enter the names.
  3. Press the button.
  4. See the result.
  5. Play again.
svg viewer
Game Flowchart

Walkthrough of the program

When the user runs the program, the user will enter two names for which they wants to find the relationship. After the user enters the details, our program will calculate the relationship status based on an algorithm. Let’s try to understand it with an example. First of all, our algorithm will remove all the common characters between the entered names.

For example, take the inputs:

CHANDLER
MONICA

The output will be:

HDLERMOI

Now our program will calculate the total number of letters in that final output list to determine how to iterate through the word FLAME for a result. In our above example, we have 8 letters in our final list, so we will go through the letters in FLAMES and cross out every 8th character iteratively. Let’s check it visually.

svg viewer

Here notice that the final result is “A” (Affectionate). Our program will also play different types of sound files on various events.


Final result

1. Start window. What the user will see after they enter the names.

1 of 3


Game implementation in Python (13 steps)

Now that we have a sense of what the F.L.A.M.E.S 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

from tkinter import *
import simpleaudio as sa
  • tkinter: To add widgets in our application.
  • simpleaudio: To play the sound files.

2. Main tkinter window

root = Tk()
root.title("FLAMES")
root.geometry("+100+0")
root.configure(bg="#000000")
root.resizable(width=False,height=False)
root.iconphoto(True,PhotoImage(file="flames.png"))
  • root = Tk( ): This is used to initialize our tkinter module.
  • root.title( ): We use this 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( ): We use this prevent the user from resizing our main window.
  • root.iconphoto( ): We use this to set the icon in the title bar for our application window.

3. Load the sound files

#Load audio 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("Draw.wav")
four = sa.WaveObject.from_wave_file("1.wav")
five = sa.WaveObject.from_wave_file("2.wav")
six = sa.WaveObject.from_wave_file("6.wav")

We will use some sound files that will play at various events. When our program starts, it will play start file. We’re going to play different files when we have different results for our game. One thing to notice is that Tkinter only accepts .wav files. First, we need to load the sound file in an object. Then, we can play it using .play( ) method when required.


4. Take input names

#Take input from user :    
name1 = input("Player 1 name : ") 
name1 = name1.upper() 
  
# replace any space with empty string 
name1.replace(" ", "") 
  
# make a list of letters or characters 
name1_list = list(name1) 
  
# take 2nd name 
name2 = input("Player 2 name : ") 
name2 = name2.upper() 
name2.replace(" ", "") 
name2_list = list(name2) 

Here we are taking input names from user. The user has to enter 2 names. After the user enters the name, our program will transform the names into upper case. Our program will also replace space with empty string. We have to do this if the user enters their first name and last name separated by space. Then, we’re going to convert it into list so that we can apply remove_comman_character( ) function on it.


5. Remove common characters

# Remove comman characters :
def remove_comman_char(list1, list2): 
  
    for i in range(len(list1)) : 
        for j in range(len(list2)) : 
            if list1[i] == list2[j] : 
                c = list1[i] 
  
                # Remove character from the list 
                list1.remove(c) 
                list2.remove(c) 
  
                # Concate two lists with # in middle  
                list3 = list1 + ["#"] + list2 
  
                # Return the concatenated list with True flag 
                return [list3, True] 
  
    # No common characters are found
    list3 = list1 + ["#"] + list2 
    return [list3, False] 

Here we are going to remove the common characters from our two names like we did in the walkthrough. We will use an interactive method for this.

Notice that when there are common characters in our string, it will return the both the name strings separated by # with a True flag. When there are no common characters in our strings, it will return both the name strings separated by # with a False flag. We’ll use this flag value later in our code to calculate the relationship.


6. Calling the function

# Taking a flag as True initially 
proceed = True

while proceed : 
  
    # Function call 
    ret_list = remove_comman_char(name1_list, name2_list) 
  
    #Final list : 
    con_list = ret_list[0] 
    
    #Flag value :
    proceed = ret_list[1] 
    
    #Index of hash : 
    hash_index = con_list.index("#") 
            
    # all characters before * store in p1_list 
    name1_list = con_list[ : hash_index] 
  
    # all characters after * store in p2_list 
    name2_list = con_list[hash_index + 1 : ] 
 
  
# count total remaining characters 
count = len(name1_list) + len(name2_list) 

First, we’re setting the proceed flag as True so that our remove_common_char function can go work. After that we’re going to remove common characters until the proceed flag isn’t set to False. When there are no common characters our program will set the flag as false.

Then we are finding the index of # by which we joined our two names after removing common characters. name1_list contains name1 characters, and name2_list stores name2 characters. Finally, we are storing the total length of both names after removing common characters in the variable called count.

From the example of the walkthrough, we get:

HDLER
MOI
  • Name 1: Length of name_1 = 5
  • Name 2: Length of name_2 = 3
  • Total length: 5 + 3 = 8

7. Calculating the relationship

# list of FLAMES acronym 
result = ["Friends", "Lovers", "Affectionate", "Marriage", "Enemies", "Siblings"] 
  
while len(result) > 1 : 
    
    ind = (count % len(result)) - 1
    
    if ind >= 0 : 
        right = result[ind + 1 : ] 
        left = result[ : ind] 
        result = right + left 
    
    else : 
        result = result[ : len(result) - 1] 

Let’s understand this with example. Our program will run until there is only one element left in result. Click through to see the iterations.

First Iteration

1 of 5


8. Load game images

Here we are loading a few images which we are going to use in our application. We are going to display the result label in form of images.

#Load images for tkinter window :
surprise = PhotoImage(file="Surprise.png")
fingers = PhotoImage(file="Fingers.png")
Friends = PhotoImage(file="F11.png")
Lovers = PhotoImage(file="L11.png")
Affectionate = PhotoImage(file="A11.png")
Marriage = PhotoImage(file="M11.png")
Enemies = PhotoImage(file="E11.png")
Siblings = PhotoImage(file="S11.png")

9. Generate list of names and load images for letters in names

Here we are generating lists of names that we’ll use to fetch the images for each letters in name. We are also finding the length of name that’ll be useful while running the for loop.

Then, we want to display each letters in name, we first need to load it in our application. Notice that our image files for alphabets are stored like:

  • A.png
  • B.png
  • C.png

Since we already have a list of letters we are going to need, we can easily run a for loop to fetch the letters.

#Length of names :
n_1 = len(name1)
n_2 = len(name2)

#Creaate list of names :
l1 = list(name1)
l2 = list(name2)

#Load the letters for name1 :
for i in range(n_1):
    l1[i] = PhotoImage(file=str(l1[i])+str(".png"))
        
#Load the letters for name2 :
for j in range(n_2):
    l2[j] = PhotoImage(file=str(l2[j])+str(".png"))

10. Display the names

r1=0
c1=0

r2=2
c2=0

#Display name1 :
for i in range(n_1):
    B = Label(root,image=l1[i])        
    B.grid(row=r1,column=c1)
    c1 = c1+1

#Add blank space :
root.grid_rowconfigure(1, minsize=50)

#Display name2 :
for j in range(n_2):
    B = Label(root,image=l2[j])
    B.grid(row=r2,column=c2)
    c2 = c2+1

#Add blank space :
root.grid_rowconfigure(3, minsize=50)

Here we are displaying the names in form of image labels. Our first name will be displayed in the 0th row and then there will be a blank space on the 1st row. Our second name will be displayed on the 2nd row. After that, we’re adding a blank space on the 3rd row.


11. Add button and result label

#Add button :
btn = Button(root,image=surprise,command=lambda:Reveal())
btn.grid(row=4,column=0,columnspan = n_1)

#Add result label :
res = Label(root,image=fingers)
res.grid(row=6,column=0,columnspan = n_1)
   
#Add blank space :
root.grid_rowconfigure(5, minsize=50)

#Play sound file :
start.play()

Since we have displayed the names, we are creating a button and a label. When the user will press the button it will trigger the Reveal( ) function. Our reveal function will display the relationship between two entered names in form of image.


12. Main function to display the result

#Reveal the result :
def Reveal():
    if result[0]=="Friends":
        one.play()
        res.configure(image=Friends)
        btn.configure(command=lambda:root.destroy())
            
    elif result[0]=="Lovers":
        five.play()
        res.configure(image=Lovers)
        btn.configure(command=lambda:root.destroy())
    
    elif result[0]=="Affectionate":
        six.play()
        res.configure(image=Affectionate)
        btn.configure(command=lambda:root.destroy())
        
    elif result[0]=="Marriage":
        four.play()
        res.configure(image=Marriage)
        btn.configure(command=lambda:root.destroy())
    
    elif result[0]=="Enemies":
        two.play()
        res.configure(image=Enemies)
        btn.configure(command=lambda:root.destroy())
    
    else:
        three.play()
        res.configure(image=Siblings)
        btn.configure(command=lambda:root.destroy())

This is the main function, that will change the image of our label based on the relationship result. Our result variable is storing the value of the relationship result calculated. The rest of the code is just if-else statements which is self explanatory.


13. Enter the mainloop

We have to enter the main loop to run the program. If our program doesn’t have this line then it will not work. Our program will remain in the main loop until we press the close button.

root.mainloop()

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.

from tkinter import *
import simpleaudio as sa

root = Tk()
root.title("FLAMES")
root.geometry("+100+0")
root.configure(bg="#000000")
root.resizable(width=False,height=False)
root.iconphoto(True,PhotoImage(file="flames.png"))

#Load audio 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("Draw.wav")
four = sa.WaveObject.from_wave_file("1.wav")
five = sa.WaveObject.from_wave_file("2.wav")
six = sa.WaveObject.from_wave_file("6.wav")


#Take input from user :    
name1 = input("Player 1 name : ") 
name1 = name1.upper() 
  
# replace any space with empty string 
name1.replace(" ", "") 
  
# make a list of letters or characters 
name1_list = list(name1) 
  
# take 2nd name 
name2 = input("Player 2 name : ") 
name2 = name2.upper() 
name2.replace(" ", "") 
name2_list = list(name2) 

#Set the longer name as name1 :
if len(name2)>len(name1):
    name3 = name1
    name1 = name2
    name2 = name3

# Remove comman characters :
def remove_comman_char(list1, list2): 
  
    for i in range(len(list1)) : 
        for j in range(len(list2)) : 
            if list1[i] == list2[j] : 
                c = list1[i] 
  
                # Remove character from the list 
                list1.remove(c) 
                list2.remove(c) 
  
                # Concate two lists with # in middle  
                list3 = list1 + ["#"] + list2 
  
                # Return the concatenated list with True flag 
                return [list3, True] 
  
    # No common chcaracters found
    list3 = list1 + ["#"] + list2 
    return [list3, False] 
 
    
    
# Taking a flag as True initially 
proceed = True

while proceed : 
  
    # Function call 
    ret_list = remove_comman_char(name1_list, name2_list) 
  
    #Final list : 
    con_list = ret_list[0] 
    
    #Flag value :
    proceed = ret_list[1] 
    
    #Index of hash : 
    hash_index = con_list.index("#") 
            
    # all characters before * store in p1_list 
    name1_list = con_list[ : hash_index] 
  
    # all characters after * store in p2_list 
    name2_list = con_list[hash_index + 1 : ] 
 
  
# count total remaining characters 
count = len(name1_list) + len(name2_list) 


# list of FLAMES acronym 
result = ["Friends", "Lovers", "Affectionate", "Marriage", "Enemies", "Siblings"] 
  
while len(result) > 1 : 
    
    ind = (count % len(result)) - 1
    
    if ind >= 0 : 
        right = result[ind + 1 : ] 
        left = result[ : ind] 
        result = right + left 
    
    else : 
        result = result[ : len(result) - 1] 
  
  

#Load images for tkinter window :
surprise = PhotoImage(file="Surprise.png")
fingers = PhotoImage(file="Fingers.png")
Friends = PhotoImage(file="F11.png")
Lovers = PhotoImage(file="L11.png")
Affectionate = PhotoImage(file="A11.png")
Marriage = PhotoImage(file="M11.png")
Enemies = PhotoImage(file="E11.png")
Siblings = PhotoImage(file="S11.png")
    
#Length of names :
n_1 = len(name1)
n_2 = len(name2)

#Creaate list of names :
l1 = list(name1)
l2 = list(name2)

#Load the letters for name1 :
for i in range(n_1):
    l1[i] = PhotoImage(file=str(l1[i])+str(".png"))
        
#Load the letters for name2 :
for j in range(n_2):
    l2[j] = PhotoImage(file=str(l2[j])+str(".png"))
    

r1=0
c1=0

r2=2
c2=0

#Display name1 :
for i in range(n_1):
    B = Label(root,image=l1[i])        
    B.grid(row=r1,column=c1)
    c1 = c1+1

#Add blank space :
root.grid_rowconfigure(1, minsize=50)

#Display name2 :
for j in range(n_2):
    B = Label(root,image=l2[j])
    B.grid(row=r2,column=c2)
    c2 = c2+1

#Add blank space :
root.grid_rowconfigure(3, minsize=50)

#Add button :
btn = Button(root,image=surprise,command=lambda:Reveal())
btn.grid(row=4,column=0,columnspan = n_1)

#Add result label :
res = Label(root,image=fingers)
res.grid(row=6,column=0,columnspan = n_1)
   
#Add blank space :
root.grid_rowconfigure(5, minsize=50)

#Play sound file :
start.play()

#Reveal the result :
def Reveal():
    if result[0]=="Friends":
        one.play()
        res.configure(image=Friends)
        btn.configure(command=lambda:root.destroy())
            
    elif result[0]=="Lovers":
        five.play()
        res.configure(image=Lovers)
        btn.configure(command=lambda:root.destroy())
    
    elif result[0]=="Affectionate":
        six.play()
        res.configure(image=Affectionate)
        btn.configure(command=lambda:root.destroy())
        
    elif result[0]=="Marriage":
        four.play()
        res.configure(image=Marriage)
        btn.configure(command=lambda:root.destroy())
    
    elif result[0]=="Enemies":
        two.play()
        res.configure(image=Enemies)
        btn.configure(command=lambda:root.destroy())
    
    else:
        three.play()
        res.configure(image=Siblings)
        btn.configure(command=lambda:root.destroy())
            
    
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 learned something new about algorithms 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!

This is the final article in my Tkinter series. I hope you enjoyed the series. Continue using Python and build your resume with fun games like these!

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.