【游戏制作】使用Python创建一个完整的2048游戏项目

 

目录

项目运行展示

项目概述

项目目标

项目结构

安装依赖

代码实现

1. 导入库

2. 创建 Game2048 类

 3. 设置UI界面

 4. 加载二维码图片

5. 创建菜单 

6. 游戏逻辑和功能 

 7. 运行应用

总结


创建一个完整的2048游戏项目

项目运行展示

项目概述

在这个项目中,我们将创建一个2048游戏的桌面应用程序。这个游戏是一个流行的数学游戏,玩家通过合并相同的数字块来达到2048。我们将使用 ttkbootstrap 库为应用程序添加现代化的外观,并且通过 tkinterPIL 实现游戏的功能和界面。

项目目标
  • 实现2048游戏的逻辑和UI
  • 添加历史记录功能
  • 实现主题和窗口大小的动态修改
  • 加载和显示二维码图片
  • 添加游戏开始和结束的逻辑
项目结构
  1. 主程序文件: game2048.py — 包含游戏逻辑和界面实现。
  2. 资源文件: 1.gif — 二维码图片资源。
安装依赖

确保你已经安装了以下Python库:

  • tkinter (Python的标准库,通常默认安装)
  • ttkbootstrap (用于增强tkinter的UI)
  • Pillow (用于处理图像)

可以通过以下命令安装缺失的依赖:

pip install ttkbootstrap pillow
代码实现
1. 导入库
import tkinter as tk
import ttkbootstrap as ttk
from ttkbootstrap.constants import *
from tkinter import Menu, Toplevel, messagebox, simpledialog
import random
import datetime
from PIL import Image, ImageTk
2. 创建 Game2048
class Game2048(ttk.Window):def __init__(self):super().__init__(title="2048 Game", themename="superhero")self.grid()self.cells = [[None for _ in range(4)] for _ in range(4)]self.history = []self.setup_ui()self.create_menu()self.start_game()
 3. 设置UI界面
    def setup_ui(self):self.title("2048 Game")self.geometry("800x600")self.resizable(False, False)self.main_grid = ttk.Frame(self, style='secondary.TFrame')self.main_grid.grid(row=0, column=0, padx=(10, 10), pady=(10, 10))for i in range(4):row = []for j in range(4):cell_frame = ttk.Frame(self.main_grid, width=100, height=100, style='primary.TFrame')cell_frame.grid(row=i, column=j, padx=5, pady=5)cell_number = ttk.Label(self.main_grid, text="", style='primary.Inverse.TLabel', font=("Helvetica", 24, "bold"))cell_number.grid(row=i, column=j)cell_data = {"frame": cell_frame, "number": cell_number}row.append(cell_data)self.cells[i] = rowself.score_label = ttk.Label(self, text="Score: 0", style='info.TLabel', font=("Helvetica", 16))self.score_label.grid(row=1, column=0, columnspan=4, pady=(0, 10))# 加载二维码图片self.load_qr_code()self.bind_keys()
 4. 加载二维码图片
    def load_qr_code(self):image = Image.open("1.gif")  # 替换为你的二维码图片路径image = image.resize((150, 150), Image.ANTIALIAS)self.qr_code_image = ImageTk.PhotoImage(image)self.qr_code_label = ttk.Label(self, image=self.qr_code_image)self.qr_code_label.grid(row=0, column=1, padx=(10, 10), pady=(10, 10))self.qr_code_text = ttk.Label(self, text="B站优秀稳妥的小光", style='info.TLabel', font=("Helvetica", 16))self.qr_code_text.grid(row=0, column=1, pady=(170, 10))
