某一个“天” 发表于 2024-1-29 17:29:29

pygame震撼巨作!!!!!!

谢谢大家支持    求评分

# Slide Puzzle
# Released under a "Simplified BSD" license

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

# Create the constants (go ahead and experiment with different values)
BOARDWIDTH = 4# number of columns in the board
BOARDHEIGHT = 4 # number of rows in the board
TILESIZE = 80
WINDOWWIDTH = 640
WINDOWHEIGHT = 480
FPS = 30
BLANK = None

#               R    G    B
BLACK =         (0,   0,   0)
WHITE =         (255, 255, 255)
BRIGHTBLUE =    (0,50, 255)
DARKTURQUOISE = (3,54,73)
GREEN =         (0, 204,   0)

BGCOLOR = DARKTURQUOISE
TILECOLOR = GREEN
TEXTCOLOR = WHITE
BORDERCOLOR = BRIGHTBLUE
BASICFONTSIZE = 20

BUTTONCOLOR = WHITE
BUTTONTEXTCOLOR = BLACK
MESSAGECOLOR = WHITE

XMARGIN = int((WINDOWWIDTH - (TILESIZE * BOARDWIDTH + (BOARDWIDTH - 1))) / 2)
YMARGIN = int((WINDOWHEIGHT - (TILESIZE * BOARDHEIGHT + (BOARDHEIGHT - 1))) / 2)

UP = 'up'
DOWN = 'down'
LEFT = 'left'
RIGHT = 'right'

def main():
    global FPSCLOCK, DISPLAYSURF, BASICFONT, RESET_SURF, RESET_RECT, NEW_SURF, NEW_RECT, SOLVE_SURF, SOLVE_RECT

    pygame.init()
    FPSCLOCK = pygame.time.Clock()
    DISPLAYSURF = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT))
    pygame.display.set_caption('Slide Puzzle')
    BASICFONT = pygame.font.Font('freesansbold.ttf', BASICFONTSIZE)

    # Store the option buttons and their rectangles in OPTIONS.
    RESET_SURF, RESET_RECT = makeText('Reset',    TEXTCOLOR, TILECOLOR, WINDOWWIDTH - 120, WINDOWHEIGHT - 90)
    NEW_SURF,   NEW_RECT   = makeText('New Game', TEXTCOLOR, TILECOLOR, WINDOWWIDTH - 120, WINDOWHEIGHT - 60)
    SOLVE_SURF, SOLVE_RECT = makeText('Solve',    TEXTCOLOR, TILECOLOR, WINDOWWIDTH - 120, WINDOWHEIGHT - 30)

    mainBoard, solutionSeq = generateNewPuzzle(80)
    SOLVEDBOARD = getStartingBoard() # a solved board is the same as the board in a start state.
    allMoves = [] # list of moves made from the solved configuration

    while True: # main game loop
      slideTo = None # the direction, if any, a tile should slide
      msg = 'Click tile or press arrow keys to slide.' # contains the message to show in the upper left corner.
      if mainBoard == SOLVEDBOARD:
            msg = 'Solved!'

      drawBoard(mainBoard, msg)

      checkForQuit()
      for event in pygame.event.get(): # event handling loop
            if event.type == MOUSEBUTTONUP:
                spotx, spoty = getSpotClicked(mainBoard, event.pos, event.pos)

                if (spotx, spoty) == (None, None):
                  # check if the user clicked on an option button
                  if RESET_RECT.collidepoint(event.pos):
                        resetAnimation(mainBoard, allMoves) # clicked on Reset button
                        allMoves = []
                  elif NEW_RECT.collidepoint(event.pos):
                        mainBoard, solutionSeq = generateNewPuzzle(80) # clicked on New Game button
                        allMoves = []
                  elif SOLVE_RECT.collidepoint(event.pos):
                        resetAnimation(mainBoard, solutionSeq + allMoves) # clicked on Solve button
                        allMoves = []
                else:
                  # check if the clicked tile was next to the blank spot

                  blankx, blanky = getBlankPosition(mainBoard)
                  if spotx == blankx + 1 and spoty == blanky:
                        slideTo = LEFT
                  elif spotx == blankx - 1 and spoty == blanky:
                        slideTo = RIGHT
                  elif spotx == blankx and spoty == blanky + 1:
                        slideTo = UP
                  elif spotx == blankx and spoty == blanky - 1:
                        slideTo = DOWN

            elif event.type == KEYUP:
                # check if the user pressed a key to slide a tile
                if event.key in (K_LEFT, K_a) and isValidMove(mainBoard, LEFT):
                  slideTo = LEFT
                elif event.key in (K_RIGHT, K_d) and isValidMove(mainBoard, RIGHT):
                  slideTo = RIGHT
                elif event.key in (K_UP, K_w) and isValidMove(mainBoard, UP):
                  slideTo = UP
                elif event.key in (K_DOWN, K_s) and isValidMove(mainBoard, DOWN):
                  slideTo = DOWN
      '''下面的值在作为布尔表达式的时候,会被解释器看作假(false)
            False    None    0   ""    ()    []   {}'''
      if slideTo:
            slideAnimation(mainBoard, slideTo, 'Click tile or press arrow keys to slide.', 8) # show slide on screen
            makeMove(mainBoard, slideTo)
            allMoves.append(slideTo) # record the slide
      pygame.display.update()
      FPSCLOCK.tick(FPS)


