6. import random, pygame, sys
7. from pygame.locals import *
8.
9. FPS = 30 # frames per second, the general speed of the program
10. WINDOWWIDTH = 640 # size of window's width in pixels
11. WINDOWHEIGHT = 480 # size of windows' height in pixels
12. REVEALSPEED = 8 # speed boxes' sliding reveals and covers
13. BOXSIZE = 40 # size of box height & width in pixels
14. GAPSIZE = 10 # size of gap between boxes in pixels
15. BOARDWIDTH = 10 # number of columns of icons
16. BOARDHEIGHT = 7 # number of rows of icons
17. assert (BOARDWIDTH * BOARDHEIGHT) % 2 == 0, 'Board needs to have an even number of boxes for pairs of matches.'
18. XMARGIN = int((WINDOWWIDTH - (BOARDWIDTH * (BOXSIZE + GAPSIZE))) / 2)
19. YMARGIN = int((WINDOWHEIGHT - (BOARDHEIGHT * (BOXSIZE + GAPSIZE))) / 2)
20.
21. # R G B
22. GRAY = (100, 100, 100)
23. NAVYBLUE = ( 60, 60, 100)
24. WHITE = (255, 255, 255)
25. RED = (255, 0, 0)
26. GREEN = ( 0, 255, 0)
27. BLUE = ( 0, 0, 255)
28. YELLOW = (255, 255, 0)
29. ORANGE = (255, 128, 0)
30. PURPLE = (255, 0, 255)
31. CYAN = ( 0, 255, 255)
32.
33. BGCOLOR = NAVYBLUE
34. LIGHTBGCOLOR = GRAY
35. BOXCOLOR = WHITE
36. HIGHLIGHTCOLOR = BLUE
37.
38. DONUT = 'donut'
39. SQUARE = 'square'
40. DIAMOND = 'diamond'
41. LINES = 'lines'
42. OVAL = 'oval'
43.
44. ALLCOLORS = (RED, GREEN, BLUE, YELLOW, ORANGE, PURPLE, CYAN)
45. ALLSHAPES = (DONUT, SQUARE, DIAMOND, LINES, OVAL)
46. assert len(ALLCOLORS) * len(ALLSHAPES) * 2 >= BOARDWIDTH * BOARDHEIGHT, "Board is too big for the number of shapes/colors defined."
47.
48. def main():
49. global FPSCLOCK, DISPLAYSURF
50. pygame.init()
51. FPSCLOCK = pygame.time.Clock()
52. DISPLAYSURF = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT))
53.
54. mousex = 0 # used to store x coordinate of mouse event
55. mousey = 0 # used to store y coordinate of mouse event
56. pygame.display.set_caption('Memory Game')
57.
58. mainBoard = getRandomizedBoard()
59. revealedBoxes = generateRevealedBoxesData(False)
60.
61. firstSelection = None # stores the (x, y) of the first box clicked.
62.
63. DISPLAYSURF.fill(BGCOLOR)
64. startGameAnimation(mainBoard)
65.
66. while True: # main game loop
67. mouseClicked = False
68.
69. DISPLAYSURF.fill(BGCOLOR) # drawing the window
70. drawBoard(mainBoard, revealedBoxes)
71.
72. for event in pygame.event.get(): # event handling loop
73. if event.type == QUIT or (event.type == KEYUP and event.key == K_ESCAPE):
74. pygame.quit()
75. sys.exit()
76. elif event.type == MOUSEMOTION:
77. mousex, mousey = event.pos
78. elif event.type == MOUSEBUTTONUP:
79. mousex, mousey = event.pos
80. mouseClicked = True
81.
82. boxx, boxy = getBoxAtPixel(mousex, mousey)
83. if boxx != None and boxy != None:
84. # The mouse is currently over a box.
85. if not revealedBoxes[boxx][boxy]:
86. drawHighlightBox(boxx, boxy)
87. if not revealedBoxes[boxx][boxy] and mouseClicked:
88. revealBoxesAnimation(mainBoard, [(boxx, boxy)])
89. revealedBoxes[boxx][boxy] = True # set the box as "revealed"
90. if firstSelection == None: # the current box was the first box clicked
91. firstSelection = (boxx, boxy)
92. else: # the current box was the second box clicked
93. # Check if there is a match between the two icons.
94. icon1shape, icon1color = getShapeAndColor(mainBoard, firstSelection[0], firstSelection[1])
95. icon2shape, icon2color = getShapeAndColor(mainBoard, boxx, boxy)
96.
97. if icon1shape != icon2shape or icon1color != icon2color:
98. # Icons don't match. Re-cover up both selections.
99. pygame.time.wait(1000) # 1000 milliseconds = 1 sec
100. coverBoxesAnimation(mainBoard, [(firstSelection[0], firstSelection[1]), (boxx, boxy)])
101. revealedBoxes[firstSelection[0]][firstSelection [1]] = False
102. revealedBoxes[boxx][boxy] = False
103. elif hasWon(revealedBoxes): # check if all pairs found
104. gameWonAnimation(mainBoard)
105. pygame.time.wait(2000)
107. # Reset the board
108. mainBoard = getRandomizedBoard()
109. revealedBoxes = generateRevealedBoxesData(False)
110.
111. # Show the fully unrevealed board for a se