Create a Memory Puzzle Game Using Pygame
Last Updated :
28 Aug, 2024
Playing memory puzzle games provides entertainment and boosts mental abilities such as focus and memory recall. This article guides you through the steps to create a straightforward memory puzzle game using the Python Pygame Library. After completing the article, you will have a fully functioning game where players try to match pairs of game pieces.
Create a Memory Puzzle Game in Python
Below is the implementation of the memory puzzle game in Python:
Create a Virtual Environment
First, create the virtual environment using the below commands
python -m venv env
.\env\Scripts\activate.ps1
Install Necessary Library
First, install PyGame, Requests, and Pillow libraries for multimedia, HTTP requests, and image processing respectively using the command below.
pip install pygame
pip install requests
pip install pillow
Writing PyGame Code
Here is the code of main.py that we are using to create our game using PyGame. Below is a step-by-step explanation of this code.
Step 1: Library Imports
below code imports essential modules for building a game with Pygame, incorporating functionalities for graphics, randomization, time management, HTTP requests, binary data handling, and image processing.
Python
import pygame
import random
import time
import requests
from io import BytesIO
from PIL import Image
Step 2: Initialization and Setup
below code initializes the Pygame library, defines constants for screen dimensions, card size, grid size, colors, flip delay, button dimensions, and timer limit. Additionally, it provides a list of image URLs for the game. Finally, it creates a game window with specified dimensions and sets the window's caption to "Memory Puzzle Game" using Pygame functions.
Python
# Initialize pygame
pygame.init()
# Constants
SCREEN_WIDTH = 700
SCREEN_HEIGHT = 700
CARD_SIZE = 175
GRID_SIZE = 4
WHITE = (255, 255, 255)
FLIP_DELAY = 0.5
BUTTON_WIDTH = 140
BLACK = (0, 0, 0)
BUTTON_HEIGHT = 40
TIMER_LIMIT = 15
# URLs for images
image_urls = [
"https://media.geeksforgeeks.org/wp-content/uploads/20240311120810/f.webp",
"https://media.geeksforgeeks.org/wp-content/uploads/20240311121011/d.webp",
"https://media.geeksforgeeks.org/wp-content/uploads/20240311120802/a.webp",
"https://media.geeksforgeeks.org/wp-content/uploads/20240311120802/b.webp",
"https://media.geeksforgeeks.org/wp-content/uploads/20240311120801/c.webp",
"https://media.geeksforgeeks.org/wp-content/uploads/20240311122347/z.webp",
"https://media.geeksforgeeks.org/wp-content/uploads/20240311122913/y.webp",
"https://media.geeksforgeeks.org/wp-content/uploads/20240311122913/x.webp"
]
# Create the game window
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("Memory Puzzle Game")
Step 3: Loading and Preprocessing Images
below, code uses the `requests` library to download an image from a specified URL, convert it to PNG format using the `PIL` (Pillow) library, and then load it as a Pygame image. The process is applied to both the card back image and a list of card images obtained from a set of URLs.
Python
# Load card back image from URL and convert to PNG format
response = requests.get(
"https://media.geeksforgeeks.org/wp-content/uploads/20240311145552/geeksforgeeks.png")
image = Image.open(BytesIO(response.content))
image = image.convert("RGB")
with BytesIO() as img_bytes:
image.save(img_bytes, "PNG")
img_bytes.seek(0)
card_back = pygame.image.load(img_bytes)
# Load card images from URLs and convert to PNG format
card_images = []
for url in image_urls:
response = requests.get(url)
image = Image.open(BytesIO(response.content))
image = image.convert("RGB")
with BytesIO() as img_bytes:
image.save(img_bytes, "PNG")
img_bytes.seek(0)
card_images.append(pygame.image.load(img_bytes))
Step 4: Game Setup - Shuffling and Duplicating Cards
In below code duplicates the card images to create pairs, shuffles them randomly, and initializes a list (`card_state`) to keep track of the state of each card in the game. Each element of `card_state` corresponds to a card on the grid, where `True` indicates the card is face-up and `False` indicates it's face-down.
Python
# Duplicate card images to create pairs
card_images *= 2
# Shuffle the cards
random.shuffle(card_images)
# Create a list to store the state of each card (True: face-up, False: face-down)
card_state = [False] * (GRID_SIZE ** 2)
Step 5: Game Loop and Input Handling
below code segment represents the main game loop, which continuously checks for user input events, such as quitting the game or clicking the mouse. If the mouse is clicked, the code determines if the click occurred within the restart button's rectangle and, if so, shuffles the cards and resets relevant game variables. The code also handles flipping cards, updating move counts, and rendering the game grid with card images.
Python
# Main game loop
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.MOUSEBUTTONDOWN:
mouse_x, mouse_y = pygame.mouse.get_pos()
restart_button_rect = (
SCREEN_WIDTH - BUTTON_WIDTH - 20, 20, BUTTON_WIDTH, BUTTON_HEIGHT)
if point_in_rect((mouse_x, mouse_y), restart_button_rect):
random.shuffle(card_images)
card_state = [False] * (GRID_SIZE ** 2)
flipped_cards = []
matched_pairs = 0
moves = 0
timer_start_time = time.time() # Restart the timer
else:
col = mouse_x // CARD_SIZE
row = mouse_y // CARD_SIZE
index = row * GRID_SIZE + col
if not card_state[index] and len(flipped_cards) < 2:
card_state[index] = True
flipped_cards.append(index)
moves += 1
screen.fill(WHITE)
# Draw grid of cards
for i in range(GRID_SIZE):
for j in range(GRID_SIZE):
index = i * GRID_SIZE + j
pygame.draw.rect(screen, WHITE, (j * CARD_SIZE,
i * CARD_SIZE, CARD_SIZE, CARD_SIZE))
if card_state[index] or index in flipped_cards:
card = card_images[index]
else:
card = card_back
card = pygame.transform.scale(card, (CARD_SIZE - 8, CARD_SIZE - 8))
screen.blit(card, (j * CARD_SIZE + 4, i * CARD_SIZE + 4))
# Render moves counter
moves_text = font.render(f"Moves: {moves}", True, WHITE)
screen.blit(moves_text, (10, 10))
# Draw restart game button
draw_restart_button()
# Draw timer
draw_timer()
Step 6: Drawing Functions
below, code initializes a memory puzzle game using Pygame, defining constants, loading card images from URLs, and creating a game window. It employs a main game loop that handles user input, updates the game state, and continuously renders the grid of cards, move counts, restart button, and timer.
Python
# Function to draw restart game button
def draw_restart_button():
restart_button_rect = (SCREEN_WIDTH - BUTTON_WIDTH -
20, 20, BUTTON_WIDTH, BUTTON_HEIGHT)
pygame.draw.rect(screen, WHITE, restart_button_rect)
# Specify text color (black)
restart_text = font.render("Restart Game", True, (0, 0, 0))
text_rect = restart_text.get_rect(center=(
restart_button_rect[0] + BUTTON_WIDTH / 2, restart_button_rect[1] + BUTTON_HEIGHT / 2))
screen.blit(restart_text, text_rect)
# Function to draw timer
def draw_timer():
elapsed_time = max(0, int(time.time() - timer_start_time))
remaining_time = max(0, TIMER_LIMIT - elapsed_time)
timer_text = font.render(f"Time: {remaining_time}s", True, BLACK)
screen.blit(timer_text, (SCREEN_WIDTH - 150, 10))
# Function to display message on the window
def display_message(message):
message_text = font.render(message, True, BLACK)
text_rect = message_text.get_rect(
center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2))
screen.blit(message_text, text_rect)
Step 7: Game Logic and End Conditions
Below, code checks for matched pairs when two cards are flipped, introducing a brief delay for visibility. If a pair is found, the counter increments; otherwise, the card states are reset. It verifies if all pairs are matched or if the time limit is reached, displaying corresponding messages and concluding the game.
Python
# Check for matched pairs
if len(flipped_cards) == 2:
time.sleep(FLIP_DELAY)
if card_images[flipped_cards[0]] == card_images[flipped_cards[1]]:
matched_pairs += 1
flipped_cards = []
else:
card_state[flipped_cards[0]] = False
card_state[flipped_cards[1]] = False
flipped_cards = []
# Check for game over
if matched_pairs == GRID_SIZE ** 2 // 2:
display_message("Congratulations! You found all the pairs!")
pygame.display.flip()
time.sleep(2) # Display the message for 2 seconds
running = False
# Check for time limit reached
elapsed_time = time.time() - timer_start_time
if elapsed_time >= TIMER_LIMIT:
display_message("Time's up! You lost the game.")
pygame.display.flip()
time.sleep(2) # Display the message for 2 seconds
running = False
pygame.display.flip()
pygame.quit()
Complete Code
This is the complete code that we have explained in the above steps that we have used to create memory puzzle game using Pygame.
main.py
Python
import pygame
import random
import time
import requests
from io import BytesIO
from PIL import Image
# Initialize pygame
pygame.init()
# Constants
SCREEN_WIDTH = 700
SCREEN_HEIGHT = 700
CARD_SIZE = 175
GRID_SIZE = 4
WHITE = (255, 255, 255)
FLIP_DELAY = 0.5
BUTTON_WIDTH = 140
BLACK = (0, 0, 0)
BUTTON_HEIGHT = 40
TIMER_LIMIT = 15
# URLs for images
image_urls = [
"https://media.geeksforgeeks.org/wp-content/uploads/20240311120810/f.webp",
"https://media.geeksforgeeks.org/wp-content/uploads/20240311121011/d.webp",
"https://media.geeksforgeeks.org/wp-content/uploads/20240311120802/a.webp",
"https://media.geeksforgeeks.org/wp-content/uploads/20240311120802/b.webp",
"https://media.geeksforgeeks.org/wp-content/uploads/20240311120801/c.webp",
"https://media.geeksforgeeks.org/wp-content/uploads/20240311122347/z.webp",
"https://media.geeksforgeeks.org/wp-content/uploads/20240311122913/y.webp",
"https://media.geeksforgeeks.org/wp-content/uploads/20240311122913/x.webp"
]
# Create the game window
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("Memory Puzzle Game")
# Load card back image from URL and convert to PNG format
response = requests.get(
"https://media.geeksforgeeks.org/wp-content/uploads/20240311145552/geeksforgeeks.png")
image = Image.open(BytesIO(response.content))
image = image.convert("RGB")
with BytesIO() as img_bytes:
image.save(img_bytes, "PNG")
img_bytes.seek(0)
card_back = pygame.image.load(img_bytes)
# Load card images from URLs and convert to PNG format
card_images = []
for url in image_urls:
response = requests.get(url)
image = Image.open(BytesIO(response.content))
image = image.convert("RGB")
with BytesIO() as img_bytes:
image.save(img_bytes, "PNG")
img_bytes.seek(0)
card_images.append(pygame.image.load(img_bytes))
# Duplicate card images to create pairs
card_images *= 2
# Shuffle the cards
random.shuffle(card_images)
# Create a list to store the state of each card (True: face-up, False: face-down)
card_state = [False] * (GRID_SIZE ** 2)
# Variables to keep track of flipped cards, matched pairs, moves, and timer
flipped_cards = []
matched_pairs = 0
moves = 0
timer_start_time = time.time()
# Font for displaying text
font = pygame.font.Font(None, 36)
# Function to check if a point is within a rectangle
def point_in_rect(point, rect):
x, y = point
rx, ry, rw, rh = rect
return rx < x < rx + rw and ry < y < ry + rh
# Function to draw restart game button
def draw_restart_button():
restart_button_rect = (SCREEN_WIDTH - BUTTON_WIDTH -
20, 20, BUTTON_WIDTH, BUTTON_HEIGHT)
pygame.draw.rect(screen, WHITE, restart_button_rect)
# Specify text color (black)
restart_text = font.render("Restart Game", True, (0, 0, 0))
text_rect = restart_text.get_rect(center=(
restart_button_rect[0] + BUTTON_WIDTH / 2, restart_button_rect[1] + BUTTON_HEIGHT / 2))
screen.blit(restart_text, text_rect)
# Function to draw timer
def draw_timer():
elapsed_time = max(0, int(time.time() - timer_start_time))
remaining_time = max(0, TIMER_LIMIT - elapsed_time)
timer_text = font.render(f"Time: {remaining_time}s", True, BLACK)
screen.blit(timer_text, (SCREEN_WIDTH - 150, 10))
# Function to display message on the window
def display_message(message):
message_text = font.render(message, True, BLACK)
text_rect = message_text.get_rect(
center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2))
screen.blit(message_text, text_rect)
# Main game loop
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.MOUSEBUTTONDOWN:
mouse_x, mouse_y = pygame.mouse.get_pos()
restart_button_rect = (
SCREEN_WIDTH - BUTTON_WIDTH - 20, 20, BUTTON_WIDTH, BUTTON_HEIGHT)
if point_in_rect((mouse_x, mouse_y), restart_button_rect):
random.shuffle(card_images)
card_state = [False] * (GRID_SIZE ** 2)
flipped_cards = []
matched_pairs = 0
moves = 0
timer_start_time = time.time() # Restart the timer
else:
col = mouse_x // CARD_SIZE
row = mouse_y // CARD_SIZE
index = row * GRID_SIZE + col
if not card_state[index] and len(flipped_cards) < 2:
card_state[index] = True
flipped_cards.append(index)
moves += 1
screen.fill(WHITE)
# Draw grid of cards
for i in range(GRID_SIZE):
for j in range(GRID_SIZE):
index = i * GRID_SIZE + j
pygame.draw.rect(screen, WHITE, (j * CARD_SIZE,
i * CARD_SIZE, CARD_SIZE, CARD_SIZE))
if card_state[index] or index in flipped_cards:
card = card_images[index]
else:
card = card_back
card = pygame.transform.scale(card, (CARD_SIZE - 8, CARD_SIZE - 8))
screen.blit(card, (j * CARD_SIZE + 4, i * CARD_SIZE + 4))
# Render moves counter
moves_text = font.render(f"Moves: {moves}", True, WHITE)
screen.blit(moves_text, (10, 10))
# Draw restart game button
draw_restart_button()
# Draw timer
draw_timer()
# Check for matched pairs
if len(flipped_cards) == 2:
time.sleep(FLIP_DELAY)
if card_images[flipped_cards[0]] == card_images[flipped_cards[1]]:
matched_pairs += 1
flipped_cards = []
else:
card_state[flipped_cards[0]] = False
card_state[flipped_cards[1]] = False
flipped_cards = []
# Check for game over
if matched_pairs == GRID_SIZE ** 2 // 2:
display_message("Congratulations! You found all the pairs!")
pygame.display.flip()
time.sleep(2) # Display the message for 2 seconds
running = False
# Check for time limit reached
elapsed_time = time.time() - timer_start_time
if elapsed_time >= TIMER_LIMIT:
display_message("Time's up! You lost the game.")
pygame.display.flip()
time.sleep(2) # Display the message for 2 seconds
running = False
pygame.display.flip()
pygame.quit()
Output
Similar Reads
Create pong game using Python - Turtle
Pong is one of the most famous arcade games, simulating table tennis. Each player controls a paddle in the game by dragging it vertically across the screen's left or right side. Players use their paddles to strike back and forth on the ball. Turtle is an inbuilt graphic module in Python. It uses a p
3 min read
Angry Bird Game Using PyGame
Let's discuss the angry bird game using Pygame, I hope this article will be very interesting as it provides a holistic gaming experience at the end. We begin by describing the modules necessary to develop this game. Angry Birds Game Using PyGame The objective of the game is to hit as many enemy bird
14 min read
Create a Simple Two Player Game using Turtle in Python
Prerequisites: Turtle Programming in Python TurtleMove game is basically a luck-based game. In this game two-players (Red & Blue), using their own turtle (object) play the game. How to play The game is played in the predefined grid having some boundaries. Both players move the turtle for a unit
4 min read
Create Settings Menu in Python - Pygame
Python is a flexible programming language with a large selection of libraries and modules for a variety of applications. Pygame menu is one such toolkit that enables programmers to design graphical user interfaces for games and apps. In this tutorial, we'll look at how to use the pygame menu package
9 min read
Create Breakout Game using Python
In this article we will build a clone of a famous game, 'Breakout'. We will build this game using one of Python's in-built libraries, Turtle. RequirementsAn IDE like PyCharm.Basics of PythonBasic knowledge of Python-Turtle.Willingness to learn.Project StructureWe want to keep the programming simple.
15+ min read
Snake Game in Python - Using Pygame module
Snake game is one of the most popular arcade games of all time. In this game, the main objective of the player is to catch the maximum number of fruits without hitting the wall or itself. Creating a snake game can be taken as a challenge while learning Python or Pygame. It is one of the best beginne
15+ min read
Brick Breaker Game In Python using Pygame
Brick Breaker is a 2D arcade video game developed in the 1990s. The game consists of a paddle/striker located at the bottom end of the screen, a ball, and many blocks above the striker. The basic theme of this game is to break the blocks with the ball using the striker. The score is calculated by th
14 min read
How to move your Game Character Around in Pygame
Prerequisites: Pygame Pygame is a cross-platform set of Python modules designed for writing video games. It includes computer graphics and sound libraries designed to be used with the Python programming language. You can create different types of games using pygame including arcade games, platformer
9 min read
How to Create a pop up in pygame with pgu?
In this article, we will learn about how to create a pop-up in pygame with pgu in Python. PyGame The pygame library is an open-source Python module designed to assist you in creating games and other multimedia applications. Pygame, which is built on top of the highly portable SDL (Simple DirectMedia
6 min read
Flipping Tiles (memory game) using Python3
Flipping tiles game can be played to test our memory. In this, we have a certain even number of tiles, in which each number/figure has a pair. The tiles are facing downwards, and we have to flip them to see them. In a turn, one flips 2 tiles, if the tiles match then they are removed. If not then the
3 min read