def terminate():
    pygame.quit()
    sys.exit()


def checkForQuit():
    for event in pygame.event.get(QUIT): # get all the QUIT events
      terminate() # terminate if any QUIT events are present
    for event in pygame.event.get(KEYUP): # get all the KEYUP events
      if event.key == K_ESCAPE:
            terminate() # terminate if the KEYUP event was for the Esc key
      pygame.event.post(event) # put the other KEYUP event objects back


def getStartingBoard():
    # Return a board data structure with tiles in the solved state.
    # For example, if BOARDWIDTH and BOARDHEIGHT are both 4, this function
    # returns [, , , ]
    counter = 1
    board = []
    for x in range(BOARDWIDTH):
      column = []
      for y in range(BOARDHEIGHT):
            column.append(counter)
            counter += BOARDWIDTH
      board.append(column)
      counter -= BOARDWIDTH * BOARDHEIGHT - 1


    board = BLANK
    print(board)
    return board


def getBlankPosition(board):
    # Return the x and y of board coordinates of the blank space.
    for x in range(BOARDWIDTH):
      for y in range(BOARDHEIGHT):
            if board == BLANK:
                return (x, y)


def makeMove(board, move):
    # This function does not check if the move is valid.
    # 此函数不检查移动是否有效
    blankx, blanky = getBlankPosition(board)

    if move == UP:
      board, board = board, board
    elif move == DOWN:
      board, board = board, board
    elif move == LEFT:
      board, board = board, board
    elif move == RIGHT:
      board, board = board, board


def isValidMove(board, move):
    blankx, blanky = getBlankPosition(board)
    return (move == UP and blanky != len(board) - 1) or \
         (move == DOWN and blanky != 0) or \
         (move == LEFT and blankx != len(board) - 1) or \
         (move == RIGHT and blankx != 0)


def getRandomMove(board, lastMove=None):
    # start with a full list of all four moves
    validMoves =

    # remove moves from the list as they are disqualified
    if lastMove == UP or not isValidMove(board, DOWN):
      validMoves.remove(DOWN)
    if lastMove == DOWN or not isValidMove(board, UP):
      validMoves.remove(UP)
    if lastMove == LEFT or not isValidMove(board, RIGHT):
      validMoves.remove(RIGHT)
    if lastMove == RIGHT or not isValidMove(board, LEFT):
      validMoves.remove(LEFT)

    # return a random move from the list of remaining moves
    return random.choice(validMoves)


def getLeftTopOfTile(tileX, tileY):
    left = XMARGIN + (tileX * TILESIZE) + (tileX - 1)
    top = YMARGIN + (tileY * TILESIZE) + (tileY - 1)
    return (left, top)


def getSpotClicked(board, x, y):
    # from the x & y pixel coordinates, get the x & y board coordinates
    for tileX in range(len(board)):
      for tileY in range(len(board)):
            left, top = getLeftTopOfTile(tileX, tileY)
            tileRect = pygame.Rect(left, top, TILESIZE, TILESIZE)
            if tileRect.collidepoint(x, y):
                return (tileX, tileY)
    return (None, None)


