pygame slide puzzle

清华大佬耗费三个月吐血整理的几百G的资源,免费分享!....>>>

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

FPS = 30
boardnum = 4
boardsize = 80
winx = 640
winy = 480
BASICFONTSIZE = 20
xmargin = int((winx - (boardnum*boardsize+(boardnum-1)))/2)
ymargin = int((winy - (boardnum*boardsize+(boardnum-1)))/2)
Blank = None
green = (0,204,0)
blue = (0,50,255)
white = (255,255,255)
dark = (3,54,73)

up = 'up'
down = 'down'
L = 'left'
R = 'right'

def main():
    global fpsclock,disp,BASICFONT,reset_surf,reset_rect,solved_surf,solved_rect,new_surf,new_rect
    pygame.init()
    fpsclock = pygame.time.Clock()    
    disp = pygame.display.set_mode((winx,winy))
    pygame.display.set_caption('slide puzzle')
    BASICFONT = pygame.font.Font('freesansbold.ttf',BASICFONTSIZE)

    reset_surf,reset_rect = maketext('reset',white,green,winx-120,winy-90)
    new_surf,new_rect = maketext('new',white,green,winx-120,winy-60)
    solved_surf,solved_rect = maketext('solve',white,green,winx-120,winy-30)

    mainboard,seq = newpuzzles(80)
    solvedboard = startboard()
    allmove = []
    
    while True:
        slide = None
        msg = 'Click tile or press arrow keys to slide.'
        if mainboard == solvedboard:
            msg = 'win'
        drawboard(mainboard,msg)
        checkforquit()
        for event in pygame.event.get():
            if event.type == MOUSEBUTTONUP:
                spotx,spoty = getclicked(mainboard,event.pos[0],event.pos[1])
                
                if (spotx,spoty)==(None,None):
                    if reset_rect.collidepoint(event.pos):
                        resetpuzzles(mainboard,allmove)
                        allmove = []
                    elif new_rect.collidepoint(event.pos):
                        mainboard,seq = newpuzzles(20)
                        allmove = []
                    elif solved_rect.collidepoint(event.pos):
                        resetpuzzles(mainboard,seq+allmove)
                        allmove = []                        
                else:
                    blankx,blanky = getblank(mainboard)
                    if spotx == blankx and spoty == blanky - 1 :
                        slide = down
                    elif spotx == blankx and spoty == blanky + 1 :
                        slide = up                      
                    if spotx == blankx+1 and spoty == blanky :
                        slide = L
                    if spotx == blankx-1 and spoty == blanky :
                        slide = R

            elif event.type == KEYUP:
                if event.key in (K_a, K_LEFT) and validmove(mainboard,L):
                    slide == L
                elif event.key in (K_d,K_RIGHT) and validmove(mainboard,R):
                    slide == R
                elif event.key in (K_w,K_UP) and validmove(mainboard,up):
                    slide == up
                elif event.key in (K_s,K_DOWN) and validmove(mainboard,down):
                    slide == down
            
        if slide:
            slideanimation(mainboard,slide,'Click tile or press arrow keys to slide.',8)
            makemove(mainboard,slide)
            allmove.append(slide)

        pygame.display.update()
        fpsclock.tick(FPS)
            
def terminal():
    pygame.quit()
    sys.exit()

def checkforquit():
    for event in pygame.event.get(QUIT):
        terminal()
    for event in pygame.event.get(KEYUP):
        if event.key == K_ESCAPE:
            terminal
        pygame.event.post(event)

def startboard():
    counter = 1
    board = []
    for x in range(boardnum):
        column = []
        for y in range(boardnum):
            
            column.append(counter)
            counter+=boardnum
        board.append(column)
        counter-=boardnum*(boardnum-1)+boardnum-1
    board[boardnum-1][boardnum-1] = Blank      
    return board

def getblank(board):
    for x in range(boardnum):
        for y in range(boardnum):
            if board[x][y] == Blank:
                return (x,y)

def makemove(board,move):
    blankx,blanky = getblank(board)
    
    if move == up:
        board[blankx][blanky],board[blankx][blanky+1] = board[blankx][blanky+1],board[blankx][blanky]
    if move == down:
        board[blankx][blanky],board[blankx][blanky-1] = board[blankx][blanky-1],board[blankx][blanky]
    if move == L:
        board[blankx][blanky],board[blankx+1][blanky] = board[blankx+1][blanky],board[blankx][blanky]
    if move == R:
        board[blankx][blanky],board[blankx-1][blanky] = board[blankx-1][blanky],board[blankx][blanky] 

