使用 Python Tkinter 创建 2048 游戏

PythonPythonBeginner
立即练习

💡 本教程由 AI 辅助翻译自英文原版。如需查看原文,您可以 切换至英文原版

简介

在这个项目中,你将学习如何使用 Python 和 Tkinter 库创建一个简单的 2048 游戏,用于图形用户界面。2048 是一款流行的滑动拼图游戏,你需要合并方块以达到值为 2048 的方块。虽然这个项目不会创建最现代、最漂亮的用户界面,但它将提供一个坚实的基础,你可以在此基础上增强美观性。

👀 预览

2048 游戏

🎯 任务

在这个项目中,你将学习:

  • 如何导入游戏所需的必要库
  • 如何创建 Game2048 类来处理游戏逻辑和用户界面
  • 如何使用 Tkinter 绘制游戏网格
  • 如何在网格上生成初始方块
  • 如何更新用户界面以反映游戏网格的当前状态
  • 如何根据方块的值定义方块颜色
  • 如何处理按键以移动方块
  • 如何定义向不同方向移动方块的方法
  • 如何检查游戏是否结束

🏆 成果

完成这个项目后,你将能够:

  • 使用 Tkinter 库创建图形用户界面
  • 处理按键并触发相应操作
  • 根据游戏状态更新用户界面
  • 实现方块移动和合并的游戏逻辑
  • 检查游戏是否结束

创建项目文件

首先,创建一个名为 2048_game.py 的新文件,并在你喜欢的代码编辑器中打开它。

cd ~/project
touch 2048_game.py
✨ 查看解决方案并练习

导入必要的库

为了让你的游戏正常运行,你需要导入必要的库。在 2048_game.py 文件中,导入 Python 的随机库和用于构建图形用户界面的 Tkinter。

import random
import tkinter as tk

这些库将用于创建游戏的功能和用户界面。

✨ 查看解决方案并练习

创建 Game2048 类

在你的 2048_game.py 文件中定义 Game2048 类。这个类将处理游戏的逻辑和用户界面。

class Game2048:
    def __init__(self, root):
        self.root = root
        self.root.title("2048 游戏")
        self.root.geometry("400x400")

        ## 初始化游戏网格和分数
        self.grid = [[0 for _ in range(4)] for _ in range(4)]
        self.score = 0

        ## 创建一个空列表来存储方块标签
        self.tiles = []

在这里,你正在创建一个类构造函数,它初始化游戏的根窗口,设置其标题和大小,初始化游戏网格,并创建一个列表来保存游戏方块。

✨ 查看解决方案并练习

绘制游戏网格

Game2048 类中,添加一个使用 Tkinter 绘制游戏网格的方法。此方法创建初始的用户界面网格。

    def draw_grid(self):
        for i in range(4):
            row = []
            for j in range(4):
                cell = tk.Label(self.root, text="", font=("Helvetica", 24), width=5, height=2, borderwidth=4, relief="ridge")
                cell.grid(row=i, column=j, padx=5, pady=5)
                row.append(cell)
            self.tiles.append(row)

此方法创建一个 4x4 的标签网格,用于显示游戏方块。

✨ 查看解决方案并练习

生成初始方块

现在,你需要实现一个方法,在游戏开始时生成初始方块。此方法将在网格上放置一个或两个值为 2 或 4 的方块。

    def spawn_tile(self):
        empty_cells = [(i, j) for i in range(4) for j in range(4) if self.grid[i][j] == 0]
        if empty_cells:
            i, j = random.choice(empty_cells)
            self.grid[i][j] = 2 if random.random() < 0.9 else 4
            self.update_tiles()

此方法在网格上找到空单元格,并在其中随机放置一个新方块。

✨ 查看解决方案并练习

更新用户界面

创建一个方法来更新用户界面,以反映游戏网格的当前状态。

    def update_tiles(self):
        for i in range(4):
            for j in range(4):
                tile_value = self.grid[i][j]
                self.tiles[i][j]["text"] = str(tile_value) if tile_value > 0 else ""
                self.tiles[i][j]["background"] = self.get_tile_color(tile_value)

此方法遍历网格,更新图形用户界面中的标签,使其与网格状态匹配。

✨ 查看解决方案并练习

定义方块颜色

