
Memory Game in Python
We will learn to create a memory Game in Python.
Table of Contents
- Part I: Displaying the basic screen
- Part II: Adding Boxes
- Part III: Highlight Box when there is cursor over it.
- Part IV: Generating a random board
- Part V: Organizing
- Part VI: Drawing Icons on the Board
- Part VII: Reveal with a click
- Part VIII: Comparing the icons of two boxes
- Part IX: Game Completion
- Part X: Displaying Time of Completion
- Part XI: Final Complete Code
- Part XII: Link to github repository
Part I: Displaying the basic screen
import pygame, random,sys
from pygame.locals import *
#frames per second, the general speed of the program
FPS = 30
#window width in pixels
WINDOWWIDTH = 640
#Window height in pixels
WINDOWHEIGHT = 480
#Boxsize
BOXSIZE = 80
#GAPsize
GAPSIZE = 20
#Number of columns of icons
BOARDWIDTH = 4
#Number of rows of icons
BOARDHEIGHT = 4
#Board need to have an even numberof boxes for pairs of matches
assert(BOARDWIDTH*BOARDHEIGHT)%2 == 0, "Board needs to have even number of Boxes"
XMARGIN = int((WINDOWWIDTH - (BOARDWIDTH*(BOXSIZE+GAPSIZE)))/2)
YMARGIN = int((WINDOWHEIGHT - (BOARDHEIGHT * (BOXSIZE+GAPSIZE)))/2)
# R G B
GRAY = (100,100,100)
NAVYBLUE = (60,60,100)
WHITE = (255,255,255)
RED = (255,0,0)
GREEN = (0,255,0)
BLUE = (0,0,255)
YELLOW = (255,255,0)
ORANGE = (255,128,0)
PURPLE = (255,0,255)
CYAN = (0,255,255)
BGCOLOR = NAVYBLUE
LIGHTBGCOLOR = GRAY
BOXCOLOR = WHITE
HIGHLIGHTCOLOR = BLUE
DONUT = 'donut'
SQUARE= ' square'
DIAMOND = 'diamond'
LINES = 'lines'
OVAL = 'oval'
ALLCOLORS = (RED,GREEN,BLUE,YELLOW,ORANGE,PURPLE,CYAN)
ALLSHAPES = (DONUT,SQUARE,DIAMOND,LINES,OVAL)
assert len(ALLCOLORS) * len(ALLSHAPES) * 2 >= BOARDHEIGHT*BOARDWIDTH, "Board is too big for the number of shapes/colors defined"
def main():
global FPSCLOCK,DISPLAYSURF
pygame.init()
FPSCLOCK = pygame.time.Clock() #this will allow us to track time since last time the screen has been refreshed
DISPLAYSURF = pygame.display.set_mode((WINDOWWIDTH,WINDOWHEIGHT))
pygame.display.set_caption("Memory Game")
while True:
#Drawing the window
DISPLAYSURF.fill(BGCOLOR)
for event in pygame.event.get():
if event.type == QUIT or (event.type == KEYUP and event.key == K_ESCAPE):
pygame.quit()
sys.exit()
#Redraw the screen and wait a clock tick
pygame.display.flip()
FPSCLOCK.tick(FPS)
if __name__ == "__main__":
main()

Part II: Adding Boxes
import pygame, random,sys
from pygame.locals import *
#frames per second, the general speed of the program
FPS = 30
#window width in pixels
WINDOWWIDTH = 640
#Window height in pixels
WINDOWHEIGHT = 480
#Boxsize
BOXSIZE = 90
#GAPsize
GAPSIZE = 20
#Number of columns of icons
BOARDWIDTH = 4
#Number of rows of icons
BOARDHEIGHT = 4
#Board need to have an even numberof boxes for pairs of matches
assert(BOARDWIDTH*BOARDHEIGHT)%2 == 0, "Board needs to have even number of Boxes"
XMARGIN = int((WINDOWWIDTH - (BOARDWIDTH*(BOXSIZE+GAPSIZE)))/2)
YMARGIN = int((WINDOWHEIGHT - (BOARDHEIGHT * (BOXSIZE+GAPSIZE)))/2)
print("Xmargin",XMARGIN)
print("Ymargin",YMARGIN)
# R G B
GRAY = (100,100,100)
NAVYBLUE = (60,60,100)
WHITE = (255,255,255)
RED = (255,0,0)
GREEN = (0,255,0)
BLUE = (0,0,255)
YELLOW = (255,255,0)
ORANGE = (255,128,0)
PURPLE = (255,0,255)
CYAN = (0,255,255)
BGCOLOR = NAVYBLUE
LIGHTBGCOLOR = GRAY
BOXCOLOR = WHITE
HIGHLIGHTCOLOR = BLUE
DONUT = 'donut'
SQUARE= ' square'
DIAMOND = 'diamond'
LINES = 'lines'
OVAL = 'oval'
ALLCOLORS = (RED,GREEN,BLUE,YELLOW,ORANGE,PURPLE,CYAN)
ALLSHAPES = (DONUT,SQUARE,DIAMOND,LINES,OVAL)
assert len(ALLCOLORS) * len(ALLSHAPES) * 2 >= BOARDHEIGHT*BOARDWIDTH, "Board is too big for the number of shapes/colors defined"
def main():
global FPSCLOCK,DISPLAYSURF
pygame.init()
FPSCLOCK = pygame.time.Clock() #this will allow us to track time since last time the screen has been refreshed
DISPLAYSURF = pygame.display.set_mode((WINDOWWIDTH,WINDOWHEIGHT))
pygame.display.set_caption("Memory Game")
while True:
#Drawing the window
DISPLAYSURF.fill(BGCOLOR)
drawBoard() #part 2
for event in pygame.event.get():
if event.type == QUIT or (event.type == KEYUP and event.key == K_ESCAPE):
pygame.quit()
sys.exit()
#Redraw the screen and wait a clock tick
pygame.display.flip()
FPSCLOCK.tick(FPS)
def leftTopCoordsOfBox(boxx,boxy): #part 2
#convert the board coordinates to pixel coordinates
left = boxx * (BOXSIZE + GAPSIZE) + XMARGIN
top = boxy * (BOXSIZE + GAPSIZE)+YMARGIN
return (left,top)
def drawBoard(): #part 2
#Draw all the boxes
for boxx in range(BOARDWIDTH):
for boxy in range(BOARDHEIGHT):
left,top = leftTopCoordsOfBox(boxx,boxy)
pygame.draw.rect(DISPLAYSURF,BOXCOLOR,(left,top,BOXSIZE,BOXSIZE))
if __name__ == "__main__":
main()