5. 创建菜单 
    def create_menu(self):menubar = Menu(self)# 历史记录菜单history_menu = Menu(menubar, tearoff=0)history_menu.add_command(label="查看历史分数", command=self.show_history)menubar.add_cascade(label="历史记录", menu=history_menu)# 查看菜单view_menu = Menu(menubar, tearoff=0)view_menu.add_command(label="查看日期", command=self.show_date)view_menu.add_command(label="查看开发者", command=self.show_developer)menubar.add_cascade(label="查看", menu=view_menu)# 修改菜单edit_menu = Menu(menubar, tearoff=0)# 修改主题子菜单theme_menu = Menu(edit_menu, tearoff=0)style = ttk.Style()theme_names = style.theme_names()for theme_name in theme_names:theme_menu.add_command(label=theme_name, command=lambda t=theme_name: self.change_theme(t))edit_menu.add_cascade(label="修改主题", menu=theme_menu)# 修改窗口大小功能edit_menu.add_command(label="修改窗口大小", command=self.change_window_size)menubar.add_cascade(label="修改", menu=edit_menu)self.config(menu=menubar)
6. 游戏逻辑和功能 
    def start_game(self):self.matrix = [[0] * 4 for _ in range(4)]self.score = 0self.add_new_tile()self.add_new_tile()self.update_ui()def add_new_tile(self):empty_cells = [(i, j) for i in range(4) for j in range(4) if self.matrix[i][j] == 0]if empty_cells:i, j = random.choice(empty_cells)self.matrix[i][j] = 2 if random.random() < 0.9 else 4def update_ui(self):for i in range(4):for j in range(4):cell_value = self.matrix[i][j]if cell_value == 0:self.cells[i][j]["frame"].configure(style='primary.TFrame')self.cells[i][j]["number"].configure(text="")else:self.cells[i][j]["frame"].configure(style=f'TFrame')self.cells[i][j]["number"].configure(text=str(cell_value), font=("Helvetica", 24, "bold"))self.score_label.configure(text=f"Score: {self.score}")self.update_idletasks()def move_up(self, event):self.move_tiles(0, -1)self.merge_tiles(0, -1)self.move_tiles(0, -1)self.add_new_tile()self.update_ui()self.check_game_over()def move_down(self, event):self.move_tiles(0, 1)self.merge_tiles(0, 1)self.move_tiles(0, 1)self.add_new_tile()self.update_ui()self.check_game_over()def move_left(self, event):self.move_tiles(-1, 0)self.merge_tiles(-1, 0)self.move_tiles(-1, 0)self.add_new_tile()self.update_ui()self.check_game_over()def move_right(self, event):self.move_tiles(1, 0)self.merge_tiles(1, 0)self.move_tiles(1, 0)self.add_new_tile()self.update_ui()self.check_game_over()def move_tiles(self, x, y):def move(x, y, i, j):if self.matrix[i][j] != 0:ni, nj = i + x, j + ywhile 0 <= ni < 4 and 0 <= nj < 4 and self.matrix[ni][nj] == 0:self.matrix[ni][nj] = self.matrix[i][j]self.matrix[i][j] = 0i, j = ni, njni, nj = i + x, j + yfor i in range(4):for j in range(4):if x == -1:move(x, y, i, j)if x == 1:move(x, y, 3 - i, j)if y == -1:move(x, y, j, i)if y == 1:move(x, y, j, 3 - i)def merge_tiles(self, x, y):def merge(x, y, i, j):ni, nj = i + x, j + yif 0 <= ni < 4 and 0 <= nj < 4 and self.matrix[i][j] == self.matrix[ni][nj] and self.matrix[i][j] != 0:self.matrix[ni][nj] *= 2self.matrix[i][j] = 0self.score += self.matrix[ni][nj]for i in range(4):for j in range(4):if x == -1:merge(x, y, i, j)if x == 1:merge(x, y, 3 - i, j)if y == -1:merge(x, y, j, i)if y == 1:merge(x, y, j, 3 - i)def show_history(self):history_window = Toplevel(self)history_window.title("历史分数")history_window.geometry("320x420")history_text = tk.Text(history_window, wrap="word")history_text.pack(expand=1, fill="both")for record in self.history:history_text.insert("end", record + "\n")def show_date(self):current_date = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")messagebox.showinfo("当前日期和时间", current_date)def show_developer(self):messagebox.showinfo("开发者信息", "开发者: B站 优秀稳妥的小光")def check_game_over(self):if not any(0 in row for row in self.matrix) and not self.can_merge():self.history.append(f"Score: {self.score}")messagebox.showinfo("Game Over", f"Game Over! Your Score: {self.score}")self.start_game()def can_merge(self):for i in range(4):for j in range(4):if j < 3 and self.matrix[i][j] == self.matrix[i][j + 1]:return Trueif i < 3 and self.matrix[i][j] == self.matrix[i + 1][j]:return Truereturn False
 7. 运行应用
