用 Python 实现经典的 2048 游戏:一步步带你打造属于你的小游戏!

用 Python 实现经典的 2048 游戏:一步步带你打造属于你的小游戏!(结尾附完整代码)

简介

2048 是一个简单而又令人上瘾的数字拼图游戏。玩家通过滑动方块使相同数字的方块合并,目标是创造出数字 2048!在这篇博客中,我们将用 Python 的 Tkinter 库 从零开始实现这款游戏,涵盖从界面设计到逻辑实现的每一个细节,帮助你全面了解背后的开发思路。

游戏特点

  • 经典玩法:滑动合并相同数字,尽可能达到 2048。
  • 随机生成新数字:每次滑动后随机生成 2 或 4。
  • 直观的图形界面:使用 Tkinter 绘制游戏网格与方块,带来清晰的视觉效果。

开发环境准备

在开始之前,确保你的环境已安装 Python,并包含以下必要库:

pip install tk

Tkinter 是 Python 内置的 GUI 工具包,因此大多数环境无需额外安装。 

项目实现步骤

我们将按照以下步骤构建游戏:

  1. 设计网格界面
  2. 实现核心逻辑
  3. 绑定键盘事件
  4. 添加游戏结束检测
  5. 优化用户体验

1. 设计网格界面

首先,我们定义游戏的基本参数,包括网格大小、方块的尺寸、间距和颜色等。随后,通过 Tkinter 创建一个网格界面,每个格子将用矩形和文本元素表示。