Part III: Highlight Box when there is cursor over it.
#Inside main function
#Part 3
mousex = 0 #used to store x coordinate of mouse event
mousey = 0 #used to store y coordinate of mouse event
#changes inside the game loop
while True:
#Drawing the window
DISPLAYSURF.fill(BGCOLOR)
drawBoard() #part 2
for event in pygame.event.get():
if event.type == QUIT or (event.type == KEYUP and event.key == K_ESCAPE):
pygame.quit()
sys.exit()
#part 3
elif event.type == MOUSEMOTION:
mousex,mousey = event.pos
mouseClicked = True
boxx,boxy = getBoxAtPixel(mousex,mousey)
if boxx != None and boxy != None:
drawHighlightBox(boxx,boxy)
#This function returns the column and row of the box according to
#position of cursor
#Part 3
def getBoxAtPixel(x,y):
for boxx in range(BOARDWIDTH):
for boxy in range(BOARDHEIGHT):
left,top = leftTopCoordsOfBox(boxx,boxy)
boxRect = pygame.Rect(left,top,BOXSIZE,BOXSIZE)
if boxRect.collidepoint(x,y):
return(boxx,boxy)
return (None,None)
#Highlights the given box by drawing a blue rectangle around it
def drawHighlightBox(boxx,boxy):
left,top = leftTopCoordsOfBox(boxx,boxy)
pygame.draw.rect(DISPLAYSURF,HIGHLIGHTCOLOR,(left-5,top-5,BOXSIZE+10,BOXSIZE+10),4)
The whole code.
#Part 3 highlighting the box with a cursor over it
import pygame, random,sys
from pygame.locals import *
#frames per second, the general speed of the program
FPS = 30
#window width in pixels
WINDOWWIDTH = 640
#Window height in pixels
WINDOWHEIGHT = 480
#Boxsize
BOXSIZE = 90
#GAPsize
GAPSIZE = 20
#Number of columns of icons
BOARDWIDTH = 4
#Number of rows of icons
BOARDHEIGHT = 4
#Board need to have an even numberof boxes for pairs of matches
assert(BOARDWIDTH*BOARDHEIGHT)%2 == 0, "Board needs to have even number of Boxes"
XMARGIN = int((WINDOWWIDTH - (BOARDWIDTH*(BOXSIZE+GAPSIZE)))/2)
YMARGIN = int((WINDOWHEIGHT - (BOARDHEIGHT * (BOXSIZE+GAPSIZE)))/2)
# R G B
GRAY = (100,100,100)
NAVYBLUE = (60,60,100)
WHITE = (255,255,255)
RED = (255,0,0)
GREEN = (0,255,0)
BLUE = (0,0,255)
YELLOW = (255,255,0)
ORANGE = (255,128,0)
PURPLE = (255,0,255)
CYAN = (0,255,255)
BGCOLOR = NAVYBLUE
LIGHTBGCOLOR = GRAY
BOXCOLOR = WHITE
HIGHLIGHTCOLOR = BLUE
DONUT = 'donut'
SQUARE= ' square'
DIAMOND = 'diamond'
LINES = 'lines'
OVAL = 'oval'
ALLCOLORS = (RED,GREEN,BLUE,YELLOW,ORANGE,PURPLE,CYAN)
ALLSHAPES = (DONUT,SQUARE,DIAMOND,LINES,OVAL)
assert len(ALLCOLORS) * len(ALLSHAPES) * 2 >= BOARDHEIGHT*BOARDWIDTH, "Board is too big for the number of shapes/colors defined"
def main():
global FPSCLOCK,DISPLAYSURF
pygame.init()
FPSCLOCK = pygame.time.Clock() #this will allow us to track time since last time the screen has been refreshed
DISPLAYSURF = pygame.display.set_mode((WINDOWWIDTH,WINDOWHEIGHT))
pygame.display.set_caption("Memory Game")
#Part 3
mousex = 0 #used to store x coordinate of mouse event
mousey = 0 #used to store y coordinate of mouse event
while True:
#Drawing the window
DISPLAYSURF.fill(BGCOLOR)
drawBoard() #part 2
for event in pygame.event.get():
if event.type == QUIT or (event.type == KEYUP and event.key == K_ESCAPE):
pygame.quit()
sys.exit()
#part 3
elif event.type == MOUSEMOTION:
mousex,mousey = event.pos
mouseClicked = True
boxx,boxy = getBoxAtPixel(mousex,mousey)
if boxx != None and boxy != None:
drawHighlightBox(boxx,boxy)
#Redraw the screen and wait a clock tick
pygame.display.flip()
FPSCLOCK.tick(FPS)
def leftTopCoordsOfBox(boxx,boxy): #part 2
#convert the board coordinates to pixel coordinates
left = boxx * (BOXSIZE + GAPSIZE) + XMARGIN
top = boxy * (BOXSIZE + GAPSIZE)+YMARGIN
return (left,top)
#Part 3
def getBoxAtPixel(x,y):
for boxx in range(BOARDWIDTH):
for boxy in range(BOARDHEIGHT):
left,top = leftTopCoordsOfBox(boxx,boxy)
boxRect = pygame.Rect(left,top,BOXSIZE,BOXSIZE)
if boxRect.collidepoint(x,y):
return(boxx,boxy)
return (None,None)
def drawHighlightBox(boxx,boxy):
left,top = leftTopCoordsOfBox(boxx,boxy)
pygame.draw.rect(DISPLAYSURF,HIGHLIGHTCOLOR,(left-5,top-5,BOXSIZE+10,BOXSIZE+10),4)
def drawBoard(): #part 2
#Draw all the boxes
for boxx in range(BOARDWIDTH):
for boxy in range(BOARDHEIGHT):
left,top = leftTopCoordsOfBox(boxx,boxy)
pygame.draw.rect(DISPLAYSURF,BOXCOLOR,(left,top,BOXSIZE,BOXSIZE))
if __name__ == "__main__":
main()
Part IV: Generating a random board
#function to generate a random board according to colors and shapes #defined
#part 4
def getRandomizedBoard():
#Get a list of every possible shape in every possible color
icons = []
for color in ALLCOLORS:
for shape in ALLSHAPES:
icons.append((shape,color))
random.shuffle(icons) #randomize the order of the icons list
numIconsUsed = int(BOARDWIDTH*BOARDHEIGHT/2) #Calculate how many icons are needed
icons = icons[:numIconsUsed]*2 #make two of each
#Create the board data structure, with randomly placed icons
board = []
for x in range(BOARDWIDTH):
column = []
for y in range(BOARDHEIGHT):
column.append(icons[0])
del icons[0] #remove the icons as we assign them
board.append(column)
return board
Call this function from main function.
#Generating a random board
#Part 3 highlighting the box with a cursor over it
import pygame, random,sys
from pygame.locals import *
#frames per second, the general speed of the program
FPS = 30
#window width in pixels
WINDOWWIDTH = 640
#Window height in pixels
WINDOWHEIGHT = 480
#Boxsize
BOXSIZE = 90
#GAPsize
GAPSIZE = 20
#Number of columns of icons
BOARDWIDTH = 4
#Number of rows of icons
BOARDHEIGHT = 4
#Board need to have an even numberof boxes for pairs of matches
assert(BOARDWIDTH*BOARDHEIGHT)%2 == 0, "Board needs to have even number of Boxes"
XMARGIN = int((WINDOWWIDTH - (BOARDWIDTH*(BOXSIZE+GAPSIZE)))/2)
YMARGIN = int((WINDOWHEIGHT - (BOARDHEIGHT * (BOXSIZE+GAPSIZE)))/2)
# R G B
GRAY = (100,100,100)
NAVYBLUE = (60,60,100)
WHITE = (255,255,255)
RED = (255,0,0)
GREEN = (0,255,0)
BLUE = (0,0,255)
YELLOW = (255,255,0)
ORANGE = (255,128,0)
PURPLE = (255,0,255)
CYAN = (0,255,255)
BGCOLOR = NAVYBLUE
LIGHTBGCOLOR = GRAY
BOXCOLOR = WHITE
HIGHLIGHTCOLOR = BLUE
DONUT = 'donut'
SQUARE= ' square'
DIAMOND = 'diamond'
LINES = 'lines'
OVAL = 'oval'
ALLCOLORS = (RED,GREEN,BLUE,YELLOW,ORANGE,PURPLE,CYAN)
ALLSHAPES = (DONUT,SQUARE,DIAMOND,LINES,OVAL)
assert len(ALLCOLORS) * len(ALLSHAPES) * 2 >= BOARDHEIGHT*BOARDWIDTH, "Board is too big for the number of shapes/colors defined"
def main():
global FPSCLOCK,DISPLAYSURF
pygame.init()
FPSCLOCK = pygame.time.Clock() #this will allow us to track time since last time the screen has been refreshed
DISPLAYSURF = pygame.display.set_mode((WINDOWWIDTH,WINDOWHEIGHT))
pygame.display.set_caption("Memory Game")
#Part 3
mousex = 0 #used to store x coordinate of mouse event
mousey = 0 #used to store y coordinate of mouse event
#Part 4
#The function to generate a random board
mainBoard = getRandomizedBoard()
print("\n\n\n")
print(mainBoard)
while True:
#Drawing the window
DISPLAYSURF.fill(BGCOLOR)
drawBoard() #part 2
for event in pygame.event.get():
if event.type == QUIT or (event.type == KEYUP and event.key == K_ESCAPE):
pygame.quit()
sys.exit()
#part 3
elif event.type == MOUSEMOTION:
mousex,mousey = event.pos
mouseClicked = True
boxx,boxy = getBoxAtPixel(mousex,mousey)
if boxx != None and boxy != None:
drawHighlightBox(boxx,boxy)
#Redraw the screen and wait a clock tick
pygame.display.flip()
FPSCLOCK.tick(FPS)
#part 4
def getRandomizedBoard():
#Get a list of every possible shape in every possible color
icons = []
for color in ALLCOLORS:
for shape in ALLSHAPES:
icons.append((shape,color))
random.shuffle(icons) #randomize the order of the icons list
numIconsUsed = int(BOARDWIDTH*BOARDHEIGHT/2) #Calculate how many icons are needed
icons = icons[:numIconsUsed]*2 #make two of each
#Create the board data structure, with randomly placed icons
board = []
for x in range(BOARDWIDTH):
column = []
for y in range(BOARDHEIGHT):
column.append(icons[0])
del icons[0] #remove the icons as we assign them
board.append(column)
return board
def leftTopCoordsOfBox(boxx,boxy): #part 2
#convert the board coordinates to pixel coordinates
left = boxx * (BOXSIZE + GAPSIZE) + XMARGIN
top = boxy * (BOXSIZE + GAPSIZE)+YMARGIN
return (left,top)
#Part 3
def getBoxAtPixel(x,y):
for boxx in range(BOARDWIDTH):
for boxy in range(BOARDHEIGHT):
left,top = leftTopCoordsOfBox(boxx,boxy)
boxRect = pygame.Rect(left,top,BOXSIZE,BOXSIZE)
if boxRect.collidepoint(x,y):
return(boxx,boxy)
return (None,None)
def drawHighlightBox(boxx,boxy):
left,top = leftTopCoordsOfBox(boxx,boxy)
pygame.draw.rect(DISPLAYSURF,HIGHLIGHTCOLOR,(left-5,top-5,BOXSIZE+10,BOXSIZE+10),4)
def drawBoard(): #part 2
#Draw all the boxes
for boxx in range(BOARDWIDTH):
for boxy in range(BOARDHEIGHT):
left,top = leftTopCoordsOfBox(boxx,boxy)
pygame.draw.rect(DISPLAYSURF,BOXCOLOR,(left,top,BOXSIZE,BOXSIZE))
if __name__ == "__main__":
main()
Part V: Organizing
Moving functions and constants to different file.
#memory_functions.py
import pygame,random
from memory_constants import *
#part 4
def getRandomizedBoard():
#Get a list of every possible shape in every possible color
icons = []
for color in ALLCOLORS:
for shape in ALLSHAPES:
icons.append((shape,color))
random.shuffle(icons) #randomize the order of the icons list
numIconsUsed = int(BOARDWIDTH*BOARDHEIGHT/2) #Calculate how many icons are needed
icons = icons[:numIconsUsed]*2 #make two of each
#Create the board data structure, with randomly placed icons
board = []
for x in range(BOARDWIDTH):
column = []
for y in range(BOARDHEIGHT):
column.append(icons[0])
del icons[0] #remove the icons as we assign them
board.append(column)
return board
def leftTopCoordsOfBox(boxx,boxy): #part 2
#convert the board coordinates to pixel coordinates
left = boxx * (BOXSIZE + GAPSIZE) + XMARGIN
top = boxy * (BOXSIZE + GAPSIZE)+YMARGIN
return (left,top)
#Part 3
def getBoxAtPixel(x,y):
for boxx in range(BOARDWIDTH):
for boxy in range(BOARDHEIGHT):
left,top = leftTopCoordsOfBox(boxx,boxy)
boxRect = pygame.Rect(left,top,BOXSIZE,BOXSIZE)
if boxRect.collidepoint(x,y):
return(boxx,boxy)
return (None,None)
def drawHighlightBox(boxx,boxy):
left,top = leftTopCoordsOfBox(boxx,boxy)
pygame.draw.rect(DISPLAYSURF,HIGHLIGHTCOLOR,(left-5,top-5,BOXSIZE+10,BOXSIZE+10),4)
def drawBoard(): #part 2
#Draw all the boxes
for boxx in range(BOARDWIDTH):
for boxy in range(BOARDHEIGHT):
left,top = leftTopCoordsOfBox(boxx,boxy)
pygame.draw.rect(DISPLAYSURF,BOXCOLOR,(left,top,BOXSIZE,BOXSIZE))
#memory_constant.py
import pygame
from pygame.locals import *
#frames per second, the general speed of the program
FPS = 30
#window width in pixels
WINDOWWIDTH = 640
#Window height in pixels
WINDOWHEIGHT = 480
#Boxsize
BOXSIZE = 90
#GAPsize
GAPSIZE = 20
#Number of columns of icons
BOARDWIDTH = 4
#Number of rows of icons
BOARDHEIGHT = 4
#Board need to have an even numberof boxes for pairs of matches
assert(BOARDWIDTH*BOARDHEIGHT)%2 == 0, "Board needs to have even number of Boxes"
XMARGIN = int((WINDOWWIDTH - (BOARDWIDTH*(BOXSIZE+GAPSIZE)))/2)
YMARGIN = int((WINDOWHEIGHT - (BOARDHEIGHT * (BOXSIZE+GAPSIZE)))/2)
# R G B
GRAY = (100,100,100)
NAVYBLUE = (60,60,100)
WHITE = (255,255,255)
RED = (255,0,0)
GREEN = (0,255,0)
BLUE = (0,0,255)
YELLOW = (255,255,0)
ORANGE = (255,128,0)
PURPLE = (255,0,255)
CYAN = (0,255,255)
BGCOLOR = NAVYBLUE
LIGHTBGCOLOR = GRAY
BOXCOLOR = WHITE
HIGHLIGHTCOLOR = BLUE
DONUT = 'donut'
SQUARE= ' square'
DIAMOND = 'diamond'
LINES = 'lines'
OVAL = 'oval'
ALLCOLORS = (RED,GREEN,BLUE,YELLOW,ORANGE,PURPLE,CYAN)
ALLSHAPES = (DONUT,SQUARE,DIAMOND,LINES,OVAL)
DISPLAYSURF = pygame.display.set_mode((WINDOWWIDTH,WINDOWHEIGHT))
assert len(ALLCOLORS) * len(ALLSHAPES) * 2 >= BOARDHEIGHT*BOARDWIDTH, "Board is too big for the number of shapes/colors defined"
#Main program for game
import pygame, random,sys
from pygame.locals import *
from memory_functions import *
from memory_constants import *
def main():
global FPSCLOCK,DISPLAYSURF
pygame.init()
FPSCLOCK = pygame.time.Clock() #this will allow us to track time since last time the screen has been refreshed
pygame.display.set_caption("Memory Game")
mousex = 0 #used to store x coordinate of mouse event
mousey = 0 #used to store y coordinate of mouse event
#The function to generate a random board
mainBoard = getRandomizedBoard()
print("\n\n\n")
print(mainBoard)
while True:
#Drawing the window
DISPLAYSURF.fill(BGCOLOR)
drawBoard()
for event in pygame.event.get():
if event.type == QUIT or (event.type == KEYUP and event.key == K_ESCAPE):
pygame.quit()
sys.exit()
elif event.type == MOUSEMOTION:
mousex,mousey = event.pos
mouseClicked = True
boxx,boxy = getBoxAtPixel(mousex,mousey)
if boxx != None and boxy != None:
drawHighlightBox(boxx,boxy)
#Redraw the screen and wait a clock tick
pygame.display.flip()
FPSCLOCK.tick(FPS)
if __name__ == "__main__":
main()
Part VI: Drawing Icons on the Board
#Functions to draw icons
#drawing Icons
def drawIcon(shape, color, boxx,boxy):
quater = int(BOXSIZE * 0.25)
half = int(BOXSIZE * 0.5)
left, top = leftTopCoordsOfBox(boxx,boxy)
#draw the shapes
if shape == DONUT:
pygame.draw.circle(DISPLAYSURF,color,(left+half,top+half),half-5)
pygame.draw.circle(DISPLAYSURF,BGCOLOR,(left+half,top+half),quater-5)
elif shape == SQUARE:
pygame.draw.rect(DISPLAYSURF,color,(left+quater,top+quater,BOXSIZE-half,BOXSIZE-half))
elif shape == DIAMOND:
pygame.draw.polygon(DISPLAYSURF,color,((left+half,top),(left+BOXSIZE-1,top+half),(left+half,top+BOXSIZE-1),(left,top+half)))
elif shape == LINES:
for i in range(0,BOXSIZE,4):
pygame.draw.line(DISPLAYSURF,color,(left,top+i),(left+i,top))
pygame.draw.line(DISPLAYSURF,color,(left+i,top+BOXSIZE-1),(left+BOXSIZE-1,top+i))
elif shape == OVAL:
pygame.draw.ellipse(DISPLAYSURF,color,(left,top+quater,BOXSIZE,half))
#Function to generate the shape and color of box
def getShapeAndColor(board,boxx,boxy):
return board[boxx][boxy][0],board[boxx][boxy][1]
#Function to draw the icons on the board
#drawRevealed Board
def drawRevealedBoard(board):
for boxx in range(BOARDWIDTH):
for boxy in range(BOARDHEIGHT):
shape,color = getShapeAndColor(board,boxx,boxy)
drawIcon(shape,color,boxx,boxy)
Current Board Data