if __name__ == "__main__":app = Game2048()app.mainloop()
总结

这个2048游戏项目展示了如何使用 tkinterttkbootstrap 创建一个具有现代化外观的桌面游戏应用程序。我们实现了基本的游戏逻辑、动态更新UI、以及附加的功能如历史记录、二维码显示和主题切换。通过这个项目,你可以深入了解如何使用Python创建复杂的图形用户界面,并且扩展到更多的功能和设计。

 交流扩列在主页加WX 

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

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

19 Python常用内置函数——range()

range() 是 Python 开发中非常常用的一个内置函数。该函数返回具有惰性求值特点的 range 对象&#xff0c;其中包含左闭右开区间 [start, end) 内以 step 为步长的整数。 参数 start 默认为 0&#xff0c;step 默认为 1。 print(range(5)) print(list(range(5))) print(list(r…

Zenario CMS 9.2 文件上传漏洞(CVE-2022-23043)

前言 CVE-2022-23043 是一个影响 Zenario CMS 9.2 的严重漏洞。该漏洞允许经过身份验证的管理员用户绕过文件上传限制。具体来说&#xff0c;管理员可以通过创建一个新的带有 ".phar" 扩展名的“文件/MIME 类型”&#xff0c;然后上传一个恶意文件。在上传过程中&am…

Java从入门到精通 (十一) ~ 操作系统、进程和线程

无论做什么&#xff0c;请记住都是为你自己而做&#xff0c;这样就毫无怨言&#xff01;今天&#xff0c;我为自己而活&#xff01;今天&#xff0c;又是美丽的一天&#xff01;早安&#xff0c;朋友&#xff01; 目录 前言 一、操作系统 1. 概念 2. 操作系统的基本功能 3…

FPGA开发——LED流水灯实现先从左往右流水,再从右往左流水

一、概述 我们在设计完一个方向的流水灯的设计时&#xff0c;总是会想实现让流水灯倒着流水回去的设计&#xff0c;这里我也是一样&#xff0c;实现这种设计的方法有很多种&#xff0c;其中就有直接使用case语句将所有可能包含进去编写&#xff0c;这种设计方法是最简单的&…

高翔【自动驾驶与机器人中的SLAM技术】学习笔记(四)高斯牛顿法详解

一、高斯牛顿法详解 拓展阅读&#xff1a;高斯牛顿法详解_gauss-newton算法步骤-CSDN博客 1、梯度下降法 ​ ​ ​ 无论一阶泰勒展开&#xff0c;还是二阶泰勒展开都是关于增量​的方程。 2、牛顿法 ​ 这个自变量增量都是可求的。但是二阶求解复杂。因此为了简化有了下…

windows下运行sh文件

1、打开git bash 2、进入sh文件所在文件夹&#xff0c;使用sh xx.sh运行

@RequiredArgsConstructor详解

RequiredArgsConstructor详解 一、什么是RequiredArgsConstructor? RequiredArgsConstructor是Lombok的一个注解&#xff0c;简化了我们对Autowired书写&#xff0c;我们在写Controller层或者Service层的时候&#xff0c;总是需要注入很多mapper接口或者service接口&#xf…

初识Play Framework框架和第一个Java play web项目的创建

文章目录 初识Play Framework框架和第一个Java play web项目的创建一、简介特点架构开发流程示例代码总结 二、创建第一个Java play web项目1、下载play框架&#xff0c;配置系统环境变量(jdk的安装就不再说了) 2、检查play的版本和创建第一个play项目3、将项目通过idea或eclip…

【NoSQL数据库】Redis知识小册

一、缓存穿透 缓存穿透是先查Redis&#xff0c;发现缓存中没有数据&#xff0c;再查数据库。然而&#xff0c;如果查询的数据在数据库中也不存在&#xff0c;那么每次查询都会绕过缓存&#xff0c;直接落到数据库上。 解决方案一、缓存空数据 查询Redis缓存&#xff1a;首先查…

