Pygame实战:升级后的2048小游戏—解锁新花样,根本停不下来【附源码】

导语

“嗨嗨嗨!别睡了,醒醒醒醒!该干活儿了~”

by——顾木子吖!

Pygame实战:升级后的2048小游戏—解锁新花样,根本停不下来【附源码】

“刚睡醒,大佬你有什么事儿吖?”

by——全体成员!

上期给大家分享的超详细——简易版本的2048都吃透了没?咳咳咳……没吃透也没关系!

慢慢来,木木子一直在等你们崛起~哈哈哈哈 ,呐~ 现在这篇文章的话是上次承诺的一个升级版本的2048小游戏。

比之之前那款呢?有什么不同?

Pygame实战:升级后的2048小游戏—解锁新花样,根本停不下来【附源码】

​那当然是大大的不同那,今天教大家写的这款是有界面的小程序,单单是有界面的这一点就可以超前面那款了,更加富有趣味性的撒~来,我们来看看!

Pygame实战:升级后的2048小游戏—解锁新花样,根本停不下来【附源码】

正文

环境安装:

Python3、pycharm、Pygame模块等。

 pip install -i https://pypi.douban.com/simple/ pygame

配置文件:

音乐、背景、字体等。

import os

'''FPS'''
FPS = 60
'''背景颜色'''
BG_COLOR = '#D3D3D3'
'''屏幕大小'''
SCREENSIZE = (650, 370)
'''保存当前最高分的文件'''
MAX_SCORE_FILEPATH = 'score'
'''字体路径'''
FONTPATH = os.path.join(os.getcwd(), 'resources/font/Gabriola.ttf')
'''背景音乐路径'''
BGMPATH = os.path.join(os.getcwd(), 'resources/audio/bgm.mp3')
'''其他一些必要的常量'''
MARGIN_SIZE = 10
BLOCK_SIZE = 80
GAME_MATRIX_SIZE = (4, 4)