def drawTile(tilex, tiley, number, adjx=0, adjy=0):
    # draw a tile at board coordinates tilex and tiley, optionally a few
    # pixels over (determined by adjx and adjy)
    left, top = getLeftTopOfTile(tilex, tiley)
    pygame.draw.rect(DISPLAYSURF, TILECOLOR, (left + adjx, top + adjy, TILESIZE, TILESIZE))
    textSurf = BASICFONT.render(str(number), True, TEXTCOLOR)
    textRect = textSurf.get_rect()
    textRect.center = left + int(TILESIZE / 2) + adjx, top + int(TILESIZE / 2) + adjy
    DISPLAYSURF.blit(textSurf, textRect)


def makeText(text, color, bgcolor, top, left):
    # create the Surface and Rect objects for some text.
    textSurf = BASICFONT.render(text, True, color, bgcolor)
    textRect = textSurf.get_rect()
    textRect.topleft = (top, left)
    return (textSurf, textRect)


def drawBoard(board, message):
    DISPLAYSURF.fill(BGCOLOR)
    if message:
      textSurf, textRect = makeText(message, MESSAGECOLOR, BGCOLOR, 5, 5)
      DISPLAYSURF.blit(textSurf, textRect)

    for tilex in range(len(board)):
      for tiley in range(len(board)):
            if board:
                drawTile(tilex, tiley, board)

    left, top = getLeftTopOfTile(0, 0)
    width = BOARDWIDTH * TILESIZE
    height = BOARDHEIGHT * TILESIZE
    pygame.draw.rect(DISPLAYSURF, BORDERCOLOR, (left - 5, top - 5, width + 11, height + 11), 4)

    DISPLAYSURF.blit(RESET_SURF, RESET_RECT)
    DISPLAYSURF.blit(NEW_SURF, NEW_RECT)
    DISPLAYSURF.blit(SOLVE_SURF, SOLVE_RECT)


def slideAnimation(board, direction, message, animationSpeed):
    # Note: This function does not check if the move is valid.

    blankx, blanky = getBlankPosition(board)
    if direction == UP:
      movex = blankx
      movey = blanky + 1
    elif direction == DOWN:
      movex = blankx
      movey = blanky - 1
    elif direction == LEFT:
      movex = blankx + 1
      movey = blanky
    elif direction == RIGHT:
      movex = blankx - 1
      movey = blanky

    # prepare the base surface
    drawBoard(board, message)
    baseSurf = DISPLAYSURF.copy()
    # draw a blank space over the moving tile on the baseSurf Surface.
    moveLeft, moveTop = getLeftTopOfTile(movex, movey)
    pygame.draw.rect(baseSurf, BGCOLOR, (moveLeft, moveTop, TILESIZE, TILESIZE))

    for i in range(0, TILESIZE, animationSpeed):
      # animate the tile sliding over
      checkForQuit()
      DISPLAYSURF.blit(baseSurf, (0, 0))
      if direction == UP:
            drawTile(movex, movey, board, 0, -i)
      if direction == DOWN:
            drawTile(movex, movey, board, 0, i)
      if direction == LEFT:
            drawTile(movex, movey, board, -i, 0)
      if direction == RIGHT:
            drawTile(movex, movey, board, i, 0)

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


def generateNewPuzzle(numSlides):
    # From a starting configuration, make numSlides number of moves (and
    # animate these moves).
    sequence = []
    board = getStartingBoard()
    drawBoard(board, '')
    pygame.display.update()
    pygame.time.wait(500) # pause 500 milliseconds for effect
    lastMove = None
    for i in range(numSlides):
      move = getRandomMove(board, lastMove)
      slideAnimation(board, move, 'Generating new puzzle...', animationSpeed=int(TILESIZE / 3))
      makeMove(board, move)
      sequence.append(move)
      lastMove = move
    return (board, sequence)


def resetAnimation(board, allMoves):
    # make all of the moves in allMoves in reverse.
    revAllMoves = allMoves[:] # gets a copy of the list
    revAllMoves.reverse()

    for move in revAllMoves:
      if move == UP:
            oppositeMove = DOWN
      elif move == DOWN:
            oppositeMove = UP
      elif move == RIGHT:
            oppositeMove = LEFT
      elif move == LEFT:
            oppositeMove = RIGHT
      slideAnimation(board, oppositeMove, '', animationSpeed=int(TILESIZE / 2))
      makeMove(board, oppositeMove)


