# Memory Puzzle, by Al Sweigart al@inventwithpython.com
# (Requires Pygame) A simple memory matching game.
__version__ = 1
import random, pygame, sys
from pygame.locals import *
FPS = 20 # frames per second, the general speed of the program 每秒帧数,程序的一般速度
WINDOWWIDTH = 640 # size of window's width in pixels 窗口宽度的大小(像素)
WINDOWHEIGHT = 480 # size of windows' height in pixels
REVEALSPEED = 8 # speed boxes' sliding reveals and covers
BOXSIZE = 50 # size of box height & width in pixels 框的高度和宽度大小(像素)
GAPSIZE = 10 # size of gap between boxes in pixels
BOARDWIDTH = 10 # number of columns of icons 图标列数
BOARDHEIGHT = 7 # number of rows of icons
assert (BOARDWIDTH * BOARDHEIGHT) % 2 == 0, 'Board needs to have an even number of boxes for pairs of matches.'
XMARGIN = int((WINDOWWIDTH - (BOARDWIDTH * (BOXSIZE + GAPSIZE))) / 2)
YMARGIN = int((WINDOWHEIGHT - (BOARDHEIGHT * (BOXSIZE + GAPSIZE))) / 2)
#RGB
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
# === 新增:水果图标定义 ===
APPLE = 'apple'
BANANA = 'banana'
#ORANGE = 'orange'
STRAWBERRY = 'strawberry'
GRAPE = 'grape'
WATERMELON = 'watermelon'
PEAR = 'pear'
PINEAPPLE = 'pineapple'
CHERRY = 'cherry'
LEMON = 'lemon'
ALLCOLORS = (RED, GREEN, BLUE, YELLOW, ORANGE, PURPLE, CYAN)
#ALLSHAPES = (APPLE,BANANA,ORANGE,STRAWBERRY,GRAPE,WATERMELON,PEAR,PINEAPPLE,CHERRY,LEMON)
ALLSHAPES = (APPLE,BANANA,PINEAPPLE,STRAWBERRY,GRAPE)
assert len(ALLCOLORS) * len(
ALLSHAPES) * 2 >= BOARDWIDTH * BOARDHEIGHT, "Board is too big for the number of shapes/colors defined."
def main():
global FPSCLOCK, DISPLAYSURF, BASICFONT
pygame.init()
FPSCLOCK = pygame.time.Clock()
DISPLAYSURF = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT))
BASICFONT = pygame.font.Font('freesansbold.ttf', 24) # 新增字体用于界面文字
pygame.display.set_caption('Memory Game')
# 显示初始界面
showStartScreen()
while True: # 主游戏循环
# 游戏逻辑保持不变...
mousex = 0 # used to store x coordinate of mouse event 用于存储鼠标事件的x坐标
mousey = 0 # used to store y coordinate of mouse event
mainBoard = getRandomizedBoard()
revealedBoxes = generateRevealedBoxesData(False)
firstSelection = None # stores the (x, y) of the first box clicked. 存储单击的第一个框的(x,y)
DISPLAYSURF.fill(BGCOLOR)
startGameAnimation(mainBoard)
game_running = True
while game_running: # 游戏运行循环
mouseClicked = False
DISPLAYSURF.fill(BGCOLOR) # drawing the window 绘制窗口
drawBoard(mainBoard, revealedBoxes)
for event in pygame.event.get(): # event handling loop 事件处理循环
if event.type == QUIT or (event.type == KEYUP and event.key == K_ESCAPE):
game_running = False
showExitScreen() # 显示退出界面
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:
# The mouse is currently over a box. 鼠标当前位于一个框上
if not revealedBoxes[boxx][boxy]:
drawHighlightBox(boxx, boxy)
if not revealedBoxes[boxx][boxy] and mouseClicked:
revealBoxesAnimation(mainBoard, [(boxx, boxy)])
revealedBoxes[boxx][boxy] = True # set the box as "revealed" 将盒子设置为“显示”
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 don't match. Re-cover up both selections. 图标不匹配。重新覆盖这两个选项。
pygame.time.wait(1000) # 1000 milliseconds = 1 sec
coverBoxesAnimation(mainBoard, [(firstSelection[0], firstSelection[1]), (boxx, boxy)])
revealedBoxes[firstSelection[0]][firstSelection[1]] = False
revealedBoxes[boxx][boxy] = False
elif hasWon(revealedBoxes): # check if all pairs found
gameWonAnimation(mainBoard)
pygame.time.wait(2000)
# Reset the board
mainBoard = getRandomizedBoard()
revealedBoxes = generateRevealedBoxesData(False)
# Show the fully unrevealed board for a second.
drawBoard(mainBoard, revealedBoxes)
pygame.display.update()
pygame.time.wait(1000)
# 回到初始界面
game_running = False
showStartScreen()
firstSelection = None # reset firstSelection variable
# Redraw the screen and wait a clock tick.
pygame.display.update()
FPSCLOCK.tick(FPS)
def showStartScreen():
"""显示游戏初始界面"""
while True:
DISPLAYSURF.fill(BGCOLOR)
# 绘制标题
title_font = pygame.font.Font('freesansbold.ttf', 48)
title_surf = title_font.render('Memory Puzzle', True, WHITE)
title_rect = title_surf.get_rect()
title_rect.center = (WINDOWWIDTH // 2, WINDOWHEIGHT // 3)
DISPLAYSURF.blit(title_surf, title_rect)
# 绘制作者信息
author_font = pygame.font.Font('freesansbold.ttf', 16)
author_surf = author_font.render('By Al Sweigart', True, WHITE)
author_rect = author_surf.get_rect()
author_rect.center = (WINDOWWIDTH // 2, WINDOWHEIGHT // 3 + 50)
DISPLAYSURF.blit(author_surf, author_rect)
# 绘制开始游戏按钮
button_color = BLUE
button_rect = pygame.Rect(WINDOWWIDTH // 2 - 100, WINDOWHEIGHT // 2, 200, 50)
pygame.draw.rect(DISPLAYSURF, button_color, button_rect)
pygame.draw.rect(DISPLAYSURF, WHITE, button_rect, 2) # 边框
button_font = pygame.font.Font('freesansbold.ttf', 24)
button_surf = button_font.render('Start Game', True, WHITE)
button_rect_text = button_surf.get_rect(center=button_rect.center)
DISPLAYSURF.blit(button_surf, button_rect_text)
# 绘制退出游戏按钮
exit_button_rect = pygame.Rect(WINDOWWIDTH // 2 - 100, WINDOWHEIGHT // 2 + 70, 200, 50)
pygame.draw.rect(DISPLAYSURF, button_color, exit_button_rect)
pygame.draw.rect(DISPLAYSURF, WHITE, exit_button_rect, 2) # 边框
exit_button_surf = button_font.render('Exit Game', True, WHITE)
exit_button_rect_text = exit_button_surf.get_rect(center=exit_button_rect.center)
DISPLAYSURF.blit(exit_button_surf, exit_button_rect_text)
# 事件处理
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
elif event.type == MOUSEBUTTONUP:
mouse_x, mouse_y = event.pos
if button_rect.collidepoint(mouse_x, mouse_y):
return # 退出此函数,开始游戏
elif exit_button_rect.collidepoint(mouse_x, mouse_y):
pygame.quit()
sys.exit()
pygame.display.update()
FPSCLOCK.tick(FPS)
def showExitScreen():
"""显示游戏退出界面"""
while True:
DISPLAYSURF.fill(BGCOLOR)
# 绘制退出信息
title_font = pygame.font.Font('freesansbold.ttf', 48)
title_surf = title_font.render('Thanks for Playing!', True, WHITE)
title_rect = title_surf.get_rect()
title_rect.center = (WINDOWWIDTH // 2, WINDOWHEIGHT // 3)
DISPLAYSURF.blit(title_surf, title_rect)
# 绘制再次游戏按钮
button_color = GREEN
button_rect = pygame.Rect(WINDOWWIDTH // 2 - 100, WINDOWHEIGHT // 2, 200, 50)
pygame.draw.rect(DISPLAYSURF, button_color, button_rect)
pygame.draw.rect(DISPLAYSURF, WHITE, button_rect, 2) # 边框
button_font = pygame.font.Font('freesansbold.ttf', 24)
button_surf = button_font.render('Play Again', True, WHITE)
button_rect_text = button_surf.get_rect(center=button_rect.center)
DISPLAYSURF.blit(button_surf, button_rect_text)
# 绘制退出游戏按钮
exit_button_rect = pygame.Rect(WINDOWWIDTH // 2 - 100, WINDOWHEIGHT // 2 + 70, 200, 50)
pygame.draw.rect(DISPLAYSURF, RED, exit_button_rect)
pygame.draw.rect(DISPLAYSURF, WHITE, exit_button_rect, 2) # 边框
exit_button_surf = button_font.render('Exit Game', True, WHITE)
exit_button_rect_text = exit_button_surf.get_rect(center=exit_button_rect.center)
DISPLAYSURF.blit(exit_button_surf, exit_button_rect_text)
# 事件处理
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
elif event.type == MOUSEBUTTONUP:
mouse_x, mouse_y = event.pos
if button_rect.collidepoint(mouse_x, mouse_y):
return # 退出此函数,重新开始游戏
elif exit_button_rect.collidepoint(mouse_x, mouse_y):
pygame.quit()
sys.exit()
pygame.display.update()
FPSCLOCK.tick(FPS)
def generateRevealedBoxesData(val):
revealedBoxes = []
for i in range(BOARDWIDTH):
revealedBoxes.append([val] * BOARDHEIGHT)
return revealedBoxes
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 splitIntoGroupsOf(groupSize, theList):
# splits a list into a list of lists, where the inner lists have at
# most groupSize number of items.
result = []
for i in range(0, len(theList), groupSize):
result.append(theList[i:i + groupSize])
return result
def leftTopCoordsOfBox(boxx, boxy):
# Convert board coordinates to pixel coordinates
left = boxx * (BOXSIZE + GAPSIZE) + XMARGIN
top = boxy * (BOXSIZE + GAPSIZE) + YMARGIN
return (left, top)
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 drawIcon(shape, color, boxx, boxy):
quarter = int(BOXSIZE * 0.25) # syntactic sugar
half = int(BOXSIZE * 0.5) # syntactic sugar
left, top = leftTopCoordsOfBox(boxx, boxy) # get pixel coords from board coords 从板坐标中获取像素坐标
# Draw the shapes 绘制形状
#, , , , , WATERMELON, PEAR, PINEAPPLE, CHERRY, LEMON
if shape == APPLE:
pygame.draw.circle(DISPLAYSURF, color, (left + BOXSIZE // 2, top + BOXSIZE // 2), BOXSIZE // 2 - 2)
pygame.draw.line(DISPLAYSURF, GREEN,
(left + BOXSIZE // 2, top + BOXSIZE // 4),
(left + BOXSIZE // 2 + BOXSIZE // 8, top + BOXSIZE // 6), 2)
elif shape == BANANA:
points = [
(left + BOXSIZE // 4, top + BOXSIZE // 4),
(left + BOXSIZE * 3 // 4, top + BOXSIZE // 3),
(left + BOXSIZE * 2 // 3, top + BOXSIZE * 3 // 4),
(left + BOXSIZE // 5, top + BOXSIZE * 2 // 3)]
pygame.draw.polygon(DISPLAYSURF, color, points)
elif shape == PINEAPPLE:
points = [
(left + BOXSIZE // 4, top + BOXSIZE // 4),
(left + BOXSIZE * 3 // 4, top + BOXSIZE // 4),
(left + BOXSIZE * 3 // 4, top + BOXSIZE * 3 // 4),
(left + BOXSIZE // 4, top + BOXSIZE * 3 // 4)
]
pygame.draw.polygon(DISPLAYSURF, color, points)
# 叶子
pygame.draw.polygon(DISPLAYSURF, GREEN, [
(left + BOXSIZE // 4, top + BOXSIZE // 4),
(left + BOXSIZE // 2, top + BOXSIZE // 8),
(left + BOXSIZE * 3 // 4, top + BOXSIZE // 4)
])
elif shape == STRAWBERRY:
pygame.draw.polygon(DISPLAYSURF, color, [
(left + BOXSIZE // 2, top + BOXSIZE // 6),
(left + BOXSIZE * 5 // 6, top + BOXSIZE * 5 // 6),
(left + BOXSIZE // 6, top + BOXSIZE * 5 // 6)
])
# 叶子
pygame.draw.polygon(DISPLAYSURF, GREEN, [
(left + BOXSIZE // 3, top + BOXSIZE // 6),
(left + BOXSIZE * 2 // 3, top + BOXSIZE // 6),
(left + BOXSIZE * 5 // 6, top + BOXSIZE // 3),
(left + BOXSIZE // 6, top + BOXSIZE // 3)
])
# 白色斑点
pygame.draw.circle(DISPLAYSURF, WHITE, (left + BOXSIZE // 3, top + BOXSIZE // 3), 2)
pygame.draw.circle(DISPLAYSURF, WHITE, (left + BOXSIZE * 2 // 3, top + BOXSIZE // 3), 2)
pygame.draw.circle(DISPLAYSURF, WHITE, (left + BOXSIZE // 2, top + BOXSIZE // 2), 2)
elif shape == GRAPE:
pygame.draw.ellipse(DISPLAYSURF, color, (left + BOXSIZE // 4, top + BOXSIZE // 6, BOXSIZE // 3, BOXSIZE // 3))
pygame.draw.ellipse(DISPLAYSURF, color, (left + BOXSIZE // 2, top + BOXSIZE // 6, BOXSIZE // 3, BOXSIZE // 3))
pygame.draw.ellipse(DISPLAYSURF, color, (left + BOXSIZE // 4, top + BOXSIZE // 3, BOXSIZE // 3, BOXSIZE // 3))
pygame.draw.ellipse(DISPLAYSURF, color, (left + BOXSIZE // 2, top + BOXSIZE // 3, BOXSIZE // 3, BOXSIZE // 3))
def getShapeAndColor(board, boxx, boxy):
# shape value for x, y spot is stored in board[x][y][0]
# color value for x, y spot is stored in board[x][y][1]
return board[boxx][boxy][0], board[boxx][boxy][1]
def drawBoxCovers(board, boxes, coverage):
# Draws boxes being covered/revealed. "boxes" is a list
# of two-item lists, which have the x & y spot of the box.
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: # only draw the cover if there is an coverage
pygame.draw.rect(DISPLAYSURF, BOXCOLOR, (left, top, coverage, BOXSIZE))
pygame.display.update()
FPSCLOCK.tick(FPS)
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):
# Do the "box cover" animation. 制作“盒子封面”动画。
for coverage in range(0, BOXSIZE + REVEALSPEED, REVEALSPEED):
drawBoxCovers(board, boxesToCover, coverage)
def drawBoard(board, revealed):
# Draws all of 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)
def drawHighlightBox(boxx, boxy):
left, top = leftTopCoordsOfBox(boxx, boxy)
pygame.draw.rect(DISPLAYSURF, HIGHLIGHTCOLOR, (left - 5, top - 5, BOXSIZE + 10, BOXSIZE + 10), 4)
def startGameAnimation(board):
# Randomly reveal the boxes 8 at a time. 一次随机显示8个框。
coveredBoxes = generateRevealedBoxesData(False)
boxes = []
for x in range(BOARDWIDTH):
for y in range(BOARDHEIGHT):
boxes.append((x, y))
random.shuffle(boxes)
boxGroups = splitIntoGroupsOf(4, boxes)
drawBoard(board, coveredBoxes)
for boxGroup in boxGroups:
revealBoxesAnimation(board, boxGroup)
coverBoxesAnimation(board, boxGroup)
def gameWonAnimation(board):
# flash the background color when the player has won 当玩家获胜时,闪烁背景颜色
coveredBoxes = generateRevealedBoxesData(True)
color1 = LIGHTBGCOLOR
color2 = BGCOLOR
for i in range(30):
color1, color2 = color2, color1 # swap colors 交换颜色
DISPLAYSURF.fill(color1)
drawBoard(board, coveredBoxes)
pygame.display.update()
pygame.time.wait(100)
def hasWon(revealedBoxes):
# Returns True if all the boxes have been revealed, otherwise False 如果所有框都已显示,则返回True,否则返回False
for i in revealedBoxes:
if False in i:
return False # return False if any boxes are covered. 如果有任何箱子被覆盖,则返回False。
return True
if __name__ == '__main__':
main()
依据这个代码生成python记忆游戏的实现与分析的论文框架
最新发布