之前在Coursera上学习python课程的时候写的一个memory的小游戏。属于记忆类的小游戏。
原来的memory是所有的纸牌都排成一列的,通过点击来翻牌,如果最近的两次翻的牌都一样那么就成功了,牌会保持翻开的状态。如下图所示:
实现代码:
# implementation of card game - Memory
# by Sean
import simplegui
import random
# helper function to initialize globals
def init():
global deck, exposed, card_list, moves
deck = [(i // 2) for i in range(0, 16)]
random.shuffle(deck)
exposed = []
for i in range(0, 16):
exposed.append(False)
card_list = []
moves = 0
l.set_text("Moves = 0")
# define event handlers
def mouseclick(pos):
global exposed, state, moves
card_checked = int(pos[0]) * 2 // 100
if exposed[card_checked] == True:
return
moves += 1
l.set_text("Moves = " + str((moves + 1) // 2))
exposed[card_checked] = True
if len(card_list) == 0:
card_list.append(card_checked)
elif len(card_list) == 1:
card_list.append(card_checked)
else:
card1, card2 = card_list.pop(), card_list.pop()
if deck[card1] != deck[card2]:
exposed[card1], exposed[card2] = False, False
card_list.append(card_checked)
# cards are logically 50x100 pixels in size
def draw(canvas):
SIDE_LEN = 50
for i in range(0, 16):
canvas.draw_text(str(deck[i]), [5 + SIDE_LEN * i, 75], 60, "White")
if not exposed[i]:
canvas.draw_polygon(([SIDE_LEN * i, 0], [SIDE_LEN * (i + 1), 0], [SIDE_LEN * (i + 1), 100], [SIDE_LEN * i, 100]), 1, "Red", "Green")
# create frame and add a button and labels
frame = simplegui.create_frame("Memory", 800, 100)
frame.add_button("Restart", init)
l = frame.add_label("Moves = 0")
# initialize global variables
init()
# register event handlers
frame.set_mouseclick_handler(mouseclick)
frame.set_draw_handler(draw)
# get things rolling
frame.start()
现做出如下改动:
将牌面放在一个二维的平面上。
将原来的牌的正面数字以及牌的背面均用图片代替。
使用pygame.
# memory-Hayao edition
# By Seandor
import pygame, sys, random
from pygame.locals import *
FPS = 30 # frames per second setting
WINDOWWIDTH = 800
WINDOWHEIGHT = 600
CARDWIDTH = 100
CARDHEIGHT = 87
CARDNUM = 36
# colors R G B
BLACK = ( 0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = ( 0, 255, 0)
BLUE = ( 0, 0, 255)
# loading image source
MASTERPIECE_SURF = pygame.image.load('masterpiece.png')
CARDBACK_SURF = pygame.image.load('back.png')
BACKGROUND_SURF = pygame.image.load('totoro.png')
class GameState():
def __init__(self, exposed, state, card_list, moves):
self.exposed = exposed
self.state = state
self.card_list = card_list
self.moves = moves
def createDeck(source):
''' Return a list of Surface Object.
Use the image source to create a deck.
'''
deck = []
for i in range(CARDNUM // 2):
card = source.subsurface((CARDWIDTH * i, 0, CARDWIDTH, CARDHEIGHT))
deck.extend([card] * 2)
return deck
def main():
global FPSCLOCK, DISPLAYSURF, BASICFONT, DECK
pygame.init()
FPSCLOCK = pygame.time.Clock()
DISPLAYSURF = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT))
BASICFONT = pygame.font.Font('freesansbold.ttf', 18)
pygame.display.set_caption('Memory-Hayao edition')
DECK = createDeck(MASTERPIECE_SURF)
random.shuffle(DECK)
exposed = [False] * CARDNUM
state = 0
card_list = []
moves = 0
gameState = GameState(exposed, state, card_list, moves)
showStartScreen()
# add background music
## pygame.mixer.music.load('totoro.mp3')
## pygame.mixer.music.play(-1, 0.0)
# draw background
DISPLAYSURF.blit(BACKGROUND_SURF, (0, 0))
while True:
gameStart(gameState)
gameOver()
def showStartScreen():
pass
def gameStart(gameState):
mouseClicked = False
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
elif event.type == MOUSEMOTION:
mousepos = event.pos
elif event.type == MOUSEBUTTONUP:
mousepos = event.pos
mouseClicked = True
if mouseClicked:
onClick(gameState, mousepos)
drawCards(gameState)
pygame.display.update()
FPSCLOCK.tick(FPS)
def onClick(gameState, mousepos):
if mousepos[0] < 150 or mousepos[0] > 750 or mousepos[1] < 39 or mousepos[1] > 561:
return
card_checked = (int(mousepos[0] - 150) // CARDWIDTH) + (int(mousepos[1] - 39) // CARDHEIGHT) * 6
if gameState.exposed[card_checked] == True:
return
gameState.moves += 1
gameState.exposed[card_checked] = True
if gameState.state == 0:
gameState.card_list.append(card_checked)
gameState.state = 1
elif gameState.state == 1:
gameState.card_list.append(card_checked)
gameState.state = 2
else:
card1, card2 = gameState.card_list.pop(), gameState.card_list.pop()
if DECK[card1] != DECK[card2]:
gameState.exposed[card1], gameState.exposed[card2] = False, False
gameState.card_list.append(card_checked)
gameState.state = 1
def drawCards(gameState):
startDrawX = 150
startDrawY = 39
# draw a 6 * 6 board
for i in range(6):
for j in range(6):
DISPLAYSURF.blit(DECK[i * 6 + j], (startDrawX + CARDWIDTH * j, startDrawY + CARDHEIGHT *i))
if not gameState.exposed[i * 6 + j]:
DISPLAYSURF.blit(CARDBACK_SURF, (startDrawX + CARDWIDTH * j, startDrawY + CARDHEIGHT *i))
def gameOver():
pass
if __name__ == '__main__':
main()
可以看到里面的一些函数还是空的。因为没有太多时间和精力去完善它,尽管是很小的东西,但是要做的精致还是很困难的。
下面是游戏运行的截图:
当所有牌都是正面的时候就gameover了。
体会感悟:
虽然做的东西很简单,但全都是自己一点一点做的,每张图片,每个图片的处理,每行代码都认真的考虑过,修改过,所以完成的时候还是挺开心的。功能方面还是有很多可以添加和改进的,可以很容易想到的就有,对于点击次数的计数,还可以添加关卡设置不同难度,玩家排名数据统计等等,但要全部实现实在精力有限。或许有闲暇时间会来再次改进。(剪图片挺有意思的^-^)