python“记忆益智游戏”

2024-10-01 22:35:41 发布

您现在位置:Python中文网/ 问答频道 /正文

import random, pygame, sys
from pygame.locals import *

FPS     = 30 # general speed of the program
WinW    = 640 # size width of window
WinH    = 480 # size height of window
RevSpd  = 8 # reveals and covers speed
BxSz    = 40 # size of box both of H & W px
GapSz   = 10 # size between boxes in px
BrdW    = 4 # number of columns of icons
BrdH    = 3 # rows
assert (BrdW * BrdH) % 2 == 0, 'Board needs to have an even number of boxes for pairs of matches.'
XMarg = int((WinW - (BrdW * (BxSz + GapSz))) / 2)
YMarg = int((WinH - (BrdH * (BxSz + GapSz))) / 2)

#           R    G    B
Gray    = (100, 100, 100) 
NavyBlu = (60, 60, 100) 
Whi     = (255, 255, 255) 
Rd      = (255, 0, 0) 
Grn     = (0, 255, 0) 
Blu     = (0, 0, 255) 
Yllw    = (255, 255, 0) 
Org     = (255, 128, 0) 
Prpl    = (255, 0, 255) 
Cyan    = (0, 255, 255) 

BgClr           = NavyBlu
LghtBgClr       = Gray
BxClr           = Whi
HighlightClr    = Blu

Donut   = 'donut'
Square  = 'square'
Diamond = 'diamond'
Lines   = 'lines'
Oval    = 'oval'

AllClr  = (Rd, Grn, Blu, Yllw, Org, Prpl, Cyan)
AllShps = (Donut, Square, Diamond, Lines, Oval)
assert len(AllClr) * len(AllShps) * 2 >= BrdW * BrdH, "Board is too big for the number of shapes/colors defined."

def main():
    global FpsClk, DiS
    pygame.init()
    FpsClk = pygame.time.Clock()
    DiS = pygame.display.set_mode((WinW, WinH))

    msx = 0 # used to store x coordinate of mouse event
    msy = 0 # y coordinate
    pygame.display.set_caption('Memory Game')

    mainBoard = getRandomizedBoard()
    revealedBoxes = generateRevealedBoxesData(False)

    firstSelection = None # stores the (x, y) of the first box clicked

    DiS.fill(BgClr)
    startGameAnimation(mainBoard)

    while True:
        mouseClicked = False

        DiS.fill(BgClr) # draw the window
        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:
                msx, msy = event.pos
            elif event.type == MOUSEBUTTONUP:
                msx, msy = event.pos
                mouseClicked = True

        boxx, boxy = getBoxAtPixel(msx, msy)
        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's a match between the two icons
                        ishp1, iclr1 = getShapeAndColor(mainBoard, firstSelection[0], firstSelection[1])
                        ishp2, iclr2 = getShapeAndColor(mainBoard, boxx, boxy)

                        if ishp1 != ishp2 or iclr1 != iclr2:
                            # icons don't match re-cover up both selection
                            pygame.time.wait(1000) # 1000 ml/s = 1 s
                            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)

                            # replay the start game animation
                            startGameAnimation(mainBoard)
                            firstSelection = None # reset firstSelect variable

                            # redraw the screen and wait a clock tick
                            pygame.display.update()
                            FpsClk.tick(FPS)

def generateRevealedBoxesData(val):
    revealedBoxes = []
    for i in range(BrdW):
        revealedBoxes.append([val] * BrdH)
    return revealedBoxes

def getRandomizedBoard():
    # get a list of every possible shape in every possible color
    icons = []
    for color in AllClr:
        for shape in AllShps:
            icons.append((shape, color))

    random.shuffle(icons) # randomize the order of the icons list
    numIcnUsd = int(BrdW * BrdH / 2) # calculate how many icons are needed
    icons = icons[:numIcnUsd] * 2 # make two of each
    random.shuffle(icons)

    # create the board data structure, with randomly placed icons
    board = []
    for x in range(BrdW):
        column = []
        for y in range(BrdH):
            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 list, 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 px coordinates
    left = boxx * (BxSz + GapSz) + XMarg
    top = boxy * (BxSz + GapSz) + YMarg
    return (left, top)

