当前位置:首页>python>Python经典游戏:2048(Pygame+random)

Python经典游戏:2048(Pygame+random)

  • 2026-10-11 08:24:14
Python经典游戏:2048(Pygame+random)

Python,速成心法

敲代码,查资料,问度娘

练习,探索,总结,优化

★★★★★博文创作不易,使用代码的过程中,如有疑问的地方,欢迎大家指正留言交流。喜欢的老铁可以多多点赞+收藏分享+置顶,小红牛在此表示感谢。★★★★★

------★Pygame经典游戏★-------

Python经典游戏:中国象棋1.0(pygame)

Python经典游戏:扫雷(pygame+random)

Python经典游戏:贪吃蛇(pygame+random)

Python经典游戏:打砖块(pygame+math)

Python经典游戏:简化版的QQ种菜游戏

Python经典游戏:手动+自动版贪吃蛇Snake

Python经典游戏:太空飞机大战Space Plane Battle

Python经典游戏:扫雷

Python经典游戏:乒乓球对战(单人+双人模式)

Pygame经典游戏:消消乐Icehappy(安排!!)

Pygame经典游戏:坦克大战TankWar+五子棋人机对弈+俄罗斯方块(安排!!)

Python经典游戏:植物大战僵尸

Python经典游戏:像素鸟flappybird

Pygame经典游戏:微信飞机大战Wechatflying(初级版)

Python经典游戏:超级玛丽

Pygame经典游戏:贪吃蛇(普通版)

Pygame游戏:3*3/4*4/5*5智力宫格拼图

Python游戏:打地鼠(坤坤版)

Python游戏:吃金币Eating-coins

Python经典游戏:走迷宫,好烦呀,我到现在还没有走出去!!

Python游戏:滑雪+弹小球

Python游戏:外星人入侵

Pygame教程01:初识pygame游戏模块

Pygame教程02:图片的加载+缩放+旋转+显示操作

Pygame教程03:文本显示+字体加载+transform方法

Pygame教程04:draw方法绘制矩形、多边形、圆、椭圆、弧线、直线和线条等

Pygame教程05:帧动画原理+边界值检测,让小球来回上下运动

Pygame教程06:Event事件的类型+处理方法+监听鼠标事件

Pygame教程07:键盘常量+键盘事件的2种捕捉方式

Pygame教程08:使用键盘方向键,控制小球,上下左右移动。

Pygame教程09:font.render文本内容,如何自动换行显示

2048 是一款数字益智游戏,玩法简单但富有策略性。以下是核心规则和操作说明:
🎯 游戏目标:通过滑动合并相同数字,最终拼出 2048 方块(也可以继续挑战更高数字)。
🎮 基本玩法
网格:4×4 方格,初始有两个数字(2 或 4)。
移动:使用键盘 方向键(↑ ↓ ← →) 将所有方块同时向该方向滑动。
合并:移动时,相同数字的方块碰到一起会 合并成一个数字(数值相加,例如 2+2=4,4+4=8……)。
新方块:每次移动后,会在空白格随机生成一个 2(90%概率)或 4(10%概率)。
分数:每次合并得到的数字会累加到总分,例如合并出 8 就加 8 分。
结束条件:当所有格子都被填满,且 相邻(上下左右)没有相同数字 时,游戏结束。
💡 进阶提示:尽量把大数字 固定在一个角落(如左下角),便于控制合并方向。保持数字 单调递增(例如一行从大到小排列),避免小数字被卡在中间。不要随意打乱布局,优先向同一个方向滑动(如下滑、左滑)。
🔁 游戏控制(基于提供的代码)
方向键:移动并合并。
R 键:随时重新开始游戏。
达到 2048 后会显示胜利提示,但可以继续玩。
开始游戏后,试着规划每一步,让数字不断翻倍,直到达成 2048!

↓ 源码如下 ↓