Java泛型的介绍和基本使用

什么是泛型 ​ 泛型就是将类型参数化&#xff0c;比如定义了一个栈&#xff0c;你必须在定义之前声明这个栈中存放的数据的类型&#xff0c;是int也好是double或者其他的引用数据类型也好&#xff0c;定义好了之后这个栈就无法用来存放其他类型的数据。如果这时候我们想要使用这…

Codeforces 903 div3 A-F

A 题目分析 数据范围很小&#xff0c;暴力枚举即可&#xff0c;然后给字符串x的长度设置一个上限&#xff0c;我设了50&#xff0c;因为n*m<25&#xff0c;多一倍够用了 C代码 #include<iostream> using namespace std; void solve(){int n,m;string x,s;cin>>…

基于RS485的Modbus协议

RS485&#xff1a;用来传输数据&#xff0c;RS485是一种差分传输的串行通信标准&#xff0c;以其强大的抗干扰能力、长距离传输和多点通信能力&#xff0c;在工业控制领域得到广泛应用。RS485使用一对差分信号线&#xff08;A和B&#xff09;来传输数据&#xff0c;差分信号能有…

eclipse ui bug

eclipse ui bug界面缺陷&#xff0c;可能项目过多&#xff0c;特别maven项目过多&#xff0c;下载&#xff0c;自动编译&#xff0c;加载更新界面异常 所有窗口死活Restore不回去了 1&#xff09;尝试创建项目&#xff0c;还原界面&#xff0c;失败 2&#xff09;关闭所有窗口&…

Django学习(二)

get请求 练习&#xff1a; views.py def test_method(request):if request.method GET:print(request.GET)# 如果链接中没有参数a会报错print(request.GET[a])# 使用这个方法&#xff0c;当查询不到参数时&#xff0c;不会报错而是返回你设置的值print(request.GET.get(c,n…

winrar安装好后,鼠标右键没有弹出解压的选项

本来安装挺好的&#xff0c;可以正常使用&#xff0c;有天我把winrar相关的文件挪了个位置&#xff0c;就不能正常使用了。 然后我去应用里面找&#xff0c;找到应用标识了&#xff0c;但是找不到对应的文件夹&#xff08;因为我挪到另外一个文件夹里了&#xff09;。 于是我找…

语言转文字

因为工作原因需要将语音转化为文字&#xff0c;经常搜索终于找到一个免费的好用工具&#xff0c;记录下使用方法 安装Whisper 搜索Colaboratory 右上方链接服务 执行 !pip install githttps://github.com/openai/whisper.git !sudo apt update && sudo apt install f…

Android 软键盘挡住输入框

Android原生输入法软键盘挡住输入框,网上各种解法,但不起效。 输入框都是被挡住了,第二张图的小点,实际就是输入法的光标。 解法: packages\inputmethods\LatinIME\java\res\values-land config.xml <!-- <fraction name="config_min_keyboard_height"&g…

pikachu靶场之目录遍历、敏感信息泄露

一、目录遍历 漏洞概述 在web功能设计中,很多时候我们会要将需要访问的文件定义成变量&#xff0c;从而让前端的功能便的更加灵活。 当用户发起一个前端的请求时&#xff0c;便会将请求的这个文件的值(比如文件名称)传递到后台&#xff0c;后台再执行其对应的文件。 在这个过…

如何评价估计量的好坏

目录 三大方法 概念 无偏性 如何计算估计量的无偏性&#xff1f; 步骤 有效性 有效性在不同类型的数据分析中如何评估&#xff1f; 步骤 一致性 一致性原则在实际应用中的挑战有哪些&#xff1f; 挑战 在大样本情况下&#xff0c;如何准确测量估计量的一致性&#xf…

AcWing-差分矩阵

insert函数影响范围&#xff0c;在b差分数组这样操作影响到是a里面的&#xff0c;所以下图的矩阵表示的是a数组 b[x1][y1]c;会导致a里面仅绿色范围的a[i][j]c b[x1][y21]-c;会导致a里面仅黄色范围的a[i][j]-c b[x21][y1]-c;会导致a里面仅蓝色范围的a[i][j]-c b[x21][y21]c;会导…