创建一个方法,根据方块的值为其分配背景颜色。

    def get_tile_color(self, value):
        colors = {
            0: "#CDC1B4",
            2: "#EEE4DA",
            4: "#EDE0C8",
            8: "#F2B179",
            16: "#F59563",
            32: "#F67C5F",
            64: "#F65E3B",
            128: "#EDCF72",
            256: "#EDCC61",
            512: "#EDC850",
            1024: "#EDC53F",
            2048: "#EDC22E"
        }
        return colors.get(value, "#FF0000")

此方法根据方块的值返回一个颜色代码。

✨ 查看解决方案并练习

处理按键事件

实现一个处理按键事件的方法。在这一步中,你将捕获箭头键的按下事件并做出相应的响应。

    def key_pressed(self, event):
        if self.is_game_over():
            return

        if event.keysym == "Up":
            self.move("up")
        elif event.keysym == "Down":
            self.move("down")
        elif event.keysym == "Left":
            self.move("left")
        elif event.keysym == "Right":
            self.move("right")

        self.spawn_tile()
        self.update_tiles()

此方法监听箭头键的按下事件,并触发相应的移动函数。

✨ 查看解决方案并练习

移动方块

实现按所需方向(上、下、左或右)移动方块的方法。

    def move(self, direction):
        if direction == "up":
            self.grid = list(map(list, zip(*self.grid)))
            self.move_left()
            self.grid = list(map(list, zip(*self.grid)))
        elif direction == "down":
            self.grid = list(map(list, zip(*self.grid)))
            self.move_right()
            self.grid = list(map(list, zip(*self.grid)))
        elif direction == "left":
            self.move_left()
        elif direction == "right":
            self.move_right()

此方法为移动准备网格,调用适当的移动函数,然后重置网格。

✨ 查看解决方案并练习

将方块向左移动

定义一个方法,将一行中的方块向左移动。

    def move_left(self):
        for i in range(4):
            row = self.grid[i]
            row = [value for value in row if value!= 0]
            while len(row) < 4:
                row.append(0)

            for j in range(3):
                if row[j] == row[j + 1] and row[j]!= 0:
                    row[j] *= 2
                    row[j + 1] = 0
                    self.score += row[j]

            row = [value for value in row if value!= 0]
            while len(row) < 4:
                row.append(0)
            self.grid[i] = row

此方法处理方块向左移动,在可能的情况下合并相邻方块并填充空单元格。

✨ 查看解决方案并练习

将方块向右移动

定义一个方法,将一行中的方块向右移动。

    def move_right(self):
        for i in range(4):
            row = self.grid[i]
            row = [value for value in row if value!= 0]
            while len(row) < 4:
                row.insert(0, 0)

            for j in range(3, 0, -1):
                if row[j] == row[j - 1] and row[j]!= 0:
                    row[j] *= 2
                    row[j - 1] = 0
                    self.score += row[j]

            row = [value for value in row if value!= 0]
            while len(row) < 4:
                row.insert(0, 0)
            self.grid[i] = row

此方法负责将方块向右移动,在适当的时候合并它们,并填充空白处。

✨ 查看解决方案并练习

检查游戏是否结束

创建一个方法来检查游戏是否结束。当无法再进行移动时,游戏结束。

    def is_game_over(self):
        for i in range(4):
            for j in range(4):
                if self.grid[i][j] == 0:
                    return False

        for i in range(4):
            for j in range(3):
                if self.grid[i][j] == self.grid[i][j + 1]:
                    return False

        for j in range(4):
            for i in range(3):
                if self.grid[i][j] == self.grid[i + 1][j]:
                    return False

        return True

此方法通过检查网格中是否包含空单元格或具有相同值的相邻单元格,来判断是否还能进行更多移动。如果无法再进行移动,则游戏结束。

✨ 查看解决方案并练习

运行项目

最后,切换到桌面并使用以下命令运行项目:

python 2048_game.py
2048游戏
✨ 查看解决方案并练习

总结

在这个项目中,你学习了如何使用Tkinter库在Python中创建一个简单的2048游戏。你从设置项目、创建主Python文件以及定义Game2048类开始。然后,你实现了按键操作、方块移动,并检查了游戏结束条件。游戏界面可能不是最现代和美观的,但你现在有了一个基础,可以在此基础上进行改进和定制,以创建一个更精致的2048游戏。要运行该项目,你可以按照以下步骤操作。