Pygame实战:升级后的2048小游戏—解锁新花样,根本停不下来【附源码】
class Game2048(object):
    def __init__(self, matrix_size=(4, 4), max_score_filepath=None, **kwargs):
        # matrix_size: (num_rows, num_cols)
        self.matrix_size = matrix_size
        # 游戏最高分保存路径
        self.max_score_filepath = max_score_filepath
        # 初始化
        self.initialize()
    '''更新游戏状态'''
    def update(self):
        game_matrix_before = copy.deepcopy(self.game_matrix)
        self.move()
        if game_matrix_before != self.game_matrix: self.randomGenerateNumber()
        if self.score > self.max_score: self.max_score = self.score
    '''根据指定的方向, 移动所有数字块'''
    def move(self):
        # 提取非空数字
        def extract(array):
            array_new = []
            for item in array:
                if item != 'null': array_new.append(item)
            return array_new
        # 合并非空数字
        def merge(array):
            score = 0
            if len(array) < 2: return array, score
            for i in range(len(array)-1):
                if array[i] == 'null':
                    break
                if array[i] == array[i+1]:
                    array[i] *= 2
                    array.pop(i+1)
                    array.append('null')
                    score += array[i]
            return extract(array), score
        # &#x4E0D;&#x9700;&#x8981;&#x79FB;&#x52A8;&#x7684;&#x8BDD;&#x76F4;&#x63A5;return
        if self.move_direction is None: return
        # &#x5411;&#x4E0A;
        if self.move_direction == 'up':
            for j in range(self.matrix_size[1]):
                col = []
                for i in range(self.matrix_size[0]):
                    col.append(self.game_matrix[i][j])
                col = extract(col)
                col.reverse()
                col, score = merge(col)
                self.score += score
                col.reverse()
                col = col + ['null',] * (self.matrix_size[0] - len(col))
                for i in range(self.matrix_size[0]):
                    self.game_matrix[i][j] = col[i]
        # &#x5411;&#x4E0B;
        elif self.move_direction == 'down':
            for j in range(self.matrix_size[1]):
                col = []
                for i in range(self.matrix_size[0]):
                    col.append(self.game_matrix[i][j])
                col = extract(col)
                col, score = merge(col)
                self.score += score
                col = ['null',] * (self.matrix_size[0] - len(col)) + col
                for i in range(self.matrix_size[0]):
                    self.game_matrix[i][j] = col[i]
        # &#x5411;&#x5DE6;
        elif self.move_direction == 'left':
            for idx, row in enumerate(copy.deepcopy(self.game_matrix)):
                row = extract(row)
                row.reverse()
                row, score = merge(row)
                self.score += score
                row.reverse()
                row = row + ['null',] * (self.matrix_size[1] - len(row))
                self.game_matrix[idx] = row
        # &#x5411;&#x53F3;
        elif self.move_direction == 'right':
            for idx, row in enumerate(copy.deepcopy(self.game_matrix)):
                row = extract(row)
                row, score = merge(row)
                self.score += score
                row = ['null',] * (self.matrix_size[1] - len(row)) + row
                self.game_matrix[idx] = row
        self.move_direction = None
    '''&#x5728;&#x65B0;&#x7684;&#x4F4D;&#x7F6E;&#x968F;&#x673A;&#x751F;&#x6210;&#x6570;&#x5B57;'''
    def randomGenerateNumber(self):
        empty_pos = []
        for i in range(self.matrix_size[0]):
            for j in range(self.matrix_size[1]):
                if self.game_matrix[i][j] == 'null': empty_pos.append([i, j])
        i, j = random.choice(empty_pos)
        self.game_matrix[i][j] = 2 if random.random() > 0.1 else 4
    '''&#x521D;&#x59CB;&#x5316;'''
    def initialize(self):
        self.game_matrix = [['null' for _ in range(self.matrix_size[1])] for _ in range(self.matrix_size[0])]
        self.score = 0
        self.max_score = self.readMaxScore()
        self.move_direction = None
        self.randomGenerateNumber()
        self.randomGenerateNumber()
    '''&#x8BBE;&#x7F6E;&#x79FB;&#x52A8;&#x65B9;&#x5411;'''
    def setDirection(self, direction):
        assert direction in ['up', 'down', 'left', 'right']
        self.move_direction = direction
    '''&#x4FDD;&#x5B58;&#x6700;&#x9AD8;&#x5206;'''
    def saveMaxScore(self):
        f = open(self.max_score_filepath, 'w', encoding='utf-8')
        f.write(str(self.max_score))
        f.close()
    '''&#x8BFB;&#x53D6;&#x6E38;&#x620F;&#x6700;&#x9AD8;&#x5206;'''
    def readMaxScore(self):
        try:
            f = open(self.max_score_filepath, 'r', encoding='utf-8')
            score = int(f.read().strip())
            f.close()
            return score
        except:
            return 0
    '''&#x6E38;&#x620F;&#x662F;&#x5426;&#x7ED3;&#x675F;'''
    @property
    def isgameover(self):
        for i in range(self.matrix_size[0]):
            for j in range(self.matrix_size[1]):
                if self.game_matrix[i][j] == 'null': return False
                if (i == self.matrix_size[0] - 1) and (j == self.matrix_size[1] - 1):
                    continue
                elif (i == self.matrix_size[0] - 1):
                    if (self.game_matrix[i][j] == self.game_matrix[i][j+1]):
                        return False
                elif (j == self.matrix_size[1] - 1):
                    if (self.game_matrix[i][j] == self.game_matrix[i+1][j]):
                        return False
                else:
                    if (self.game_matrix[i][j] == self.game_matrix[i+1][j]) or (self.game_matrix[i][j] == self.game_matrix[i][j+1]):
                        return False
        return True

Pygame实战:升级后的2048小游戏—解锁新花样,根本停不下来【附源码】 然后设置不同的颜色。

不同的数字2-4-8等等组合成不同的数字颜色相应的变化。

颜色展示:

Pygame实战:升级后的2048小游戏—解锁新花样,根本停不下来【附源码】
'''根据方格当前的分数获得[方格背景颜色, 方格里的字体颜色]'''
def getColorByNumber(number):
    number2color_dict = {
        2: ['#eee4da', '#776e65'], 4: ['#ede0c8', '#776e65'], 8: ['#f2b179', '#f9f6f2'],
        16: ['#f59563', '#f9f6f2'], 32: ['#f67c5f', '#f9f6f2'], 64: ['#f65e3b', '#f9f6f2'],
        128: ['#edcf72', '#f9f6f2'], 256: ['#edcc61', '#f9f6f2'], 512: ['#edc850', '#f9f6f2'],
        1024: ['#edc53f', '#f9f6f2'], 2048: ['#edc22e', '#f9f6f2'], 4096: ['#eee4da', '#776e65'],
        8192: ['#edc22e', '#f9f6f2'], 16384: ['#f2b179', '#776e65'], 32768: ['#f59563', '#776e65'],
        65536: ['#f67c5f', '#f9f6f2'], 'null': ['#9e948a', None]
    }
    return number2color_dict[number]

