鱼C论坛

 找回密码
 立即注册
查看: 384|回复: 12

[技术交流] pygame震撼巨作!!!!!!

[复制链接]
发表于 2024-1-29 17:29:29 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
谢谢大家支持    求评分

  1. # Slide Puzzle
  2. # Released under a "Simplified BSD" license

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

  5. # Create the constants (go ahead and experiment with different values)
  6. BOARDWIDTH = 4  # number of columns in the board
  7. BOARDHEIGHT = 4 # number of rows in the board
  8. TILESIZE = 80
  9. WINDOWWIDTH = 640
  10. WINDOWHEIGHT = 480
  11. FPS = 30
  12. BLANK = None

  13. #                 R    G    B
  14. BLACK =         (  0,   0,   0)
  15. WHITE =         (255, 255, 255)
  16. BRIGHTBLUE =    (  0,  50, 255)
  17. DARKTURQUOISE = (  3,  54,  73)
  18. GREEN =         (  0, 204,   0)

  19. BGCOLOR = DARKTURQUOISE
  20. TILECOLOR = GREEN
  21. TEXTCOLOR = WHITE
  22. BORDERCOLOR = BRIGHTBLUE
  23. BASICFONTSIZE = 20

  24. BUTTONCOLOR = WHITE
  25. BUTTONTEXTCOLOR = BLACK
  26. MESSAGECOLOR = WHITE

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

  29. UP = 'up'
  30. DOWN = 'down'
  31. LEFT = 'left'
  32. RIGHT = 'right'

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

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

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

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

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

  52.         drawBoard(mainBoard, msg)

  53.         checkForQuit()
  54.         for event in pygame.event.get(): # event handling loop
  55.             if event.type == MOUSEBUTTONUP:
  56.                 spotx, spoty = getSpotClicked(mainBoard, event.pos[0], event.pos[1])

  57.                 if (spotx, spoty) == (None, None):
  58.                     # check if the user clicked on an option button
  59.                     if RESET_RECT.collidepoint(event.pos):
  60.                         resetAnimation(mainBoard, allMoves) # clicked on Reset button
  61.                         allMoves = []
  62.                     elif NEW_RECT.collidepoint(event.pos):
  63.                         mainBoard, solutionSeq = generateNewPuzzle(80) # clicked on New Game button
  64.                         allMoves = []
  65.                     elif SOLVE_RECT.collidepoint(event.pos):
  66.                         resetAnimation(mainBoard, solutionSeq + allMoves) # clicked on Solve button
  67.                         allMoves = []
  68.                 else:
  69.                     # check if the clicked tile was next to the blank spot

  70.                     blankx, blanky = getBlankPosition(mainBoard)
  71.                     if spotx == blankx + 1 and spoty == blanky:
  72.                         slideTo = LEFT
  73.                     elif spotx == blankx - 1 and spoty == blanky:
  74.                         slideTo = RIGHT
  75.                     elif spotx == blankx and spoty == blanky + 1:
  76.                         slideTo = UP
  77.                     elif spotx == blankx and spoty == blanky - 1:
  78.                         slideTo = DOWN

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


  97. def terminate():
  98.     pygame.quit()
  99.     sys.exit()


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


  107. def getStartingBoard():
  108.     # Return a board data structure with tiles in the solved state.
  109.     # For example, if BOARDWIDTH and BOARDHEIGHT are both 4, this function
  110.     # returns [[1, 5, 9, 13], [2, 6, 10, 14], [3, 7, 11, 15], [4, 8, 12, None]]
  111.     counter = 1
  112.     board = []
  113.     for x in range(BOARDWIDTH):
  114.         column = []
  115.         for y in range(BOARDHEIGHT):
  116.             column.append(counter)
  117.             counter += BOARDWIDTH
  118.         board.append(column)
  119.         counter -= BOARDWIDTH * BOARDHEIGHT - 1


  120.     board[BOARDWIDTH-1][BOARDHEIGHT-1] = BLANK
  121.     print(board)
  122.     return board


  123. def getBlankPosition(board):
  124.     # Return the x and y of board coordinates of the blank space.
  125.     for x in range(BOARDWIDTH):
  126.         for y in range(BOARDHEIGHT):
  127.             if board[x][y] == BLANK:
  128.                 return (x, y)


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

  133.     if move == UP:
  134.         board[blankx][blanky], board[blankx][blanky + 1] = board[blankx][blanky + 1], board[blankx][blanky]
  135.     elif move == DOWN:
  136.         board[blankx][blanky], board[blankx][blanky - 1] = board[blankx][blanky - 1], board[blankx][blanky]
  137.     elif move == LEFT:
  138.         board[blankx][blanky], board[blankx + 1][blanky] = board[blankx + 1][blanky], board[blankx][blanky]
  139.     elif move == RIGHT:
  140.         board[blankx][blanky], board[blankx - 1][blanky] = board[blankx - 1][blanky], board[blankx][blanky]


  141. def isValidMove(board, move):
  142.     blankx, blanky = getBlankPosition(board)
  143.     return (move == UP and blanky != len(board[0]) - 1) or \
  144.            (move == DOWN and blanky != 0) or \
  145.            (move == LEFT and blankx != len(board) - 1) or \
  146.            (move == RIGHT and blankx != 0)


  147. def getRandomMove(board, lastMove=None):
  148.     # start with a full list of all four moves
  149.     validMoves = [UP, DOWN, LEFT, RIGHT]

  150.     # remove moves from the list as they are disqualified
  151.     if lastMove == UP or not isValidMove(board, DOWN):
  152.         validMoves.remove(DOWN)
  153.     if lastMove == DOWN or not isValidMove(board, UP):
  154.         validMoves.remove(UP)
  155.     if lastMove == LEFT or not isValidMove(board, RIGHT):
  156.         validMoves.remove(RIGHT)
  157.     if lastMove == RIGHT or not isValidMove(board, LEFT):
  158.         validMoves.remove(LEFT)

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


  161. def getLeftTopOfTile(tileX, tileY):
  162.     left = XMARGIN + (tileX * TILESIZE) + (tileX - 1)
  163.     top = YMARGIN + (tileY * TILESIZE) + (tileY - 1)
  164.     return (left, top)


  165. def getSpotClicked(board, x, y):
  166.     # from the x & y pixel coordinates, get the x & y board coordinates
  167.     for tileX in range(len(board)):
  168.         for tileY in range(len(board[0])):
  169.             left, top = getLeftTopOfTile(tileX, tileY)
  170.             tileRect = pygame.Rect(left, top, TILESIZE, TILESIZE)
  171.             if tileRect.collidepoint(x, y):
  172.                 return (tileX, tileY)
  173.     return (None, None)


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


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


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

  194.     for tilex in range(len(board)):
  195.         for tiley in range(len(board[0])):
  196.             if board[tilex][tiley]:
  197.                 drawTile(tilex, tiley, board[tilex][tiley])

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

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


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

  207.     blankx, blanky = getBlankPosition(board)
  208.     if direction == UP:
  209.         movex = blankx
  210.         movey = blanky + 1
  211.     elif direction == DOWN:
  212.         movex = blankx
  213.         movey = blanky - 1
  214.     elif direction == LEFT:
  215.         movex = blankx + 1
  216.         movey = blanky
  217.     elif direction == RIGHT:
  218.         movex = blankx - 1
  219.         movey = blanky

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

  226.     for i in range(0, TILESIZE, animationSpeed):
  227.         # animate the tile sliding over
  228.         checkForQuit()
  229.         DISPLAYSURF.blit(baseSurf, (0, 0))
  230.         if direction == UP:
  231.             drawTile(movex, movey, board[movex][movey], 0, -i)
  232.         if direction == DOWN:
  233.             drawTile(movex, movey, board[movex][movey], 0, i)
  234.         if direction == LEFT:
  235.             drawTile(movex, movey, board[movex][movey], -i, 0)
  236.         if direction == RIGHT:
  237.             drawTile(movex, movey, board[movex][movey], i, 0)

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


  240. def generateNewPuzzle(numSlides):
  241.     # From a starting configuration, make numSlides number of moves (and
  242.     # animate these moves).
  243.     sequence = []
  244.     board = getStartingBoard()
  245.     drawBoard(board, '')
  246.     pygame.display.update()
  247.     pygame.time.wait(500) # pause 500 milliseconds for effect
  248.     lastMove = None
  249.     for i in range(numSlides):
  250.         move = getRandomMove(board, lastMove)
  251.         slideAnimation(board, move, 'Generating new puzzle...', animationSpeed=int(TILESIZE / 3))
  252.         makeMove(board, move)
  253.         sequence.append(move)
  254.         lastMove = move
  255.     return (board, sequence)


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

  260.     for move in revAllMoves:
  261.         if move == UP:
  262.             oppositeMove = DOWN
  263.         elif move == DOWN:
  264.             oppositeMove = UP
  265.         elif move == RIGHT:
  266.             oppositeMove = LEFT
  267.         elif move == LEFT:
  268.             oppositeMove = RIGHT
  269.         slideAnimation(board, oppositeMove, '', animationSpeed=int(TILESIZE / 2))
  270.         makeMove(board, oppositeMove)


  271. if __name__ == '__main__':
  272.     main()
