• python制作小游戏之二2048最终章


    上一部分已经实现了2048游戏的核心规则内容,但是在我们移动了数字后,游戏界面并没有增加新的数字,所以我们需要在每次移动后,增加新的数字。同时如果按下按键,在按键方向上并没有可以移动的数字,那么此时不需要增加新的数字到游戏界面。

    在编写之前,先编写一个空位检查函数,如果没有空位,那么则不需要再增加数字了。

    def has_enough_space(board):
        enough_space_flag = False
        for i in range(len(board)):
            for j in range(len(board[i])):
                if board[i][j] is None:
                    enough_space_flag = True
        return enough_space_flag
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    然后定义生成新数字函数

    def generate_new_number(board):
        if has_enough_space(board):
            counter = 1
            while counter > 0:
                random_x = random.randint(0, board_height-1)
                random_y = random.randint(0, board_width-1)
                if board[random_x][random_y] is None:
                    board[random_x][random_y] = 2
                    counter -= 1
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    修改slide_to部分内容

                if slide_to:
                    move_the_number(main_board, slide_to)
                    generate_new_number(main_board)
    
    • 1
    • 2
    • 3

    请添加图片描述

    考虑到新产生的数字因该有在移动完成后有个间隔,可以考虑增加一个等待。

            elif event.type == KEYUP:
                if event.key in (K_LEFT, K_a):
                    slide_to = left
                elif event.key in (K_RIGHT, K_d):
                    slide_to = right
                elif event.key in (K_UP, K_w):
                    slide_to = up
                elif event.key in (K_DOWN, K_s):
                    slide_to = down
                # print(slide_to)
    
                if slide_to:
                    move_the_number(main_board, slide_to)
                    draw_board(main_board, '2048')
                    pygame.display.update()
                    pygame.time.wait(120)
                    generate_new_number(main_board)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    注意slide_to的位置

    接下来只剩下检查游戏结束的函数了,游戏结束条件是,首先已经没有进一步放数字的空间同时任何一个数字,上下左右四个方向都没有与自己相等用来组合的数字了,则游戏结束。

    def game_over_check(board):
        game_over_flag = True
        for i in range(len(board)):
            for j in range(len(board[i])):
                if board[i][j] is None:
                    game_over_flag = False
                for direction in directions:
                    next_i = i + direction[0]
                    next_j = j + direction[1]
                    if 0 <= next_i < board_width and 0 <= next_j < board_height:
                        if board[i][j] == board[next_i][next_j]:
                            game_over_flag = False
        return game_over_flag
        ```
    
    将判断游戏结束代码放到循环内部
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    ```
    
    • 1

    #判断游戏是否结束

        if game_over_check(main_board):
            main_board = generate_new_puzzle()
    
    • 1
    • 2
    
    
    • 1
    def game_over_animation(color=white, animation_speed=50):
        orig_surf = display.copy()
        flash_surf = pygame.Surface(display.get_size())
        flash_surf = flash_surf.convert_alpha()
        r, g, b = color
        for i in range(3):
            for start, end, step in ((0, 255, 1), (255, 0, -1)):
                for alpha in range(start, end, animation_speed * step):
                    # 先铺一层新的界面,包含老界面所有内容
                    display.blit(orig_surf, (0, 0))
                    # flash界面填充颜色,开始很淡,越来越浓,然后越来越淡
                    flash_surf.fill((r, g, b, alpha))
                    # 把flash界面加载到display中,位置由当前颜色块决定
                    display.blit(orig_surf, (0, 0))
                    display.blit(flash_surf, (0, 0))
                    # draw_game_board(maze)
                    # 刷新看效果
                    pygame.display.update()
                    fps_clock.tick(fps)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    增加结束界面

        if game_over_check(main_board):
            game_over_animation()
            main_board = generate_new_puzzle()
    
    • 1
    • 2
    • 3

    while循环所有内容

    while True:
        for event in pygame.event.get():
            if event.type == QUIT:
                pygame.quit()
            elif event.type == MOUSEBUTTONUP:
                if reset_rect.collidepoint(event.pos):
                    game_over_animation()
                    main_board = generate_new_puzzle()
            elif event.type == KEYUP:
                if event.key in (K_LEFT, K_a):
                    slide_to = left
                elif event.key in (K_RIGHT, K_d):
                    slide_to = right
                elif event.key in (K_UP, K_w):
                    slide_to = up
                elif event.key in (K_DOWN, K_s):
                    slide_to = down
                # print(slide_to)
    
                if slide_to:
                    move_the_number(main_board, slide_to)
                    draw_board(main_board, '2048')
                    pygame.display.update()
                    pygame.time.wait(120)
                    generate_new_number(main_board)
    
        # 判断游戏是否结束
        if game_over_check(main_board):
            game_over_animation()
            main_board = generate_new_puzzle()
    
        draw_board(main_board, '2048')
    
        pygame.display.update()
        fps_clock.tick(fps)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    至此核心功能完结,我没有做得分系统,因为这个实现起来很简单,其次我真不知道这个分数因该怎么算才合适。所以就懒得做了。因为是随便做做,也没怎么测试,所以优化空间极大,哈哈。

    最后说一下动画,因为动画过程比较麻烦,需要修改数字移动函数,然后增加新的动画函数,而效果呢不算特别明显,就不做了。说说我的思想,我做的时候是在移动函数中取出了所有的需要移动的元素的坐标,每一个元素用一个列表来存放,比如,数字2在二维列表的[3][2]处,需要往左移动到[3][0]位置,那么我存放的列表为[2, (3,2), (3,1), (3,0)],其他的元素也是一样,所有的这些数据都存放在一个二维列表中,当移动算法计算完成,我在来绘制移动动画,每次移动一格的动画,每一格移动的时候使用偏移量来模拟移动效果。还使用了另一块画布来实现这个过程,总之很麻烦。最终效果一般,我放上两种方式的对比视频。

    这是没有动画版本的
    请添加图片描述

    这是有动画效果版本请添加图片描述

    主要是对于pygame的绘制部分理解得不透彻,所以这块儿效果一般。

    终于…

  • 相关阅读:
    用R语言制作交互式图表和地图
    Linux 基本语句_7_C语言_文件I/O文件复制操作
    Docker资源分配--Cgroup
    Type-C接口相关知识
    Go语言入门【8】函数
    opensl学习——base16编码解码、base64编码解码、ASCII码表、扩展ASCII码
    【大数据Hive】hive 多字段分隔符使用详解
    四元数求导
    Linux权限
    若依+lodop+jasperreports+ireport 设计打印票据格式(一)
  • 原文地址:https://blog.csdn.net/jackwsd/article/details/126439203