'''&#x5C06;2048&#x6E38;&#x620F;&#x7684;&#x5F53;&#x524D;&#x6570;&#x5B57;&#x6392;&#x5217;&#x753B;&#x5230;&#x5C4F;&#x5E55;&#x4E0A;'''
def drawGameMatrix(screen, game_matrix, cfg):
    for i in range(len(game_matrix)):
        for j in range(len(game_matrix[i])):
            number = game_matrix[i][j]
            x = cfg.MARGIN_SIZE * (j + 1) + cfg.BLOCK_SIZE * j
            y = cfg.MARGIN_SIZE * (i + 1) + cfg.BLOCK_SIZE * i
            pygame.draw.rect(screen, pygame.Color(getColorByNumber(number)[0]), (x, y, cfg.BLOCK_SIZE, cfg.BLOCK_SIZE))
            if number != 'null':
                font_color = pygame.Color(getColorByNumber(number)[1])
                font_size = cfg.BLOCK_SIZE - 10 * len(str(number))
                font = pygame.font.Font(cfg.FONTPATH, font_size)
                text = font.render(str(number), True, font_color)
                text_rect = text.get_rect()
                text_rect.centerx, text_rect.centery = x + cfg.BLOCK_SIZE / 2, y + cfg.BLOCK_SIZE / 2
                screen.blit(text, text_rect)

Pygame实战:升级后的2048小游戏—解锁新花样,根本停不下来【附源码】 游戏界面添加额外的元素。

如下图:玩法介绍、分数显示。

Pygame实战:升级后的2048小游戏—解锁新花样,根本停不下来【附源码】
'''&#x5C06;&#x6E38;&#x620F;&#x7684;&#x6700;&#x9AD8;&#x5206;&#x548C;&#x5F53;&#x524D;&#x5206;&#x6570;&#x753B;&#x5230;&#x5C4F;&#x5E55;&#x4E0A;'''
def drawScore(screen, score, max_score, cfg):
    font_color = (255, 255, 255)
    font_size = 30
    font = pygame.font.Font(cfg.FONTPATH, font_size)
    text_max_score = font.render('Best: %s' % max_score, True, font_color)
    text_score = font.render('Score: %s' % score, True, font_color)
    start_x = cfg.BLOCK_SIZE * cfg.GAME_MATRIX_SIZE[1] + cfg.MARGIN_SIZE * (cfg.GAME_MATRIX_SIZE[1] + 1)
    screen.blit(text_max_score, (start_x+10, 10))
    screen.blit(text_score, (start_x+10, 20+text_score.get_rect().height))
    start_y = 30 + text_score.get_rect().height + text_max_score.get_rect().height
    return (start_x, start_y)

'''&#x6E38;&#x620F;&#x4ECB;&#x7ECD;'''
def drawGameIntro(screen, start_x, start_y, cfg):
    start_y += 40
    font_color = (0, 0, 0)
    font_size_big = 30
    font_size_small = 20
    font_big = pygame.font.Font(cfg.FONTPATH, font_size_big)
    font_small = pygame.font.Font(cfg.FONTPATH, font_size_small)
    intros = ['Game play:', ' Slide the keyboard up, down, left and right.', 'Combine two identical numbers', 'For example: 2 + 2 = 4, 4 + 4 = 8... Until 1024 + 1024 = 2048!', 'You win!']
    for idx, intro in enumerate(intros):
        font = font_big if idx == 0 else font_small
        text = font.render(intro, True, font_color)
        screen.blit(text, (start_x+10, start_y))
        start_y += text.get_rect().height + 10

游戏结束界面:

Pygame实战:升级后的2048小游戏—解锁新花样,根本停不下来【附源码】

附源码:

