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

然后定义生成新数字函数

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

修改slide_to部分内容

            if slide_to:
                move_the_number(main_board, slide_to)
                generate_new_number(main_board)

请添加图片描述

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

        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)

注意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
    ```

将判断游戏结束代码放到循环内部
```

#判断游戏是否结束

    if game_over_check(main_board):
        main_board = generate_new_puzzle()

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)

增加结束界面

    if game_over_check(main_board):
        game_over_animation()
        main_board = generate_new_puzzle()

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)

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

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

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

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

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

终于…

猜你喜欢

转载自blog.csdn.net/jackwsd/article/details/126439203