The memory tile or matching game is an excellent and fun way to boost cognitive abilities, enhance memory, and improve focus. The game has a set of tiles that you have to flip one by one, memorize, and select the ones which match. On matching all the tiles correctly, you win the game.

So how can you develop this amazing game using Python?

The Tkinter and Random Modules

You can build the memory tile game using the Tkinter and Random modules. Tkinter allows you to create desktop applications. It offers a variety of widgets like buttons, labels, and text boxes that make it easier to develop applications like calendars, calculators, and to-do lists. To install Tkinter, open the terminal and run:

        pip install tkinter
    

The Random module is a built-in Python module used for generating pseudo-random numbers. Using this, you can build a random password generator, a dice roll simulation application, or a list shuffler. Furthermore, you can also develop interesting games like hand cricket and number guessing games.

How to Build the Memory Tile Game Using Python

You can find the source code for building the memory tile game using Python in this GitHub repository.

Begin by importing the Tkinter and the Random module. Initialize the root window, and set the title and dimensions in pixels.

        from tkinter import *
import random
from tkinter import messagebox

root = Tk()
root.title('Memory Tile Game')
root.geometry("760x550")

Define two global variables and initialize the winner variable to zero. Declare a list of items that will appear on the tiles. Reorder the list using the random module's shuffle() method. Define a frame in the root window and add a padding of 10 in the vertical direction.

Initialize a count variable to 0 and declare an answer list and dictionary respectively.

        global winner, matches
winner = 0
matches = ["apple","apple","banana","banana", "orange","orange", "blueberry","blueberry","mulberry","mulberry", "grapes","grapes"]
random.shuffle(matches)
my_frame = Frame(root)
my_frame.pack(pady=10)
count = 0
answer_list = []
answer_dict = {}

Define a function, reset(). Set the label's text to an empty string using the config() function. Define a button list, one for each of the tiles. Iterate over the list and set the text on the button tile to an empty string, the background color to default (SystemButtonFace), and the state to normal.

        def reset():
    my_label.config(text="")
    button_list = [b0,b1,b2,b3,b4,b5,b6,b7,b8,b9,b10,b11]
    for button in button_list:
        button.config(text=" ", bg="SystemButtonFace", state="normal")

Define a function, win(). Set a winning message in the text parameter of the label using the config() function. Define the button list as earlier and iterate through it to set the tile's background color to light green.

        def win():
    my_label.config(text="Congratulations! You Win!")
    button_list = [b0,b1,b2,b3,b4,b5,b6,b7,b8,b9,b10,b11]
    for button in button_list:
        button.config(bg="#90EE90")

Define a function, button_click() that takes the button and its number as input parameters. Reference the global variables, list, and dictionary. If the text of the button equals a space and the count is less than two then insert and display the text of the button. Append the button number to the answer list and the name to the answer dictionary. Increment the count variable by one.

        def button_click(b, number):
    global count, answer_list, answer_dict, winner
    if b["text"] == ' ' and count < 2:
        b["text"] = matches[number]
        answer_list.append(number)
        answer_dict[b] = matches[number]
        count += 1

If the length of the answer list is two, it means that the user has selected two tiles. If the text of the first tile matches the other, configure the label to display that both of them match correctly. Turn the state of the button to disabled. Set the count to zero, and empty the list and the dictionary. Increment the winner variable by one and if it turns to six, call the win function declared earlier.

            if len(answer_list) == 2:
        if matches[answer_list[0]] == matches[answer_list[1]]:
            my_label.config(text="It's a Match!")
            for key in answer_dict:
                key["state"] = "disabled"
            count = 0
            answer_list = []
            answer_dict = {}
            winner += 1
            if winner == 6:
                win()

Otherwise, reset the count variable and the list. Display a message box with the title and content depicting it as an incorrect match. Iterate over the answer list and set the text of the tile to a space. Reset the label and empty the dictionary. This ensures that there is no visible text on the button and the label after the user has selected incorrect tiles.

                else:
            count = 0
            answer_list = []
            messagebox.showinfo("Incorrect!", "Incorrect")
            for key in answer_dict:
                key["text"] = " "
            my_label.config(text=" ")
            answer_dict = {}

Define 12 buttons. Set the parent window you want to place them in, the text they should display, the font style they should have, their height, and width, and the command to execute when clicked. Remember to use the lambda function to pass the data to the button_click() function. Set the relief parameter to groove to create a 3-D depth effect around the button.

        b0 = Button(my_frame, text=' ', font=("Helvetica", 20), height=4, width=8, command=lambda: button_click(b0, 0), relief="groove")