Current Board

Part VII: Reveal with a click
Start by combining the two functions: drawRevelBoard() and drawBoard()
def drawBoard(board,revealed):
#Draw all the boxes in their covered or revealed state
for boxx in range(BOARDWIDTH):
for boxy in range(BOARDHEIGHT):
left,top = leftTopCoordsOfBox(boxx,boxy)
if not revealed[boxx][boxy]:
#Draw a covered box
pygame.draw.rect(DISPLAYSURF,BOXCOLOR,(left,top,BOXSIZE,BOXSIZE))
else:
#Draw the (revealed icon)
shape, color = getShapeAndColor(board,boxx,boxy)
drawIcon(shape,color,boxx,boxy)
The =n following two functions will help us to animate the revealing of icons
def drawBoxCovers(board,boxes,coverage):
for box in boxes:
left, top = leftTopCoordsOfBox(box[0],box[1])
pygame.draw.rect(DISPLAYSURF,BGCOLOR,(left,top,BOXSIZE,BOXSIZE))
shape,color = getShapeAndColor(board,box[0],box[1])
drawIcon(shape,color,box[0],box[1])
if coverage > 0:
pygame.draw.rect(DISPLAYSURF,BOXCOLOR,(left,top,coverage,BOXSIZE))
pygame.display.update()
FPSCLOCK.tick(FPS)
#Animating the revealbox
def revealBoxesAnimation(board,boxesToReveal):
#do the box reveal animation
for coverage in range(BOXSIZE,(-REVEALSPEED)-1,-REVEALSPEED):
drawBoxCovers(board,boxesToReveal,coverage)
The main code:For now we will set all the boxes as not revealed with
revealedBoxes = generateRevealedBoxesData(False) . We will check whether the current box has been clicked or not.
After clicking we call the revealBoxesAnimation(mainBoard,[(boxx,boxy)]) function.
import pygame, random,sys
from pygame.locals import *
from memory_functions import *
from memory_constants import *
def main():
pygame.init()
#this will allow us to track time since last time the screen has been refreshed
pygame.display.set_caption("Memory Game")
mousex = 0 #used to store x coordinate of mouse event
mousey = 0 #used to store y coordinate of mouse event
#The function to generate a random board
mainBoard = getRandomizedBoard()
#part 7
revealedBoxes = generateRevealedBoxesData(False)
while True:
#Drawing the window
DISPLAYSURF.fill(BGCOLOR)
#drawRevealedBoard(mainBoard)
drawBoard(mainBoard,revealedBoxes)
for event in pygame.event.get():
if event.type == QUIT or (event.type == KEYUP and event.key == K_ESCAPE):
pygame.quit()
sys.exit()
elif event.type == MOUSEBUTTONUP:
mousex,mousey = event.pos
mouseClicked = True
boxx,boxy = getBoxAtPixel(mousex,mousey)
if boxx != None and boxy != None:
#part 7
if not revealedBoxes[boxx][boxy]:
drawHighlightBox(boxx,boxy)
if not revealedBoxes[boxx][boxy] and mouseClicked:
revealBoxesAnimation(mainBoard,[(boxx,boxy)])
#Redraw the screen and wait a clock tick
pygame.display.flip()
FPSCLOCK.tick(FPS)
if __name__ == "__main__":
main()
Part VIII: Comparing the icons of two boxes
The first clicked box will be revealed. The second clicked box will also be revealed. We will compare the the shape and colors of icons under first and second boxes. If the match, we will leave them in revealed condition, else we will call coverBoxesAnimation(board,boxesToCover) to cover them.
Changes to main.py
................
def main():
pygame.init()
pygame.display.set_caption("Memory Game")
mousex = 0 #used to store x coordinate of mouse event
mousey = 0 #used to store y coordinate of mouse event
#The function to generate a random board
mainBoard = getRandomizedBoard()
#part 7
revealedBoxes = generateRevealedBoxesData(False)
#part 8
#store the (x,y) of the first box clicked
firstSelection = None
while True:
#part 8
mouseClicked = False
#Drawing the window
DISPLAYSURF.fill(BGCOLOR)
drawBoard(mainBoard,revealedBoxes)
for event in pygame.event.get():
if event.type == QUIT or (event.type == KEYUP and event.key == K_ESCAPE):
pygame.quit()
sys.exit()
elif event.type == MOUSEMOTION:
mousex,mousey = event.pos
elif event.type == MOUSEBUTTONUP:
mousex,mousey = event.pos
mouseClicked = True
boxx,boxy = getBoxAtPixel(mousex,mousey)
if boxx != None and boxy != None:
#part 7
if not revealedBoxes[boxx][boxy]:
drawHighlightBox(boxx,boxy)
if not revealedBoxes[boxx][boxy] and mouseClicked:
revealBoxesAnimation(mainBoard,[(boxx,boxy)])
#part 8
#set the box as revealed
revealedBoxes[boxx][boxy]=True
if firstSelection == None:#the current box was the first box clicked
firstSelection = (boxx,boxy)
else:#the current box was the second box clicked
#check if there is a match between the two icons
icon1Shape, icon1Color = getShapeAndColor(mainBoard,firstSelection[0],firstSelection[1])
icon2Shape, icon2Color = getShapeAndColor(mainBoard,boxx,boxy)
if icon1Shape != icon2Shape or icon1Color != icon2Color:
#icons do not match recover up both selections
coverBoxesAnimation(mainBoard,[(firstSelection[0],firstSelection[1]),(boxx,boxy)])
revealedBoxes[firstSelection[0]][firstSelection[1]] = False
revealedBoxes[boxx][boxy] = False
firstSelection = None
...........................
Defining coverBoxesAnimation(board,boxesToCover):
def coverBoxesAnimation(board,boxesToCover):
for coverage in range(BOXSIZE,(-REVEALSPEED)-1,-REVEALSPEED):
drawBoxCovers(board,boxesToCover,coverage)
Part IX: Game Completion
We import tkinter to display message.
.................................................
from tkinter import *
from tkinter import messagebox
Tk().wm_withdraw() #to hide the main window
...............................................
elif hasWon(revealedBoxes):
print("You did it")
messagebox.showinfo('Winner','You did it')
..................................
#has won function
def hasWon(revealedBoxes):
#Return True if all the boxes have been revealed
for i in revealedBoxes:
if False in i:
return False
return True
Part X: Displaying Time of Completion
Add tic before while and toc after winning.
import time
......................................
tic = time.time()
..............................................................
elif hasWon(revealedBoxes):
toc = time.time()
print(toc)
print("You did it")
string = "You completed in " + str(math.floor(toc-tic))+"seconds"
messagebox.showinfo('Winner',string)
#wait for a second and end the program
pygame.time.wait(1000)
pygame.quit()
sys.exit()
Edit gg and add one more shuffle
def getRandomizedBoard():
#Get a list of every possible shape in every possible color
icons = []
for color in ALLCOLORS:
for shape in ALLSHAPES:
icons.append((shape,color))
random.shuffle(icons) #randomize the order of the icons list
numIconsUsed = int(BOARDWIDTH*BOARDHEIGHT/2) #Calculate how many icons are needed
icons = icons[:numIconsUsed]*2 #make two of each
random.shuffle(icons)#added later
#Create the board data structure, with randomly placed icons
board = []
for x in range(BOARDWIDTH):
column = []
for y in range(BOARDHEIGHT):
column.append(icons[0])
del icons[0] #remove the icons as we assign them
board.append(column)
return board
Final Output
Part XI: Final Complete Code
#memory_constants.py
import pygame
from pygame.locals import *
#frames per second, the general speed of the program
FPS = 30
#window width in pixels
WINDOWWIDTH = 640
#Window height in pixels
WINDOWHEIGHT = 480
#Boxsize
BOXSIZE = 90
#GAPsize
GAPSIZE = 20
#Number of columns of icons
BOARDWIDTH = 4
#Number of rows of icons
BOARDHEIGHT = 4
#Board need to have an even numberof boxes for pairs of matches
assert(BOARDWIDTH*BOARDHEIGHT)%2 == 0, "Board needs to have even number of Boxes"
XMARGIN = int((WINDOWWIDTH - (BOARDWIDTH*(BOXSIZE+GAPSIZE)))/2)
YMARGIN = int((WINDOWHEIGHT - (BOARDHEIGHT * (BOXSIZE+GAPSIZE)))/2)
# R G B
GRAY = (100,100,100)
NAVYBLUE = (60,60,100)
WHITE = (255,255,255)
RED = (255,0,0)
GREEN = (0,255,0)
BLUE = (0,0,255)
YELLOW = (255,255,0)
ORANGE = (255,128,0)
PURPLE = (255,0,255)
CYAN = (0,255,255)
BGCOLOR = NAVYBLUE
LIGHTBGCOLOR = GRAY
BOXCOLOR = WHITE
HIGHLIGHTCOLOR = BLUE
DONUT = 'donut'
SQUARE= ' square'
DIAMOND = 'diamond'
LINES = 'lines'
OVAL = 'oval'
ALLCOLORS = (RED,GREEN,BLUE,YELLOW,ORANGE,PURPLE,CYAN)
ALLSHAPES = (DONUT,SQUARE,DIAMOND,LINES,OVAL)
DISPLAYSURF = pygame.display.set_mode((WINDOWWIDTH,WINDOWHEIGHT))
FPSCLOCK = pygame.time.Clock()
#speed of boxes sliding reveals and covers
REVEALSPEED = 8
assert len(ALLCOLORS) * len(ALLSHAPES) * 2 >= BOARDHEIGHT*BOARDWIDTH, "Board is too big for the number of shapes/colors defined"
#memory_functions.py
import pygame,random
from memory_constants import *
#part 4
def getRandomizedBoard():
#Get a list of every possible shape in every possible color
icons = []
for color in ALLCOLORS:
for shape in ALLSHAPES:
icons.append((shape,color))
random.shuffle(icons) #randomize the order of the icons list
numIconsUsed = int(BOARDWIDTH*BOARDHEIGHT/2) #Calculate how many icons are needed
icons = icons[:numIconsUsed]*2 #make two of each
random.shuffle(icons)
#Create the board data structure, with randomly placed icons
board = []
for x in range(BOARDWIDTH):
column = []
for y in range(BOARDHEIGHT):
column.append(icons[0])
del icons[0] #remove the icons as we assign them
board.append(column)
return board
def leftTopCoordsOfBox(boxx,boxy): #part 2
#convert the board coordinates to pixel coordinates
left = boxx * (BOXSIZE + GAPSIZE) + XMARGIN
top = boxy * (BOXSIZE + GAPSIZE)+YMARGIN
return (left,top)
#Part 3
def getBoxAtPixel(x,y):
for boxx in range(BOARDWIDTH):
for boxy in range(BOARDHEIGHT):
left,top = leftTopCoordsOfBox(boxx,boxy)
boxRect = pygame.Rect(left,top,BOXSIZE,BOXSIZE)
if boxRect.collidepoint(x,y):
return(boxx,boxy)
return (None,None)
def drawHighlightBox(boxx,boxy):
left,top = leftTopCoordsOfBox(boxx,boxy)
pygame.draw.rect(DISPLAYSURF,HIGHLIGHTCOLOR,(left-5,top-5,BOXSIZE+10,BOXSIZE+10),4)
#drawing Icons
def drawIcon(shape, color, boxx,boxy):
quater = int(BOXSIZE * 0.25)
half = int(BOXSIZE * 0.5)
left, top = leftTopCoordsOfBox(boxx,boxy)
#draw the shapes
if shape == DONUT:
pygame.draw.circle(DISPLAYSURF,color,(left+half,top+half),half-5)
pygame.draw.circle(DISPLAYSURF,BGCOLOR,(left+half,top+half),quater-5)
elif shape == SQUARE:
pygame.draw.rect(DISPLAYSURF,color,(left+quater,top+quater,BOXSIZE-half,BOXSIZE-half))
elif shape == DIAMOND:
pygame.draw.polygon(DISPLAYSURF,color,((left+half,top),(left+BOXSIZE-1,top+half),(left+half,top+BOXSIZE-1),(left,top+half)))
elif shape == LINES:
for i in range(0,BOXSIZE,4):
pygame.draw.line(DISPLAYSURF,color,(left,top+i),(left+i,top))
pygame.draw.line(DISPLAYSURF,color,(left+i,top+BOXSIZE-1),(left+BOXSIZE-1,top+i))
elif shape == OVAL:
pygame.draw.ellipse(DISPLAYSURF,color,(left,top+quater,BOXSIZE,half))
def getShapeAndColor(board,boxx,boxy):
return board[boxx][boxy][0],board[boxx][boxy][1]
#generate revealedBox data
def generateRevealedBoxesData(val):
revealedBoxes = []
for i in range(BOARDWIDTH):
revealedBoxes.append([val]*BOARDHEIGHT)
return revealedBoxes
#part 7
def drawBoard(board,revealed):
#Draw all the boxes in their covered or revealed state
for boxx in range(BOARDWIDTH):
for boxy in range(BOARDHEIGHT):
left,top = leftTopCoordsOfBox(boxx,boxy)
if not revealed[boxx][boxy]:
#Draw a covered box
pygame.draw.rect(DISPLAYSURF,BOXCOLOR,(left,top,BOXSIZE,BOXSIZE))
else:
#Drwa the (revealed icon)
shape, color = getShapeAndColor(board,boxx,boxy)
drawIcon(shape,color,boxx,boxy)
def drawBoxCovers(board,boxes,coverage):
for box in boxes:
left, top = leftTopCoordsOfBox(box[0],box[1])
pygame.draw.rect(DISPLAYSURF,BGCOLOR,(left,top,BOXSIZE,BOXSIZE))
shape,color = getShapeAndColor(board,box[0],box[1])
drawIcon(shape,color,box[0],box[1])
if coverage > 0:
pygame.draw.rect(DISPLAYSURF,BOXCOLOR,(left,top,coverage,BOXSIZE))
pygame.display.update()
FPSCLOCK.tick(FPS)
#Animating the revealbox
def revealBoxesAnimation(board,boxesToReveal):
#do the box reveal animation
for coverage in range(BOXSIZE,(-REVEALSPEED)-1,-REVEALSPEED):
drawBoxCovers(board,boxesToReveal,coverage)
def coverBoxesAnimation(board,boxesToCover):
for coverage in range(BOXSIZE,(-REVEALSPEED)-1,-REVEALSPEED):
drawBoxCovers(board,boxesToCover,coverage)
#Part 9
def hasWon(revealedBoxes):
#Return True if all the boxes have been revealed
for i in revealedBoxes:
if False in i:
return False
return True
#main.py
import pygame, random,sys
from pygame.locals import *
from tkinter import *
from tkinter import messagebox
Tk().wm_withdraw() #to hide the main window
import time
import math
from memory_functions import *
from memory_constants import *
def main():
pygame.init()
pygame.display.set_caption("Memory Game")
mousex = 0 #used to store x coordinate of mouse event
mousey = 0 #used to store y coordinate of mouse event
#The function to generate a random board
mainBoard = getRandomizedBoard()
#part 7
revealedBoxes = generateRevealedBoxesData(False)
#part 8
#store the (x,y) of the first box clicked
firstSelection = None
tic = time.time()
while True:
#part 8
mouseClicked = False
#Drawing the window
DISPLAYSURF.fill(BGCOLOR)
drawBoard(mainBoard,revealedBoxes)
for event in pygame.event.get():
if event.type == QUIT or (event.type == KEYUP and event.key == K_ESCAPE):
pygame.quit()
sys.exit()
elif event.type == MOUSEMOTION:
mousex,mousey = event.pos
elif event.type == MOUSEBUTTONUP:
mousex,mousey = event.pos
mouseClicked = True
boxx,boxy = getBoxAtPixel(mousex,mousey)
if boxx != None and boxy != None:
#part 7
if not revealedBoxes[boxx][boxy]:
drawHighlightBox(boxx,boxy)
if not revealedBoxes[boxx][boxy] and mouseClicked:
revealBoxesAnimation(mainBoard,[(boxx,boxy)])
#part 8
#set the box as revealed
revealedBoxes[boxx][boxy]=True
if firstSelection == None:#the current box was the first box clicked
firstSelection = (boxx,boxy)
else:#the current box was the second box clicked
#check if there is a match between the two icons
icon1Shape, icon1Color = getShapeAndColor(mainBoard,firstSelection[0],firstSelection[1])
icon2Shape, icon2Color = getShapeAndColor(mainBoard,boxx,boxy)
if icon1Shape != icon2Shape or icon1Color != icon2Color:
#icons do not match recover up both selections
pygame.time.wait(1000)
coverBoxesAnimation(mainBoard,[(firstSelection[0],firstSelection[1]),(boxx,boxy)])
revealedBoxes[firstSelection[0]][firstSelection[1]] = False
revealedBoxes[boxx][boxy] = False
#part 9
elif hasWon(revealedBoxes):
toc = time.time()
print(toc)
print("You did it")
string = "You completed in " + str(math.floor(toc-tic))+"seconds"
messagebox.showinfo('Winner',string)
#wait for a second and end the program
pygame.time.wait(1000)
pygame.quit()
sys.exit()
firstSelection = None
#Redraw the screen and wait a clock tick
pygame.display.flip()
FPSCLOCK.tick(FPS)
if __name__ == "__main__":
main()