# -*- coding: utf-8 -*-# @Author : 小红牛# 微信公众号:wdPythonimport pygameimport randomimport sys# 初始化Pygamepygame.init()# 游戏配置WIDTH, HEIGHT = 450, 550          # 窗口宽度和高度GRID_SIZE = 4                     # 4x4网格CELL_SIZE = 80                    # 每个格子大小MARGIN = 10                       # 格子间距GRID_LEFT = (WIDTH - (GRID_SIZE * CELL_SIZE + (GRID_SIZE - 1) * MARGIN)) // 2GRID_TOP = 120                    # 网格顶部Y坐标# 颜色定义 (R, G, B)BG_COLOR = (250, 248, 239)        # 背景米色EMPTY_COLOR = (205, 193, 180)     # 空格子颜色# 数字对应的格子颜色TILE_COLORS = {    0: (205, 193, 180),    2: (238, 228, 218),    4: (237, 224, 200),    8: (242, 177, 121),    16: (245, 149, 99),    32: (246, 124, 95),    64: (246, 94, 59),    128: (237, 207, 114),    256: (237, 204, 97),    512: (237, 200, 80),    1024: (237, 197, 63),    2048: (237, 194, 46),}# 文字颜色 (深色/浅色)DARK_TEXT = (119, 110, 101)LIGHT_TEXT = (249, 246, 242)# 字体设置FONT_LARGE = pygame.font.SysFont("arial", 36, bold=True)FONT_MEDIUM = pygame.font.SysFont("arial", 28, bold=True)FONT_SMALL = pygame.font.SysFont("arial", 24, bold=True)class Game2048:    """2048游戏核心逻辑"""    def __init__(self):        self.grid = [[0] * GRID_SIZE for _ in range(GRID_SIZE)]        self.score = 0        self.highscore = 0        self.game_over = False        self.reset()  # 初始化网格并添加两个起始数字    def reset(self):        """重置游戏(保留最高分)"""        self.grid = [[0] * GRID_SIZE for _ in range(GRID_SIZE)]        self.score = 0        self.game_over = False        self.add_random_tile()   # 第一个数字        self.add_random_tile()   # 第二个数字    def add_random_tile(self):        """在随机空格子添加新数字(2或4),90%概率为2,10%概率为4"""        empty_cells = [(r, c) for r in range(GRID_SIZE) for c in range(GRID_SIZE) if self.grid[r][c] == 0]        if empty_cells:            r, c = random.choice(empty_cells)            self.grid[r][c] = 2 if random.random() < 0.9 else 4            return True        return False    def get_max_tile(self):        """获取当前网格中的最大数字"""        return max(max(row) for row in self.grid)    def update_highscore(self):        """更新最高分"""        if self.score > self.highscore:            self.highscore = self.score    def is_game_over(self):        """检查游戏是否结束:没有空格子且任何方向都无法移动"""        # 如果有空格,游戏未结束        if any(self.grid[r][c] == 0 for r in range(GRID_SIZE) for c in range(GRID_SIZE)):            return False        # 检查是否还有相邻相同数字可以合并        for r in range(GRID_SIZE):            for c in range(GRID_SIZE):                val = self.grid[r][c]                if (c + 1 < GRID_SIZE and self.grid[r][c + 1] == val) or \                   (r + 1 < GRID_SIZE and self.grid[r + 1][c] == val):                    return False        return True    # ---------- 移动和合并核心算法 ----------    @staticmethod    def _merge_line(line):        """合并一行(向左),返回新行和本次合并获得的分数"""        # 过滤掉0,得到非零数字列表        filtered = [num for num in line if num != 0]        new_line = []        score_gain = 0        skip = False        for i in range(len(filtered)):            if skip:                skip = False                continue            # 如果下一个数字存在且相等,合并            if i + 1 < len(filtered) and filtered[i] == filtered[i + 1]:                merged = filtered[i] * 2                new_line.append(merged)                score_gain += merged                skip = True            else:                new_line.append(filtered[i])        # 补零至长度为GRID_SIZE        new_line += [0] * (GRID_SIZE - len(new_line))        return new_line, score_gain    def _move_left(self):        """向左移动所有行,返回新网格和总得分"""        new_grid = []        total_score = 0        for row in self.grid:            new_row, score = self._merge_line(row)            new_grid.append(new_row)            total_score += score        return new_grid, total_score    def _move_right(self):        """向右移动:每行反转 -> 左移合并 -> 反转回来"""        new_grid = []        total_score = 0        for row in self.grid:            reversed_row = row[::-1]            merged_row, score = self._merge_line(reversed_row)            new_grid.append(merged_row[::-1])            total_score += score        return new_grid, total_score    def _move_up(self):        """向上移动:矩阵转置 -> 左移 -> 转置回来"""        # 转置        transposed = [[self.grid[r][c] for r in range(GRID_SIZE)] for c in range(GRID_SIZE)]        new_trans, score = self._move_left()  # 在转置矩阵上执行左移        # 转置回来        new_grid = [[new_trans[r][c] for r in range(GRID_SIZE)] for c in range(GRID_SIZE)]        return new_grid, score    def _move_down(self):        """向下移动:转置 -> 右移 -> 转置回来"""        transposed = [[self.grid[r][c] for r in range(GRID_SIZE)] for c in range(GRID_SIZE)]        new_trans, score = self._move_right()        new_grid = [[new_trans[r][c] for r in range(GRID_SIZE)] for c in range(GRID_SIZE)]        return new_grid, score    def move(self, direction):        """        执行移动操作        direction: 'up', 'down', 'left', 'right'        返回是否移动成功(网格发生变化)        """        if self.game_over:            return False        # 保存当前状态,用于比较是否发生变化        old_grid = [row[:] for row in self.grid]        old_score = self.score        # 根据方向调用相应移动方法        if direction == 'left':            new_grid, score_gain = self._move_left()        elif direction == 'right':            new_grid, score_gain = self._move_right()        elif direction == 'up':            new_grid, score_gain = self._move_up()        elif direction == 'down':            new_grid, score_gain = self._move_down()        else:            return False        # 检查网格是否发生变化        if new_grid == old_grid:            return False        # 更新网格和分数        self.grid = new_grid        self.score += score_gain        self.update_highscore()        # 移动成功后添加随机新数字        self.add_random_tile()        # 检查游戏是否结束        if self.is_game_over():            self.game_over = True        return Truedef draw_tile(screen, value, x, y):    """绘制单个格子"""    # 选择颜色,如果值超过2048则使用2048颜色    color = TILE_COLORS.get(value, TILE_COLORS[2048])    rect = pygame.Rect(x, y, CELL_SIZE, CELL_SIZE)    pygame.draw.rect(screen, color, rect, border_radius=8)    pygame.draw.rect(screen, (187, 173, 160), rect, 2, border_radius=8)  # 边框    # 绘制数字    if value != 0:        # 根据数字大小选择字体和颜色        if value < 8:            text_color = DARK_TEXT        else:            text_color = LIGHT_TEXT        # 数字太大时缩小字体        if value >= 1000:            font = pygame.font.SysFont("arial", 24, bold=True)        elif value >= 100:            font = pygame.font.SysFont("arial", 28, bold=True)        else:            font = FONT_MEDIUM        text = font.render(str(value), True, text_color)        text_rect = text.get_rect(center=(x + CELL_SIZE // 2, y + CELL_SIZE // 2))        screen.blit(text, text_rect)def draw_game(screen, game):    """绘制整个游戏界面"""    screen.fill(BG_COLOR)    # 绘制标题    title = FONT_LARGE.render("2048", True, DARK_TEXT)    screen.blit(title, (GRID_LEFT, 20))    # 绘制分数面板    score_rect = pygame.Rect(WIDTH - 140, 20, 120, 50)    pygame.draw.rect(screen, (187, 173, 160), score_rect, border_radius=6)    score_text = FONT_SMALL.render("SCORE", True, LIGHT_TEXT)    score_value = FONT_MEDIUM.render(str(game.score), True, LIGHT_TEXT)    screen.blit(score_text, (WIDTH - 130, 25))    screen.blit(score_value, (WIDTH - 125, 45))    # 绘制最高分面板    high_rect = pygame.Rect(WIDTH - 140, 80, 120, 45)    pygame.draw.rect(screen, (187, 173, 160), high_rect, border_radius=6)    high_text = FONT_SMALL.render("BEST", True, LIGHT_TEXT)    high_value = FONT_MEDIUM.render(str(game.highscore), True, LIGHT_TEXT)    screen.blit(high_text, (WIDTH - 130, 85))    screen.blit(high_value, (WIDTH - 125, 105))    # 绘制游戏网格    for r in range(GRID_SIZE):        for c in range(GRID_SIZE):            x = GRID_LEFT + c * (CELL_SIZE + MARGIN)            y = GRID_TOP + r * (CELL_SIZE + MARGIN)            draw_tile(screen, game.grid[r][c], x, y)    # 游戏结束或胜利提示    if game.game_over:        # 半透明覆盖层        overlay = pygame.Surface((WIDTH, HEIGHT), pygame.SRCALPHA)        overlay.fill((0, 0, 0, 180))        screen.blit(overlay, (0, 0))        # 游戏结束文字        game_over_text = FONT_LARGE.render("GAME OVER", True, (255, 255, 255))        restart_text = FONT_SMALL.render("Press R to restart", True, (255, 255, 255))        screen.blit(game_over_text, (WIDTH // 2 - game_over_text.get_width() // 2, HEIGHT // 2 - 40))        screen.blit(restart_text, (WIDTH // 2 - restart_text.get_width() // 2, HEIGHT // 2 + 20))    else:        # 检查是否胜利(达到2048)        if game.get_max_tile() >= 2048:            win_text = FONT_MEDIUM.render("You Win!", True, (255, 215, 0))            screen.blit(win_text, (GRID_LEFT, GRID_TOP - 35))    # 提示操作    hint = FONT_SMALL.render("Use arrow keys / R to restart", True, (119, 110, 101))    screen.blit(hint, (WIDTH // 2 - hint.get_width() // 2, HEIGHT - 30))def main():    """主函数:游戏循环"""    screen = pygame.display.set_mode((WIDTH, HEIGHT))    pygame.display.set_caption("2048")    clock = pygame.time.Clock()    game = Game2048()    running = True    while running:        for event in pygame.event.get():            if event.type == pygame.QUIT:                running = False                pygame.quit()                sys.exit()            elif event.type == pygame.KEYDOWN:                if event.key == pygame.K_r:                    game.reset()                elif not game.game_over:                    moved = False                    if event.key == pygame.K_LEFT:                        moved = game.move('left')                    elif event.key == pygame.K_RIGHT:                        moved = game.move('right')                    elif event.key == pygame.K_UP:                        moved = game.move('up')                    elif event.key == pygame.K_DOWN:                        moved = game.move('down')                    # 移动后更新显示(自动重绘)        draw_game(screen, game)        pygame.display.flip()        clock.tick(30)    pygame.quit()if __name__ == "__main__":    main()

完毕!!感谢您的收看

--------★★历史博文集合★★--------

Python入门篇  进阶篇  视频教程  Py安装

py项目Python模块 Python爬虫  Json

Xpath正则表达式SeleniumEtreeCss

Gui程序开发TkinterPyqt5 列表元组字典

数据可视化 matplotlib  词云图Pyecharts

海龟画图PandasBug处理电脑小知识

自动化脚本编程工具NumPy CSVWeb

Pygame  图像处理  机器学习数据库

最新文章

随机文章