b1 = Button(my_frame, text=' ', font=("Helvetica", 20), height=4, width=8, command=lambda: button_click(b1, 1), relief="groove")
b2 = Button(my_frame, text=' ', font=("Helvetica", 20), height=4, width=8, command=lambda: button_click(b2, 2), relief="groove")
b3 = Button(my_frame, text=' ', font=("Helvetica", 20), height=4, width=8, command=lambda: button_click(b3, 3), relief="groove")
b4 = Button(my_frame, text=' ', font=("Helvetica", 20), height=4, width=8, command=lambda: button_click(b4, 4), relief="groove")
b5 = Button(my_frame, text=' ', font=("Helvetica", 20), height=4, width=8, command=lambda: button_click(b5, 5), relief="groove")
b6 = Button(my_frame, text=' ', font=("Helvetica", 20), height=4, width=8, command=lambda: button_click(b6, 6), relief="groove")
b7 = Button(my_frame, text=' ', font=("Helvetica", 20), height=4, width=8, command=lambda: button_click(b7, 7), relief="groove")
b8 = Button(my_frame, text=' ', font=("Helvetica", 20), height=4, width=8, command=lambda: button_click(b8, 8), relief="groove")
b9 = Button(my_frame, text=' ', font=("Helvetica", 20), height=4, width=8, command=lambda: button_click(b9, 9), relief="groove")
b10 = Button(my_frame, text=' ', font=("Helvetica", 20), height=4, width=8, command=lambda: button_click(b10, 10), relief="groove")
b11 = Button(my_frame, text=' ', font=("Helvetica", 20), height=4, width=8, command=lambda: button_click(b11, 11), relief="groove")

Organize the buttons in a tabular format consisting of three rows and four columns using Tkinter's grid manager. To do so, call the grid() method and pass the row along with the column number you want to place it in.

        b0.grid(row=0, column=0)
b1.grid(row=0, column=1)
b2.grid(row=0, column=2)
b3.grid(row=0, column=3)
b4.grid(row=1, column=0)
b5.grid(row=1, column=1)
b6.grid(row=1, column=2)
b7.grid(row=1, column=3)
b8.grid(row=2, column=0)
b9.grid(row=2, column=1)
b10.grid(row=2, column=2)
b11.grid(row=2, column=3)

Define a label that shows an empty string and add a padding of 20 in the vertical direction. Define a top-level menu on the root window and attach it by turning the tearoff parameter to False. Add a sub-menu item, Options using the add_cascade parameter.

Add two menu items along with the commands they should execute when clicked in the submenu named Reset Game and Exit Game. Add a separator between them for demarcation.

        my_label = Label(root, text="")
my_label.pack(pady=20)

my_menu = Menu(root)
root.config(menu=my_menu)
option_menu = Menu(my_menu, tearoff=False)
my_menu.add_cascade(label="Options", menu=option_menu)
option_menu.add_command(label="Reset Game", command=reset)
option_menu.add_separator()
option_menu.add_command(label="Exit Game", command=root.quit)

The mainloop() function tells Python to run the Tkinter event loop and listen for events until you close the window.

        root.mainloop()
    

Put all the code together. Now the memory tile game is ready to play.

Output of the Memory Tile Game

On running the program, 12 buttons appear with empty text along with the Options menu. On clicking Reset Game, the window appears in this same fashion.

Output of memory tile game in beginning or on pressing reset game

On selecting two matching tiles, the buttons appear disabled and the label displays that the choice is correct.

Output of memory tile game on selection of correct tiles

On selecting two tiles that do not match, a message box appears indicating the selection was incorrect. The buttons and the label return to their original empty state.

Output of memory tile game on selection of wrong tiles

On successfully matching all the choices, the program turns all the tiles green and displays the winning message.

Output of memory tile game when you win

Games You Can Build Using Python

Python offers a variety of modules to build games. To create simple word or choice-based games such as Hangman, Tic-Tac-Toe, or Rock Paper Scissors you can utilize the Tkinter and Random modules. To develop games that need more graphics, you can use Pygame.

Pygame is a set of Python modules that works on all platforms. It includes computer graphics and sound libraries that make the games more interactive. A few of the games you can build using Pygame include the Snake game, memory puzzle game, and Sudoku.