def endInterface(screen, cfg):
    font_size_big = 60
    font_size_small = 30
    font_color = (255, 255, 255)
    font_big = pygame.font.Font(cfg.FONTPATH, font_size_big)
    font_small = pygame.font.Font(cfg.FONTPATH, font_size_small)
    surface = screen.convert_alpha()
    surface.fill((127, 255, 212, 2))
    text = font_big.render('Game Over!', True, font_color)
    text_rect = text.get_rect()
    text_rect.centerx, text_rect.centery = cfg.SCREENSIZE[0]/2, cfg.SCREENSIZE[1]/2-50
    surface.blit(text, text_rect)
    button_width, button_height = 100, 40
    button_start_x_left = cfg.SCREENSIZE[0] / 2 - button_width - 20
    button_start_x_right = cfg.SCREENSIZE[0] / 2 + 20
    button_start_y = cfg.SCREENSIZE[1] / 2 - button_height / 2 + 20
    pygame.draw.rect(surface, (0, 255, 255), (button_start_x_left, button_start_y, button_width, button_height))
    text_restart = font_small.render('Restart', True, font_color)
    text_restart_rect = text_restart.get_rect()
    text_restart_rect.centerx, text_restart_rect.centery = button_start_x_left + button_width / 2, button_start_y + button_height / 2
    surface.blit(text_restart, text_restart_rect)
    pygame.draw.rect(surface, (0, 255, 255), (button_start_x_right, button_start_y, button_width, button_height))
    text_quit = font_small.render('Quit', True, font_color)
    text_quit_rect = text_quit.get_rect()
    text_quit_rect.centerx, text_quit_rect.centery = button_start_x_right + button_width / 2, button_start_y + button_height / 2
    surface.blit(text_quit, text_quit_rect)
    while True:
        screen.blit(surface, (0, 0))
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            elif event.type == pygame.MOUSEBUTTONDOWN and event.button:
                if text_quit_rect.collidepoint(pygame.mouse.get_pos()):
                    return False
                if text_restart_rect.collidepoint(pygame.mouse.get_pos()):
                    return True
        pygame.display.update()

主程序:

def main(cfg):
    # &#x6E38;&#x620F;&#x521D;&#x59CB;&#x5316;
    pygame.init()
    screen = pygame.display.set_mode(cfg.SCREENSIZE)
    pygame.display.set_caption('2048&#x5C0F;&#x6E38;&#x620F;&#x5347;&#x7EA7;&#x7248;')
    # &#x64AD;&#x653E;&#x80CC;&#x666F;&#x97F3;&#x4E50;
    pygame.mixer.music.load(cfg.BGMPATH)
    pygame.mixer.music.play(-1)
    # &#x5B9E;&#x4F8B;&#x5316;2048&#x6E38;&#x620F;
    game_2048 = Game2048(matrix_size=cfg.GAME_MATRIX_SIZE, max_score_filepath=cfg.MAX_SCORE_FILEPATH)
    # &#x6E38;&#x620F;&#x4E3B;&#x5FAA;&#x73AF;
    clock = pygame.time.Clock()
    is_running = True
    while is_running:
        screen.fill(pygame.Color(cfg.BG_COLOR))
        # --&#x6309;&#x952E;&#x68C0;&#x6D4B;
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            elif event.type == pygame.KEYDOWN:
                if event.key in [pygame.K_UP, pygame.K_DOWN, pygame.K_LEFT, pygame.K_RIGHT]:
                    game_2048.setDirection({pygame.K_UP: 'up', pygame.K_DOWN: 'down', pygame.K_LEFT: 'left', pygame.K_RIGHT: 'right'}[event.key])
        # --&#x66F4;&#x65B0;&#x6E38;&#x620F;&#x72B6;&#x6001;
        game_2048.update()
        if game_2048.isgameover:
            game_2048.saveMaxScore()
            is_running = False
        # --&#x5C06;&#x5FC5;&#x8981;&#x7684;&#x6E38;&#x620F;&#x5143;&#x7D20;&#x753B;&#x5230;&#x5C4F;&#x5E55;&#x4E0A;
        drawGameMatrix(screen, game_2048.game_matrix, cfg)
        start_x, start_y = drawScore(screen, game_2048.score, game_2048.max_score, cfg)
        drawGameIntro(screen, start_x, start_y, cfg)
        # --&#x5C4F;&#x5E55;&#x66F4;&#x65B0;
        pygame.display.update()
        clock.tick(cfg.FPS)
    return endInterface(screen, cfg)

'''run'''
if __name__ == '__main__':
    while True:
        if not main(cfg):
            break

2048游戏效果如下图所示:

Pygame实战:升级后的2048小游戏—解锁新花样,根本停不下来【附源码】

本来是想给大家截一张2048的图的,但是玩了好几遍都卡死了,这图你们就将就着看叭~我尽力了!

Pygame实战:升级后的2048小游戏—解锁新花样,根本停不下来【附源码】

Pygame实战:升级后的2048小游戏—解锁新花样,根本停不下来【附源码】

好啦!这篇升级版的2048小游戏就到这里结束啦,快来试试你能通关嘛?

Pygame实战:升级后的2048小游戏—解锁新花样,根本停不下来【附源码】

🌼完整的免费源码领取处:看主页左侧获取方式。

你们的支持是我最大的动力!! 记得三连哦~mua 欢迎大家阅读往期的文章哦~

Original: https://blog.csdn.net/weixin_55822277/article/details/120546460
Author: 顾木子吖
Title: Pygame实战:升级后的2048小游戏—解锁新花样,根本停不下来【附源码】

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/782098/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球