if __name__ == '__main__':
    main()

cjjJasonchen 发表于 2024-1-29 19:22:58

本帖最后由 cjjJasonchen 于 2024-1-29 19:29 编辑


(打乱状态)


(正在复原。。。)

可以看到有动画


(复原完成!)

总而言之,麻雀虽小,五脏俱全,界面比较美观,代码也很好看,非常适合萌新学习,

{:10_252:}

FishC 发表于 2024-1-29 17:30:12

这是一个使用pygame制作的滑动拼图游戏,让我们来看看其中的一些关键函数:

1. `main()`函数:这是游戏的主循环,处理事件、绘制界面等。

2. `getStartingBoard()`函数:返回一个解决状态的拼图板。

3. `getBlankPosition(board)`函数:返回空白格子的位置。

4. `makeMove(board, move)`函数:根据移动方向对拼图板进行更新,移动一块拼图。

5. `isValidMove(board, move)`函数:检查移动是否有效,即检查移动方向是否合法。

6. `getRandomMove(board, lastMove=None)`函数:返回一个随机的合法移动方向。

7. `getLeftTopOfTile(tileX, tileY)`函数:返回指定拼图的左上角坐标。

8. `getSpotClicked(board, x, y)`函数:根据点击的位置返回拼图的坐标。

9. `drawTile(tilex, tiley, number, adjx=0, adjy=0)`函数:在指定位置绘制一个拼图块。

10. `drawBoard(board, message)`函数:绘制拼图板和相关信息。

11. `slideAnimation(board, direction, message, animationSpeed)`函数:将拼图块按指定方向进行滑动,并完成动画效果。

12. `generateNewPuzzle(numSlides)`函数:生成一个新的乱序拼图。

13. `resetAnimation(board, allMoves)`函数:重置拼图板,并按照allMoves中的移动序列进行反向滑动。

这些函数相互配合,构成了整个游戏的基本逻辑和功能。你可以根据个人需求进行改动和扩展,加入更多的特性和功能,使游戏更加有趣。祝你玩得开心!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

小甲鱼的二师兄 发表于 2024-1-29 18:19:09

这是啥?搞个截图呗~

JasonChencCjj 发表于 2024-1-29 19:11:26

小甲鱼的二师兄 发表于 2024-1-29 18:19
这是啥?搞个截图呗~

新鱼油似乎没有权限?

cjjJasonchen 发表于 2024-1-29 19:17:45

这似乎是一个很有意思的小游戏欸!
短短三百余行的代码,着实震惊到我了!{:10_270:}

很不错的推荐贴,我两个号都帮你评个分

cjjJasonchen 发表于 2024-1-29 19:24:32

小甲鱼的二师兄 发表于 2024-1-29 18:19
这是啥?搞个截图呗~

截图来啦~看我回贴

某一个“天” 发表于 2024-1-29 19:29:55

cjjJasonchen 发表于 2024-1-29 19:17
这似乎是一个很有意思的小游戏欸!
短短三百余行的代码,着实震惊到我了!



谢谢你

cjjJasonchen 发表于 2024-1-29 19:30:17

某一个“天” 发表于 2024-1-29 19:29
谢谢你

{:10_257:}

陈尚涵 发表于 2024-1-29 19:56:18

cjjJasonchen 发表于 2024-1-29 19:17
这似乎是一个很有意思的小游戏欸!
短短三百余行的代码,着实震惊到我了!



华容道了解以下{:10_254:}不过确实厉害{:10_256:}

hveagle 发表于 2024-1-29 20:57:01

我弟可以复原6*6的华容道

python爱好者. 发表于 2024-1-29 22:39:14

厉害,加油

某一个“天” 发表于 2024-1-30 08:34:58

hveagle 发表于 2024-1-29 20:57
我弟可以复原6*6的华容道

厉害

叫花儿 发表于 2024-12-13 11:16:21

学习了,非常感谢
页: [1]
查看完整版本: pygame震撼巨作!!!!!!