def getBoxAtPixel(x, y):
    for boxx in range(BrdW):
        for boxy in range(BrdH):
            left, top = leftTopCoordsOfBox(boxx, boxy)
            boxRect = pygame.Rect(left, top, BxSz, BxSz)
            if boxRect.collidepoint(x, y):
                return (boxx, boxy)
    return (None, None)

def drawIcon(shape, color, boxx, boxy):
    quarter = int(BxSz * 0.25) # syntactic sugar
    half    = int(BxSz * 0.5) # syntactic sugar

    left, top = leftTopCoordsOfBox(boxx, boxy) # get pixel coords from board coords
    # draw the shapes
    if shape == Donut:
        pygame.draw.circle(DiS, color, (left + half, top + half), half - 5)
        pygame.draw.circle(DiS, BgClr, (left + half, top + half), quarter - 5)
    elif shape == Square:
        pygame.draw.rect(DiS, color, (left + quarter, top + quarter, BxSz - half, BxSz - half))
    elif shape == Diamond:
        pygame.draw.polygon(DiS, color, ((left + half, top), (left + BxSz - 1, top + half), (left + half, top + BxSz - 1), (left, top + half)))
    elif shape == Lines:
        for i in range(0, BxSz, 4):
            pygame.draw.line(DiS, color, (left, top + i), (left + i, top))
            pygame.draw.line(DiS, color, (left + i, top + BxSz - 1), (left + BxSz - 1, top + i))
    elif shape == Oval:
        pygame.draw.ellipse(DiS, color, (left, top + quarter, BxSz, half))        

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(DiS, BgClr, (left, top, BxSz, BxSz))
        shape, color = getShapeAndColor(board, box[0], box[1])
        drawIcon(shape, color, box[0], box[1])
        if coverage > 0: # only draw the cover if there's an coverage
            pygame.draw.rect(DiS, BxClr, (left, top, coverage, BxSz))
    pygame.display.update()
    FpsClk.tick(FPS)

def revealBoxesAnimation(board, boxesToReveal):
    # do the "box reveal" animation
    for coverage in range (BxSz, (-RevSpd) - 1, - RevSpd):
        drawBoxCovers(board, boxesToReveal, coverage)

def coverBoxesAnimation(board, boxesToCover):
    # do the "box cover" animation
    for coverage in range(0, BxSz + RevSpd, RevSpd):
        drawBoxCovers(board, boxesToCover, coverage)

def drawBoard(board, revealed):
    # draws all of the boxes in their covered or revealed state
    for boxx in range(BrdW):
        for boxy in range(BrdH):
            left, top = leftTopCoordsOfBox(boxx, boxy)
            if not revealed[boxx][boxy]:
                # draw a covered box
                pygame.draw.rect(DiS, BxClr, (left, top, BxSz, BxSz))
            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(DiS, HighlightClr, (left - 5, top - 5, BxSz + 10, BxSz + 10), 4)

def startGameAnimation(board):
    # randomly reveal the boxes 8 at a time
    coveredBoxes = generateRevealedBoxesData(False)
    boxes = []
    for x in range(BrdW):
        for y in range(BrdH):
            boxes.append((x, y))
    random.shuffle(boxes)
    boxGroups = splitIntoGroupsOf(8, 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 = LghtBgClr
    color2 = BgClr

    for i in range(13):
        color1, color2 = color2, color1 # swap color
        DiS.fill(color1)
        drawBoard(board, coveredBoxes)
        pygame.display.update()
        pygame.time.wait(3000)

def hasWon(revealedBoxes):
    # returns True if all the boxes have been revealed, otherwisw False
    for i in  revealedBoxes:
        if False in i:
            return False # return False if any boxes are covered
    return True

if __name__ == '__main__':
    main()

我对这个“记忆之谜”游戏有问题。。。。。 脚本是从我的电子书,我只是想学习最基本的。。 我试着把所有的都打出来,但都没发现错别字。。 也许是我的错,但我想知道我犯了什么错。。。在

所以有个问题。。在

当我完成选择第一块板时,它当然会显示出来,但是在第二块板之后,我选择了它,它会检查它是否与两块板不匹配,然后重新覆盖。。。 虽然我会选择另一块板,但板不会显示出来,因为它与我选择的第一块板粘在一起。。。 所以,第三个选择我会选择尽快掩盖,不会透露。。 我怎么解决这个问题,请你们的指导人员


Tags: oftheinboardboxforiftop

热门问题