def validmove(board,move):
    blankx,blanky = getblank(board)
    return (move == up and blanky != boardnum-1) or (move==down and blanky != 0) or (move == L and blankx != boardnum-1)or (move==R and blankx != 0)

def getrandommove(board,lastmove = None):
    validmoves = [up,down,L,R]
    if lastmove == up or not validmove(board,down):
        validmoves.remove(down)
    if lastmove == down or not validmove(board,up):
        validmoves.remove(up)
    if lastmove == L or not validmove(board,R):
        validmoves.remove(R)
    if lastmove == R or not validmove(board,L):
        validmoves.remove(L)
    return random.choice(validmoves)

def leftop(tilex,tiley):
    left = xmargin + tilex*boardsize+tilex-1
    top = ymargin + tiley*boardsize+tiley-1
    return (left,top)

def getclicked(board,x,y):
    for tilex in range(boardnum):
        for tiley in range(boardnum):
            left,top = leftop(tilex,tiley)
            b = pygame.Rect(left,top,boardsize,boardsize)
            if b.collidepoint(x,y):
                return (tilex,tiley)
    return(None,None)
    
def drawtile(tilex,tiley,number,ax = 0,ay = 0):
    
  
    left,top = leftop(tilex,tiley)
    pygame.draw.rect(disp,green,(left+ax,top+ay,boardsize,boardsize))
    textsuf = BASICFONT.render(str(number),True,white)
    textrect = textsuf.get_rect()
    textrect.center = left + int(boardsize/2)+ax,top + int(boardsize/2)+ay
    disp.blit(textsuf,textrect)

def maketext(text,color,dark,top,left):
    textsuf = BASICFONT.render(text,True,color,dark)
    textrect = textsuf.get_rect()
    textrect.topleft = (top,left)
    return(textsuf,textrect)
        
def drawboard(board,message):
    disp.fill(dark)
    if message:
        textsuf,textrect = maketext(message,white,dark,5,5)
        disp.blit(textsuf,textrect)
    for tilex in range(boardnum):
        for tiley in range(boardnum):
            if board[tilex][tiley]:
                    drawtile(tilex,tiley,board[tilex][tiley])

    left,top = leftop(0,0)
    size = boardsize*boardnum
    pygame.draw.rect(disp,blue,(left-5,top-5,size+11,size+11),4)

    disp.blit(reset_surf,reset_rect)
    disp.blit(new_surf,new_rect)
    disp.blit(solved_surf,solved_rect)

def slideanimation(board,direction,message,animationspeed):
    blankx,blanky = getblank(board)
    if direction == up:
        movex =blankx
        movey = blanky+1
    if direction == down:
        movex = blankx
        movey = blanky-1
    if direction == L:
        movex = blankx + 1
        movey = blanky
    if direction == R:
        movex = blankx - 1
        movey = blanky

    drawboard(board,message)
    bash = disp.copy()
    moveleft,movetop = leftop(movex,movey)
    pygame.draw.rect(bash,dark,(moveleft,movetop,boardsize,boardsize))
   # pygame.draw.rect(bash,dark,(moveleft,movetop,boardsize,boardsize))
    for i in range(0,boardsize,animationspeed):        
        checkforquit()
        disp.blit(bash,(0,0))
        if direction == up:
            drawtile(movex,movey,board[movex][movey],0,-i)
        if direction == down:
            drawtile(movex,movey,board[movex][movey],0,i)
        if direction == L:
            drawtile(movex,movey,board[movex][movey],-i,0)
        if direction == R:
            drawtile(movex,movey,board[movex][movey],i,0)

        pygame.display.update()
        fpsclock.tick(FPS)

def newpuzzles(numslide):
    board = startboard()
    seq = []
    drawboard(board,'')
    pygame.display.update()
    pygame.time.wait(500)

    lastmove = None
    for i in range(numslide):
        move = getrandommove(board,lastmove)
        slideanimation(board,move,'generate new game',animationspeed = int(boardsize/3))
        makemove(board,move)        
        seq.append(move)
        lastmove = move
    return (board,seq)

def resetpuzzles(board,allmove):
    revallmove = allmove[:]
    revallmove.reverse()

    for move in revallmove:
        if move == up:
            oppositemove = down
        elif move == down:
            oppositemove = up
        elif move == L:
            oppositemove = R
        elif move == R:
            oppositemove = L

        slideanimation(board,oppositemove,'',animationspeed=int(boardsize / 2))
        makemove(board,oppositemove)

if __name__ == '__main__':
    main()