import tkinter as tk
from tkinter import messagebox
import random# 常量定义
GRID_SIZE = 4  # 网格为 4x4
TILE_SIZE = 100  # 每个方块的像素大小
PADDING = 10  # 方块之间的间距
BACKGROUND_COLOR = "#92877d"
TILE_COLORS = {0: "#9e948a", 2: "#eee4da", 4: "#ede0c8",8: "#f2b179", 16: "#f59563", 32: "#f67c5f",64: "#f65e3b", 128: "#edcf72", 256: "#edcc61",512: "#edc850", 1024: "#edc53f", 2048: "#edc22e",
}# 初始化游戏界面
class Game2048:def __init__(self, master):self.master = masterself.master.title("2048")self.master.geometry(f"{GRID_SIZE * TILE_SIZE + PADDING * (GRID_SIZE + 1)}x{GRID_SIZE * TILE_SIZE + PADDING * (GRID_SIZE + 1)}")self.master.resizable(False, False)self.init_grid()self.reset_game()def init_grid(self):"""创建 4x4 网格"""self.canvas = tk.Canvas(self.master, bg=BACKGROUND_COLOR, bd=0, highlightthickness=0)self.canvas.pack(fill=tk.BOTH, expand=True)self.tiles = []for i in range(GRID_SIZE):row = []for j in range(GRID_SIZE):x1 = PADDING + j * (TILE_SIZE + PADDING)y1 = PADDING + i * (TILE_SIZE + PADDING)x2 = x1 + TILE_SIZEy2 = y1 + TILE_SIZErect = self.canvas.create_rectangle(x1, y1, x2, y2, fill=TILE_COLORS[0], outline="")text = self.canvas.create_text(x1 + TILE_SIZE // 2, y1 + TILE_SIZE // 2, text="", font=("Helvetica", 30), fill="#776e65")row.append((rect, text))self.tiles.append(row)

 运行效果:运行后你会看到一个 4x4 的灰色网格,每个格子代表一个方块。

 

2. 实现核心逻辑

游戏的逻辑主要包括:

  • 压缩和合并数字:将相邻的数字合并。
  • 滑动方向操作:实现上下左右滑动功能。
  • 随机生成新数字:在空格中随机生成 2 或 4。
压缩与合并

每次滑动操作可以拆分为两部分:压缩(去掉空格)合并(合并相邻的相同数字)

def compress(row):"""将行向左压缩,去掉 0"""new_row = [num for num in row if num != 0]new_row += [0] * (GRID_SIZE - len(new_row))return new_rowdef merge(row):"""合并相邻相同的数字"""for i in range(len(row) - 1):if row[i] == row[i + 1] and row[i] != 0:row[i] *= 2row[i + 1] = 0return row
滑动操作

根据方向执行不同操作(上下左右)。

def move_left(grid):"""左移操作"""new_grid = []for row in grid:compressed_row = compress(row)merged_row = merge(compressed_row)new_grid.append(compress(merged_row))return new_grid
随机生成数字

每次滑动后随机选择一个空格,填入 2 或 4。

def spawn_new_tile(grid):"""随机生成一个新的数字方块(2 或 4)"""empty_cells = [(i, j) for i in range(GRID_SIZE) for j in range(GRID_SIZE) if grid[i][j] == 0]if empty_cells:i, j = random.choice(empty_cells)grid[i][j] = 2 if random.random() < 0.9 else 4

3. 绑定键盘事件

为了让游戏动起来,我们需要捕获用户的按键(上下左右方向键),并根据按键更新网格状态。

def key_press(event):"""处理键盘输入"""key = event.keysymif key in ["Up", "Down", "Left", "Right"]:if key == "Up":game.grid = move_left(rotate_left(game.grid))game.grid = rotate_right(game.grid)elif key == "Down":game.grid = move_left(rotate_right(game.grid))game.grid = rotate_left(game.grid)elif key == "Left":game.grid = move_left(game.grid)elif key == "Right":game.grid = move_left(reverse_rows(game.grid))game.grid = reverse_rows(game.grid)spawn_new_tile(game.grid)game.update_ui()if is_game_over(game.grid):messagebox.showinfo("Game Over", "No more moves left!")

4. 添加游戏结束检测

当所有格子都被填满且没有可合并的数字时,游戏结束。

def is_game_over(grid):"""判断是否还有有效操作"""for i in range(GRID_SIZE):for j in range(GRID_SIZE):if grid[i][j] == 0:  # 空格存在return Falseif j + 1 < GRID_SIZE and grid[i][j] == grid[i][j + 1]:  # 横向可合并return Falseif i + 1 < GRID_SIZE and grid[i][j] == grid[i + 1][j]:  # 纵向可合并return Falsereturn True

5. 完整代码

将上述代码整合的完整代码如下:运行后即可得到完整的 2048 游戏!

import tkinter as tk
from tkinter import messagebox
import random# 常量定义
GRID_SIZE = 4
TILE_SIZE = 100
PADDING = 10
BACKGROUND_COLOR = "#92877d"
TILE_COLORS = {0: "#9e948a", 2: "#eee4da", 4: "#ede0c8",8: "#f2b179", 16: "#f59563", 32: "#f67c5f",64: "#f65e3b", 128: "#edcf72", 256: "#edcc61",512: "#edc850", 1024: "#edc53f", 2048: "#edc22e",
}class Game2048:def __init__(self, master):self.master = masterself.master.title("2048")self.master.geometry(f"{GRID_SIZE * TILE_SIZE + PADDING * (GRID_SIZE + 1)}x{GRID_SIZE * TILE_SIZE + PADDING * (GRID_SIZE + 1)}")self.master.resizable(False, False)self.init_grid()self.reset_game()def init_grid(self):"""初始化网格界面"""self.canvas = tk.Canvas(self.master, bg=BACKGROUND_COLOR, bd=0, highlightthickness=0)self.canvas.pack(fill=tk.BOTH, expand=True)self.tiles = []for i in range(GRID_SIZE):row = []for j in range(GRID_SIZE):x1 = PADDING + j * (TILE_SIZE + PADDING)y1 = PADDING + i * (TILE_SIZE + PADDING)x2 = x1 + TILE_SIZEy2 = y1 + TILE_SIZErect = self.canvas.create_rectangle(x1, y1, x2, y2, fill=TILE_COLORS[0], outline="")text = self.canvas.create_text(x1 + TILE_SIZE // 2, y1 + TILE_SIZE // 2, text="", font=("Helvetica", 30), fill="#776e65")row.append((rect, text))self.tiles.append(row)def reset_game(self):"""重置游戏状态"""self.grid = [[0] * GRID_SIZE for _ in range(GRID_SIZE)]self.spawn_new_tile()self.spawn_new_tile()self.update_ui()def spawn_new_tile(self):"""随机生成一个新的数字方块(2 或 4)"""empty_cells = [(i, j) for i in range(GRID_SIZE) for j in range(GRID_SIZE) 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 4def update_ui(self):"""更新界面显示"""for i in range(GRID_SIZE):for j in range(GRID_SIZE):value = self.grid[i][j]rect, text = self.tiles[i][j]self.canvas.itemconfig(rect, fill=TILE_COLORS.get(value, TILE_COLORS[2048]))self.canvas.itemconfig(text, text=str(value) if value != 0 else "")def compress(row):"""将行向左压缩,去掉 0"""new_row = [num for num in row if num != 0]new_row += [0] * (GRID_SIZE - len(new_row))return new_rowdef merge(row):"""合并相邻相同的数字"""for i in range(len(row) - 1):if row[i] == row[i + 1] and row[i] != 0:row[i] *= 2row[i + 1] = 0return rowdef move_left(grid):"""左移操作"""new_grid = []for row in grid:compressed_row = compress(row)merged_row = merge(compressed_row)new_grid.append(compress(merged_row))return new_griddef rotate_right(grid):"""矩阵顺时针旋转 90°"""return [list(row) for row in zip(*grid[::-1])]def rotate_left(grid):"""矩阵逆时针旋转 90°"""return [list(row) for row in zip(*grid)][::-1]def reverse_rows(grid):"""矩阵水平翻转"""return [row[::-1] for row in grid]def is_game_over(grid):"""判断是否还有有效操作"""for i in range(GRID_SIZE):for j in range(GRID_SIZE):if grid[i][j] == 0:  # 空格存在return Falseif j + 1 < GRID_SIZE and grid[i][j] == grid[i][j + 1]:  # 横向可合并return Falseif i + 1 < GRID_SIZE and grid[i][j] == grid[i + 1][j]:  # 纵向可合并return Falsereturn Truedef key_press(event):"""处理键盘输入"""key = event.keysymif key in ["Up", "Down", "Left", "Right"]:if key == "Up":game.grid = move_left(rotate_left(game.grid))game.grid = rotate_right(game.grid)elif key == "Down":game.grid = move_left(rotate_right(game.grid))game.grid = rotate_left(game.grid)elif key == "Left":game.grid = move_left(game.grid)elif key == "Right":game.grid = move_left(reverse_rows(game.grid))game.grid = reverse_rows(game.grid)game.spawn_new_tile()game.update_ui()if is_game_over(game.grid):messagebox.showinfo("Game Over", "No more moves left!")root = tk.Tk()
game = Game2048(root)
root.bind("<Key>", key_press)
root.mainloop()

通过本篇博客,我们从头实现了经典的 2048 游戏。不仅让你掌握了 Tkinter 界面开发,还深入理解了游戏逻辑的实现过程。如果你喜欢这篇博客,请分享给更多的 Python 爱好者吧!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/889737.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Go】-倒排索引的简单实现

目录 什么是倒排索引 定义 基本结构和原理 分词在倒排索引中的重要性 简单倒排索引的实现 接口定义 简单数据库的实现 倒排索引 正排索引 测试 总结 什么是倒排索引 定义 倒排索引&#xff08;Inverted Index&#xff09;是一种索引数据结构&#xff0c;它是文档检…

智汇云舟4个案例入选“中国联通智慧城市物联感知与AI应用案例”

12月10日&#xff0c;由中国联通智慧城市军团联合联通数字科技有限公司物联网事业部、物联中国团体组织联席会共同主办的“中国联通首届智慧城市领域物联感知与AI应用优秀案例发布交流大会”在郑州举行。大会现场对50余个优秀案例进行了集中发布与表彰。智汇云舟凭借深厚的技术…

http 502 和 504 的区别

首先看一下概念&#xff1a; 502&#xff1a;作为网关或者代理工作的服务器尝试执行请求时&#xff0c;从上游服务器接收到无效的响应。503&#xff1a;由于临时的服务器维护或者过载&#xff0c;服务器当前无法处理请求。这个状况是临时的&#xff0c;并且将在一段时间以后恢…

博弈论3:图游戏SG函数(Graph Games)

目录 一、图游戏是什么 1.游戏特征 2.游戏实例 二、图游戏的必胜策略 1.SG 函数&#xff08;Sprague-Grundy Function&#xff09; 2.必胜策略&#xff08;利用SG函数&#xff09; 3.拿走游戏转化成图游戏&#xff08;Take-away Game -> Graph Game&#xff09; 一、图…

免费生成AI PPT产品推荐?

要完全免费几乎是没有的&#xff0c;要知道AI还是非常烧钱的。 不过免费蹭还是有很多方法的&#xff0c;这里收集了一些&#xff1a; 下面分享我自己免费蹭过的几款AI制作PPT的工具。 1 金山-WPS PPT对我们来说并不陌生&#xff0c;而微软的PowerPoint与金山的WPS也是我们最常…

Python机器视觉的学习

一、二值化 1.1 二值化图 二值化图&#xff1a;就是将图像中的像素改成只有两种值&#xff0c;其操作的图像必须是灰度图。 1.2 阈值法 阈值法&#xff08;Thresholding&#xff09;是一种图像分割技术&#xff0c;旨在根据像素的灰度值或颜色值将图像分成不同的区域。该方法…

Cisco Packet Tarcer配置计网实验笔记

文章目录 概要整体架构流程网络设备互连基础拓扑图拓扑说明配置步骤 RIP/OSPF混合路由拓扑图拓扑说明配置步骤 BGP协议拓扑图拓扑说明配置步骤 ACL访问控制拓扑图拓扑说明配置步骤 HSRP冗余网关拓扑图拓扑说明配置步骤 小结 概要 一些环境配置笔记 整体架构流程 网络设备互连…

【优选算法】二分算法(在排序数组中查找元素的第一个和最后一个位置,寻找峰值,寻找排序数组中的最小值)

二分算法简介&#xff1a; 提到二分我们可能都会想起二分查找&#xff0c;二分查找要求待查找的数组是有序的&#xff0c;与我们今天讲的二分算法不同&#xff0c;并不是数组元素严格按照有序排列才可以使用二分算法&#xff0c;只要数组中有一个点可以将数组分为两个部分&…

下载与使用PCL启动器(2.8.12正式版)

一.下载PCL启动器 PCL启动器下载官网&#xff1a;爱发电 连接创作者与粉丝的会员制平台将创作的自由还给创作者&#xff01;爱发电是让创作者简单地获得稳定收入的粉丝赞助平台。无论你在创作什么&#xff0c;都能在这里获得持续的资金支持&#xff0c;让创作从此更自由。htt…

【ArcGIS】基于R语言、MaxEnt模型融合技术的物种分布模拟、参数优化方法、结果分析制图与论文写作

第一章、以问题导入的方式&#xff0c;深入掌握原理基础【理论篇】 1、R语言入门&#xff1a; &#xff08;1&#xff09;安装R及集成开发环境&#xff08;IDE&#xff09;&#xff1b;&#xff08;2&#xff09;R语言基础语法与数据结构&#xff0c;包括&#xff1a;程序包安…

泊松编辑 possion editing图像合成笔记

开源地址&#xff1a; GitHub - kono-dada/Reproduction-of-possion-image-editing 掩码必须是矩形框

江科大笔记—DMA数据转运DMA+AD多通道

1. DMA初始化结构体详解 标准库函数对每个外设都建立了一个初始化结构体xxx_InitTypeDef(xxx为外设名称)&#xff0c;结构体成员用于设置外设工作参数&#xff0c; 并由标准库函数xxx_Init()调用这些设定参数进入设置外设相应的寄存器&#xff0c;达到配置外设工作环境的目的。…

程序算术题-2

程序算术题-2 输出所有组合逻辑实例代码 输出所有排列逻辑实例代码 输出所有组合 计算一组数字按n位数组合的所有组合。 逻辑 /*** param stringBuilder 用于组合的拼接* param list 组合数序列* param level 目前位数* param exceptedLevel 组合期待位数*/…

MAC M3电脑在idea上搭建Spark环境并跑通第一个程序

我的电脑是Macbook Pro&#xff0c;最近在学习Spark&#xff0c;想要在idea里搭建Spark环境&#xff0c;为之后的Spark编程作准备。下面是在MAC版本的idea里配置Spark环境。 1. 准备工作 1.安装 JDK 确保Mac 上已经安装了 JDK 8 或更高版本。 可通过 java -version 查看是否…

欧科云链研究院:AI时代,如何证明“我是我”?

OKG Research&#xff5c;编辑 近日&#xff0c;OpenAI 发布了新模型 Sora。这是一款高性能的文本到多模态生成工具&#xff0c;支持从文本生成精细的图像和动态视频。 相较早先发布的视频样例&#xff0c;该功能目前已经可以由用户真实上手体验&#xff0c;目前由于服务过载…

任务5 Web服务配置与管理

Web服务概述 Web服务简介 当今人们获取和传播信息的主要方式之一。 Web服务提供的资源多种多样&#xff0c;可能是简单的文本&#xff0c;也可能是图片、音频和视频等多媒体数据。 常用的浏览器有Chrome、Internet Explorer&#xff0c;以及Firefox等。 手机等移动设备成为…

Opencv之图像添加水印

一、实验原理 在图片处理领域&#xff0c;添加水印是一种常见的操作。通过叠加图像的方式&#xff0c;可以将水印无缝嵌入目标图像的指定位置。其基本原理包括以下步骤&#xff1a; 1、模板输入&#xff08;掩膜生成&#xff09;&#xff1a; 将水印图片转换为灰度图&#xf…

「Mac玩转仓颉内测版50」小学奥数篇13 - 动态规划入门

本篇将通过 Python 和 Cangjie 双语介绍动态规划的基本概念&#xff0c;并解决一个经典问题&#xff1a;斐波那契数列。学生将学习如何使用动态规划优化递归计算&#xff0c;并掌握编程中的重要算法思想。 关键词 小学奥数Python Cangjie动态规划斐波那契数列 一、题目描述 …

远程调试软件对比与使用推荐

远程调试软件对比与使用推荐 远程调试是现代软件开发中不可或缺的一部分&#xff0c;尤其是在处理分布式系统、云端服务或远程服务器上的问题时。以下是对几种常见远程调试工具的详细对比和推荐使用场景。 1. GDB (GNU Debugger) 特点 开源&#xff1a;完全免费且开源&…

HTML和JavaScript实现商品购物系统

下面是一个更全面的商品购物系统示例&#xff0c;包含新增商品、商品的增加删除以及结算找零的功能。这个系统使用HTML和JavaScript实现。 1.功能说明&#xff1a; 这个应用程序使用纯HTML和JavaScript实现。 包含一个商品列表和一个购物车区域。商品列表中有几个示例商品&a…