python3+pygame实现的2048,非常完整的代码
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了python3+pygame实现的2048,非常完整的代码,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含10008字,纯文字阅读大概需要15分钟。
内容图文
![python3+pygame实现的2048,非常完整的代码](/upload/InfoBanner/zyjiaocheng/1124/ffa9fc8429be4351923fd3c4bb7c6d1f.jpg)
前几天写了一个2048程序,是基于python3+pygame实现的,对于初学python的同学来说应该是很好的练手项目,现在将源码分享给大家,添加了清晰的注释,相信大家能看的很明白
运行效果如下:
游戏结束后的效果如下:
完整代码如下,如果需要下载素材(图片、字体等可以到 https://www.itprojects.cn/detail.html?example_id=ad099a8cf24e15979a89d2d2bcaa4ca4 进行下载)
1 import random 2 import sys 3 from collections import Iterable 4from functools import reduce 5 6import pygame 7 8# 屏幕尺寸 9 WIDTH, HEIGHT = (650, 370) 10# 背景颜色 11 BG_COLOR = ‘#92877d‘ 12# 棋盘需要的数据 13 MARGIN_SIZE = 10 # 间隔大小 14 BLOCK_SIZE = 80 # 棋子位置大小 15 16 17def draw_tips(screen): 18""" 19 显示提示信息 20""" 21# 显示"分数:" 22 tips_img = pygame.image.load("resources/images/tips.png") 23 screen.blit(tips_img, (375, 200)) 24 25 26def get_score(chess_nums_temp): 27""" 28 计算当前棋盘的总分数 29""" 30 31def sum_all(x, y): 32if isinstance(x, Iterable): 33return sum(x) + sum(y) 34return x + sum(y) 35 36return reduce(sum_all, chess_nums_temp) 37 38 39def draw_score(screen, score): 40""" 41 显示分数 42""" 43# 显示数字 44 font_size_big = 60 45 font_color = (0, 255, 255) 46 font_big = pygame.font.Font("resources/font/Gabriola.ttf", font_size_big) 47 score = font_big.render(str(score), True, font_color) 48 screen.blit(score, (470, 25)) 49# 显示"分数:" 50 score_img = pygame.image.load("resources/images/score.png") 51 screen.blit(score_img, (370, 30)) 52 53 54def show_game_over(screen): 55 font_size_big = 60 56 font_size_small = 30 57 font_color = (255, 255, 255) 58 font_big = pygame.font.Font("resources/font/Gabriola.ttf", font_size_big) 59 font_small = pygame.font.Font("resources/font/Gabriola.ttf", font_size_small) 60 surface = screen.convert_alpha() 61 surface.fill((127, 255, 212, 2)) 62 text = font_big.render(‘Game Over!‘, True, font_color) 63 text_rect = text.get_rect() 64 text_rect.centerx, text_rect.centery = WIDTH / 2, HEIGHT / 2 - 50 65 surface.blit(text, text_rect) 66 button_width, button_height = 100, 40 67 button_start_x_left = WIDTH / 2 - button_width - 20 68 button_start_x_right = WIDTH / 2 + 20 69 button_start_y = HEIGHT / 2 - button_height / 2 + 20 70 pygame.draw.rect(surface, (0, 255, 255), (button_start_x_left, button_start_y, button_width, button_height)) 71 text_restart = font_small.render(‘Restart‘, True, font_color) 72 text_restart_rect = text_restart.get_rect() 73 text_restart_rect.centerx, text_restart_rect.centery = button_start_x_left + button_width / 2, button_start_y + button_height / 2 74 surface.blit(text_restart, text_restart_rect) 75 pygame.draw.rect(surface, (0, 255, 255), (button_start_x_right, button_start_y, button_width, button_height)) 76 text_quit = font_small.render(‘Quit‘, True, font_color) 77 text_quit_rect = text_quit.get_rect() 78 text_quit_rect.centerx, text_quit_rect.centery = button_start_x_right + button_width / 2, button_start_y + button_height / 2 79 surface.blit(text_quit, text_quit_rect) 80 clock = pygame.time.Clock() 81while True: 82 screen.blit(surface, (0, 0)) 83for event in pygame.event.get(): 84if event.type == pygame.QUIT: 85 pygame.quit() 86 sys.exit() 87elif event.type == pygame.MOUSEBUTTONDOWN and event.button: 88if text_quit_rect.collidepoint(pygame.mouse.get_pos()): 89 sys.exit() 90if text_restart_rect.collidepoint(pygame.mouse.get_pos()): 91return True 92 pygame.display.update() 93 clock.tick(60) 94 95 96def judge_game_over(field): 97""" 98 只要有1个方向可以移动,那么游戏就没结束 99"""100returnnot any([judge_move_left(field), judge_move_right(field), judge_move_up(field), judge_move_down(field)]) 101102103def judge_move_up(chess_nums_temp): 104# 对棋盘的数字进行「行与列转置」,即原来在第2行第3列变为第3行第2列105# zip: 实现106# *chess_nums_temp对列表进行拆包107 chess_nums_temp = [list(row) for row in zip(*chess_nums_temp)] 108return judge_move_left(chess_nums_temp) 109110111def judge_move_down(chess_nums_temp): 112"""113 逻辑:判断能否向下移动, 也就是对于元素进行转置, 判断转置后的棋盘能否向右移动 114"""115# 1.「行与列转置」116 chess_nums_temp = [list(row) for row in zip(*chess_nums_temp)] 117# 2. 判断是否可以向右移动118return judge_move_right(chess_nums_temp) 119120121def judge_move_left(chess_nums_temp): 122# 只要棋盘的任意一行可以向左移动, 就返回True123for row in chess_nums_temp: 124for i in range(3): # 每一行判断3次125# 如果判断的左边的数为0,右边的数不为0,则说明可以向左移动;126if row[i] == 0 and row[i + 1] != 0: 127return True 128elif row[i] != 0 and row[i + 1] == row[i]: 129# 如果判断的左边的数不为0,且左右2个数相等,则说明可以向左移动;130return True 131return False 132133134def judge_move_right(chess_nums_temp): 135# 对棋盘的每一行元素进行反转,此时就可以用向左的函数进行判断了136return judge_move_left([row[::-1] for row in chess_nums_temp]) 137138139def move_left(chess_nums_temp): 140for i, row in enumerate(chess_nums_temp): 141# 1.把这一行的非0 数字向前放,把0向后放。例如之前是[0, 2, 2, 2]-->[2, 2, 2, 0]142 row = sorted(row, key=lambda x: 1 if x == 0 else 0) 143144# 2.依次循环判断两个数是否相等,如果相等 第一个*2 第二个数为0。例如[2, 2, 2, 0]-->[4, 0, 2, 0]145for index in range(3): 146if row[index] == row[index + 1]: 147 row[index] *= 2 148 row[index + 1] = 0 149150# 3.将合并之后的空隙移除,即非0靠左,0靠右。例如[4, 0, 2, 0]-->[4, 2, 0, 0]151 row = sorted(row, key=lambda x: 1 if x == 0 else 0) 152# 4. 更新数字列表,因为这一行已经是操作之后的了153 chess_nums_temp[i] = row 154return chess_nums_temp 155156157def move_right(chess_nums_temp): 158# 先翻翻转159 chess_nums_temp = [row[::-1] for row in chess_nums_temp] 160# 然后在调用像左移动的功能161 move_left(chess_nums_temp) 162# 最后再次翻转,实现之前的样子163return [row[::-1] for row in chess_nums_temp] 164165166def move_up(chess_nums_temp): 167# "行与列转置"168 chess_nums_temp = [list(row) for row in zip(*chess_nums_temp)] 169# 向左移动170 chess_nums_temp = move_left(chess_nums_temp) 171# 再次"行与列转置"从而实现复原172return [list(row) for row in zip(*chess_nums_temp)] 173174175def move_down(chess_nums_temp): 176# "行与列转置"177 chess_nums_temp = [list(row) for row in zip(*chess_nums_temp)] 178# 向右移动179 chess_nums_temp = move_right(chess_nums_temp) 180# 再次"行与列转置"从而实现复原181return [list(row) for row in zip(*chess_nums_temp)] 182183184def move(chess_nums_temp, direction): 185"""186 根据方向移动数字 187"""188# 存储判断各个方向是否可移动对应的函数189 judge_move_func_dict = { 190‘left‘: judge_move_left, 191‘right‘: judge_move_right, 192‘up‘: judge_move_up, 193‘down‘: judge_move_down 194 } 195# 存储各个方向移动的函数196 move_func_dict = { 197‘left‘: move_left, 198‘right‘: move_right, 199‘up‘: move_up, 200‘down‘: move_down 201 } 202203# 调用对应的函数,判断是否可以朝这个方向移动204 ret = judge_move_func_dict[direction](chess_nums_temp) 205print("%s方向是否可以移动:" % direction, ret) 206if ret: 207 chess_nums_temp = move_func_dict[direction](chess_nums_temp) 208 create_random_num(chess_nums_temp) 209210# 返回列表,如果更新了就是新的,如果没有更新就是之前的那个211return chess_nums_temp 212213214def get_num_color(num): 215"""216 根据当前要显示的数字,提取出背景色以及字体颜色 217 对应的数字:[方格背景颜色, 方格里的字体颜色] 218"""219 color_dict = { 220 2: [‘#eee4da‘, ‘#776e65‘], 4: [‘#ede0c8‘, ‘#776e65‘], 8: [‘#f2b179‘, ‘#f9f6f2‘], 221 16: [‘#f59563‘, ‘#f9f6f2‘], 32: [‘#f67c5f‘, ‘#f9f6f2‘], 64: [‘#f65e3b‘, ‘#f9f6f2‘], 222 128: [‘#edcf72‘, ‘#f9f6f2‘], 256: [‘#edcc61‘, ‘#f9f6f2‘], 512: [‘#edc850‘, ‘#f9f6f2‘], 223 1024: [‘#edc53f‘, ‘#f9f6f2‘], 2048: [‘#edc22e‘, ‘#f9f6f2‘], 4096: [‘#eee4da‘, ‘#776e65‘], 224 8192: [‘#edc22e‘, ‘#f9f6f2‘], 16384: [‘#f2b179‘, ‘#776e65‘], 32768: [‘#f59563‘, ‘#776e65‘], 225 65536: [‘#f67c5f‘, ‘#f9f6f2‘], 0: [‘#9e948a‘, None] 226 } 227return color_dict[num] 228229230def create_random_num(nums_temp): 231"""232 在棋盘中随机生成一个数字 233"""234# 存储所有空位置235 positions = list() 236for row, line in enumerate(nums_temp): 237for col, num in enumerate(line): 238if num == 0: 239 positions.append((row, col)) 240241# 随机从空位置列表中抽取一个,然后拆包242 row, col = random.choice(positions) 243 nums_temp[row][col] = random.choice([2, 4, 2]) # 随机从2个2,1个4中抽取,这样抽到2的概率是4的2倍244245246def draw_nums(screen, chess_nums_temp): 247"""248 显示棋盘上的数字 249"""250# 准备字体等251 font_size = BLOCK_SIZE - 10 252 font = pygame.font.Font("./resources/font/Gabriola.ttf", font_size) 253# 遍历数字254for i, line in enumerate(chess_nums_temp): 255for j, num in enumerate(line): 256if num != 0: 257# 计算显示位置(x坐标、y坐标)258 x = MARGIN_SIZE * (j + 1) + BLOCK_SIZE * j 259 y = MARGIN_SIZE * (i + 1) + BLOCK_SIZE * i 260# 获取颜色261 font_color = pygame.Color(get_num_color(num)[1]) 262# 显示数字263 text = font.render(str(num), True, font_color) 264 text_rect = text.get_rect() 265 text_rect.centerx, text_rect.centery = x + BLOCK_SIZE / 2, y + BLOCK_SIZE / 2 266# 用对应的数字背景色,重新绘制这个方块267 pygame.draw.rect(screen, pygame.Color(get_num_color(num)[0]), (x, y, BLOCK_SIZE, BLOCK_SIZE)) 268 screen.blit(text, text_rect) 269270271def draw_chess_board(screen): 272"""273 显示棋盘 274"""275for i in range(4): 276for j in range(4): 277 x = MARGIN_SIZE * (j + 1) + BLOCK_SIZE * j 278 y = MARGIN_SIZE * (i + 1) + BLOCK_SIZE * i 279 pygame.draw.rect(screen, pygame.Color(‘#f9f6f2‘), (x, y, BLOCK_SIZE, BLOCK_SIZE)) 280281282def run(screen): 283# 定义列表,用来记录当前棋盘上的所有数字,如果某位置没有数字,则为0284 chess_nums = [[0 for _ in range(4)] for _ in range(4)] 285# 随机生成一个数字286 create_random_num(chess_nums) 287 create_random_num(chess_nums) 288# 记录当前的分数289 score = get_score(chess_nums) 290# 创建计时器(防止while循环过快,占用太多CPU的问题)291 clock = pygame.time.Clock() 292while True: 293# 事件检测(鼠标点击、键盘按下等)294for event in pygame.event.get(): 295if event.type == pygame.QUIT: 296 pygame.quit() 297 sys.exit() 298elif event.type == pygame.KEYDOWN: 299if event.key in [pygame.K_UP, pygame.K_DOWN, pygame.K_LEFT, pygame.K_RIGHT]: 300 direction = {pygame.K_UP: ‘up‘, pygame.K_DOWN: ‘down‘, pygame.K_LEFT: ‘left‘, pygame.K_RIGHT: ‘right‘}[event.key] 301print("按下了方向键:", direction) 302 chess_nums = move(chess_nums, direction) 303if judge_game_over(chess_nums): 304print("游戏结束....") 305return306# 每按下方向键,就重新计算307 score = get_score(chess_nums) 308309# 显示背景色310 screen.fill(pygame.Color(BG_COLOR)) 311312# 显示棋盘313 draw_chess_board(screen) 314315# 显示棋盘上的数字316 draw_nums(screen, chess_nums) 317318# 显示分数319 draw_score(screen, score) 320321# 显示操作提示322 draw_tips(screen) 323324# 刷新显示(此时窗口才会真正的显示)325 pygame.display.update() 326327# FPS(每秒钟显示画面的次数)328 clock.tick(60) # 通过一定的延时,实现1秒钟能够循环60次329330331def main(): 332# 游戏初始化333 pygame.init() 334 screen = pygame.display.set_mode((WIDTH, HEIGHT)) 335while True: 336# 运行一次游戏337 run(screen) 338# 显示游戏结束,是否重来339 show_game_over(screen) 340341342if__name__ == ‘__main__‘: 343 main()
原文:https://www.cnblogs.com/dong4716138/p/14462954.html
内容总结
以上是互联网集市为您收集整理的python3+pygame实现的2048,非常完整的代码全部内容,希望文章能够帮你解决python3+pygame实现的2048,非常完整的代码所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。