复制代码

评分

参与人数 3荣誉 +5 鱼币 +5 贡献 +9 收起 理由
python爱好者. + 3 鱼C有你更精彩^_^
陈尚涵 + 5 + 5 + 3 鱼C有你更精彩^_^
cjjJasonchen + 3

查看全部评分

本帖被以下淘专辑推荐:

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2024-1-29 19:22:58 | 显示全部楼层
本帖最后由 cjjJasonchen 于 2024-1-29 19:29 编辑

打乱

打乱

(打乱状态)

复原中。。。

复原中。。。

(正在复原。。。)

可以看到有动画

复原完成!

复原完成!

(复原完成!)

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



想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

发表于 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 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-1-29 18:19:09 | 显示全部楼层
这是啥?搞个截图呗~
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-1-29 19:11:26 | 显示全部楼层

新鱼油似乎没有权限?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

很不错的推荐贴,我两个号都帮你评个分
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-1-29 19:24:32 | 显示全部楼层

截图来啦~看我回贴
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

谢谢你
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-1-29 19:30:17 | 显示全部楼层
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

华容道了解以下不过确实厉害
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-1-29 20:57:01 | 显示全部楼层
我弟可以复原6*6的华容道
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-1-29 22:39:14 | 显示全部楼层
厉害,加油
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-1-30 08:34:58 | 显示全部楼层
hveagle 发表于 2024-1-29 20:57
我弟可以复原6*6的华容道

厉害
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-4-29 02:08

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表