程序员合集|Pygame实战(升级后的2048小游戏—解锁新花样,根本停不下来【附源码】)

导语 “嗨嗨嗨!别睡了,醒醒醒醒!该干活儿了~”
by——顾木子吖!
程序员合集|Pygame实战(升级后的2048小游戏—解锁新花样,根本停不下来【附源码】)
文章图片


【程序员合集|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小游戏—解锁新花样,根本停不下来【附源码】)
文章图片
定义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 # 不需要移动的话直接return if self.move_direction is None: return # 向上 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] # 向下 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] # 向左 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 # 向右 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 '''在新的位置随机生成数字''' 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 '''初始化''' 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() '''设置移动方向''' def setDirection(self, direction): assert direction in ['up', 'down', 'left', 'right'] self.move_direction = direction '''保存最高分''' def saveMaxScore(self): f = open(self.max_score_filepath, 'w', encoding='utf-8') f.write(str(self.max_score)) f.close() '''读取游戏最高分''' 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 '''游戏是否结束''' @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]'''将2048游戏的当前数字排列画到屏幕上''' 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小游戏—解锁新花样,根本停不下来【附源码】)
文章图片

'''将游戏的最高分和当前分数画到屏幕上''' 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)'''游戏介绍''' 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): # 游戏初始化 pygame.init() screen = pygame.display.set_mode(cfg.SCREENSIZE) pygame.display.set_caption('2048小游戏升级版') # 播放背景音乐 pygame.mixer.music.load(cfg.BGMPATH) pygame.mixer.music.play(-1) # 实例化2048游戏 game_2048 = Game2048(matrix_size=cfg.GAME_MATRIX_SIZE, max_score_filepath=cfg.MAX_SCORE_FILEPATH) # 游戏主循环 clock = pygame.time.Clock() is_running = True while is_running: screen.fill(pygame.Color(cfg.BG_COLOR)) # --按键检测 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]) # --更新游戏状态 game_2048.update() if game_2048.isgameover: game_2048.saveMaxScore() is_running = False # --将必要的游戏元素画到屏幕上 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) # --屏幕更新 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 欢迎大家阅读往期的文章哦~

    推荐阅读