CS109_Project_HappyMatch
写在前面
本文记录了一些写CS109计算机程序设计基础期末project过程中的开发经验以及使用到的技术(这部分老师大概率不会讲,得自学)。
SUSTechCS109ProjectGuide
SUSTechCS109ProjectGuide是一篇学长写的project指南,里面写有许多有价值的建议,非常值得一看。
关于提问
开发的过程中难免会遇到很多陌生的问题或者bug,如果有时间,建议学习一下提问的智慧。
如果时间短缺,记住善用AI工具 > 搜索引擎 > 询问他人
。提出问题的时候,请提供清晰的截图
不要再用手机拍你的屏幕了、有用的报错信息
、详细完整的问题描述
,这会大大增加你解决问题的效率。
关于项目
题目
每学期的project都是对于某一种游戏玩法的复刻,而2023秋学期的主题是三消游戏
,和主题相关的游戏有俄罗斯方块,开心消消乐等。
题目发布时间
详细的题目文档会在期中前后
发布,总共的开发周期有5-6周左右。
文档
pdf分数组成
跟据本学期和往年的经验,分数由80%的基础分和20%的bonus分数组成。
- 80%基础分数跟据题目文档判定
- 另外20%分数为bonus分,跟据几个维度判断:美观程度、额外功能、开发流程(比如有没有用git)、有无明显bug等等
DEMO
题目发布的同时,老师也会给出一个实现了部分功能的demo。你可以把这个理解成是一个框架,在这个基础框架上去完成你的项目。
但是对于有水平的同学,我建议不使用老师所给的框架。理由如下:
- 老师给出的框架大概率是Swing写的图形化界面,相比于Swing,更建议使用JavaFX。
- 有些地方可能受到框架限制,没法实现自己想要的功能。
- 不使用老师给的框架有加分…
项目设计
建议在拿到project题目的第一时间,对你的项目整体进行规划(比如要做出哪些界面,实现哪些功能),和队友商量好分工,并且制定好详细的计划。按照计划有的放矢,就不会出现只剩一周还没开始写的情况。听说很多人答辩前熬大夜
先放一个我在初期写的计划的框架。可以使用类似语雀等软件与你的队友共享文档,同步需求。
想要对项目有个整体的把握,不仅需要熟悉需求文档,还要仔细分析每个功能具体的实现。
关于AI工具的使用
本人极力提倡在开发的过程中使用AI工具,目的及理由如下(chatGPT生成):
- 提高开发效率:AI可以自动化一些重复性和繁琐的任务,如代码补全、缺陷检测和测试等,从而减少开发人员的工作量,提高开发效率。
- 提高代码质量:AI可以帮助开发人员发现潜在的缺陷和错误,并提供修复建议。它还可以生成高质量的代码,减少人为错误的产生。
- 加速学习和开发过程:AI可以根据开发人员的需求快速生成代码,从而加速学习和开发过程。它可以提供示例代码、算法实现和框架结构,帮助开发人员快速上手和实现想法。
在开发的过程中,对我帮助最大的莫过于copilot和chatGPT,前者提供了非常只能的代码补全功能,极大地加快了开发效率;后者不仅能帮你快速学习新的知识,还能帮你debug一些不常见的疑难杂症。
ps. AI工具只能作为你的开发助手,不要想让它帮你完成整个project。
copilot
非常好用,用到就是赚到,强力安利
通过Github的学生认证即可食用,网上教程很多,搜索一下即可。
简单的算法
写project前老师可能会布置一些相关的作业题,让你熟悉对应的游戏算法。
消除连续的方块
8*8
的地图分为两份,一份对行进行扫描,另一份对列经行扫描,存在三个以上相连的部分就标记为'0'
,最后对两张地图进行整合,去除所有标记为'0'
的方块。
代码
(未校验)
1 |
|
让悬空的方块掉落
遍历即可,还可以加入一些特殊的判断,比如边界、禁止方块等。
代码
1 |
|
技术部分
这部分存在一些超纲知识,如果对你来说太难了,可以跳过不看~。
Git
什么是Git
Git是一种分布式版本控制系统,用于跟踪和管理软件开发项目中的代码变更。它被广泛用于协作开发和版本管理,可以帮助团队成员在不同的开发环境中协同工作,并记录每个修改的历史。
如何使用GitHub
GitHub 教程:https://zhuanlan.zhihu.com/p/369486197
图形化界面
Swing
Swing是一个比较传统的GUI框架,由于课程中会讲解swing以及本人用了JavaFX,这里做简单介绍。
ChatGPT : Swing是Java平台上的一套GUI(图形用户界面)工具包,它提供了一系列的组件和工具,用于构建桌面应用程序的用户界面。下面是一些关键的概念和组件,帮助你入门Swing:
- JFrame:JFrame是Swing中的顶级窗口组件,它代表了一个可调整大小的窗口。你可以创建一个JFrame对象,并在其中添加其他组件,如按钮、文本框等。
- JPanel:JPanel是Swing中的容器组件,用于组织和布局其他组件。你可以将多个组件添加到JPanel中,并使用布局管理器来控制它们的位置和大小。
- JButton:JButton是一个按钮组件,用于触发特定的操作。你可以创建一个JButton对象,并为其设置文本、图标和事件处理程序,以便在用户点击按钮时执行相应的操作。
- JLabel:JLabel是一个标签组件,用于显示文本或图像。你可以创建一个JLabel对象,并将其添加到窗口中,以显示一些静态文本或图像。
- JTextField:JTextField是一个文本框组件,用于接收用户的输入。你可以创建一个JTextField对象,并将其添加到窗口中,以便用户可以输入文本。
- LayoutManager:布局管理器是Swing中用于管理组件布局的工具。Swing提供了多种布局管理器,如FlowLayout、BorderLayout和GridLayout等,它们可以帮助你自动调整和排列组件的位置和大小。
- 事件处理:Swing使用事件模型来处理用户的交互操作,例如点击按钮、输入文本等。你可以为组件注册事件监听器,并在事件发生时执行相应的操作。
- 这只是Swing的一小部分内容,它还提供了许多其他组件和功能,如复选框、下拉列表、对话框等。你可以通过阅读Swing的官方文档或参考一些教程和示例来深入学习和实践Swing。开始使用Swing时,建议从简单的示例开始,逐步探索并构建更复杂的界面。祝你在学习Swing的过程中取得成功!
Swing 可视化开发
开发图形化界面,离不开可视化的开发界面。
关于Swing的GUI设计器的食用方法,可以看看官方文档https://www.jetbrains.com/help/idea/gui-designer-basics.html。
JavaFX
先来个简单的介绍
ChatGPT : JavaFX是Java平台上的一套现代化的GUI(图形用户界面)工具包,用于构建丰富、交互式的桌面和移动应用程序的用户界面。下面是一些关键的概念和组件,帮助你了解JavaFX:
- Stage和Scene:在JavaFX中,应用程序的顶级容器是Stage,它代表了一个窗口。每个Stage包含一个或多个Scene,Scene定义了窗口中的内容和布局。
- Node:Node是JavaFX中的基本构建块,它代表了界面上的一个可视元素。JavaFX提供了许多内置的Node子类,如Button、Label、TextField等,你还可以创建自定义的Node。
- Layout:JavaFX提供了多种布局管理器,如VBox、HBox、BorderPane等,用于控制Node的位置和大小。布局管理器可以帮助你自动调整和排列节点,以适应不同的窗口大小和屏幕分辨率。
- CSS样式:JavaFX支持使用CSS(层叠样式表)来为界面元素设置样式。你可以使用CSS来定义节点的外观、背景、字体等属性,以及定义动画和过渡效果。
- 事件处理:JavaFX使用事件模型来处理用户的交互操作,例如点击按钮、拖动滑块等。你可以为节点注册事件处理器,并在事件发生时执行相应的操作。
- 动画和效果:JavaFX提供了丰富的动画和效果支持,可以实现平滑的过渡、缩放、旋转等效果,以及渐变、阴影、模糊等视觉效果。
- 多媒体和图形:JavaFX内置了对多媒体和图形的支持,你可以播放音频和视频文件,加载和显示图像,创建图形和图表等。
- JavaFX还提供了其他一些功能,如WebView(用于显示Web内容)、打印支持、国际化等。JavaFX的设计目标是提供一个现代化、易用且高性能的GUI开发框架,它在Java平台上得到了广泛的应用和支持。
- 你可以通过阅读JavaFX的官方文档、教程和示例来深入学习和实践JavaFX。开始使用JavaFX时,建议从简单的示例开始,逐步探索和构建更复杂的界面。祝你在学习JavaFX的过程中取得成功!
Scene Builder
JavaFX Scene Builder是一个可视化布局工具,用于设计和构建JavaFX应用程序的用户界面。它提供了拖放和配置组件的界面,简化了界面布局的过程。你可以选择组件、调整大小和位置,并设置CSS样式和事件处理。它与JavaFX紧密集成,可以与Java IDE配合使用。Scene Builder是一个强大而直观的工具,加速了JavaFX界面开发的过程。
安装
Scene Builder 的安装网址: https://www.oracle.com/java/technologies/javafxscenebuilder-1x-archive-downloads.html
选择合适的版本下载
- 可能需要登录Oracle账号,注册一个即可
- 下载完后打开,根据引导完成安装
- 接下来进行idea的配置:在新版本中,JavaFX插件已经内置,旧版本可
能需要手动下载。
- 接下来进行软件的绑定,如图设置SceneBuilder的运行路径即可。
HelloWorld-第一个JavaFx程序
- 创建JavaFX项目,如图选择
- 初始程序
- 右键
hello-view.fxml
-> 选择在SceneBuilder 中打开
- SceneBuilder 界面如图
- Controller中可以设置对应的控制类(示例代码已经给出对应的控制类)
- 如何设置监听事件
如图,选择控件 > 切换到code界面 > 在想要监听的事件处写上方法名
- 保存fxml文件,回到控制类,写上同名的控制方法。注意用
@FXML
标记。
- 运行查看成果~
一些食用技巧
Scene Builder 预览界面
Scene Builder 控制类代码示例
快速生成控制类的代码~
Scene Builder 使用CSS
具体规则可参考:https://docs.oracle.com/javase/8/javafx/api/javafx/scene/doc-files/cssref.html
JavaFX 多界面切换
目录结构如下
1 |
|
- OtherPage.fxml 设置
- 源码
HelloController.javaOtherPage.java1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16public class HelloController {
@FXML
private Label welcomeText;
@FXML
void btnClick() throws IOException {
Stage primaryStage = (Stage) welcomeText.getScene().getWindow();
//加载fxml文件
URL url = getClass().getResource("OtherPage.fxml");
//加载完fxml文件后,获取其中的root
Parent root = FXMLLoader.load(Objects.requireNonNull(url));
//设置场景
Scene scene = new Scene(root);
primaryStage.setScene(scene);
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15public class OtherPage {
@FXML
Button btn;
@FXML
void gotoMain() throws IOException {
Stage primaryStage = (Stage) btn.getScene().getWindow();
//加载fxml文件
URL url = getClass().getResource("hello-view.fxml");
//加载完fxml文件后,获取其中的root
Parent root = FXMLLoader.load(Objects.requireNonNull(url));
//设置场景
Scene scene = new Scene(root);
primaryStage.setScene(scene);
}
} - 效果
JavaFX 播放音频
下面是一个简单的音频播放类,其中包含一个静态方法用于播放音频。你可以将以下代码保存到一个名为AudioPlayer.java的文件中:
1 |
|
你需要在 pom.xml
中配置依赖
1 |
|
使用示例:
1 |
|
JavaFX就介绍到这里,更多操作自行探索吧~
服务端
根据不同的项目,可以按照需求选择要不要写服务端。
服务端可以干什么
GPT: 游戏的服务器端通常承担着多个功能和责任。以下是游戏服务器端可能承担的一些常见任务和功能:
- 游戏逻辑处理:服务器端负责处理游戏的逻辑和规则。它会验证和执行玩家的操作,并确保游戏状态的一致性和合法性。服务器端会处理游戏中的各种事件、计算分数、处理胜负条件等。
- 网络通信:服务器端负责处理与客户端之间的网络通信。它接收来自客户端的请求和指令,并将游戏状态和更新发送回客户端。服务器端还负责处理网络连接、数据传输和通信协议等相关任务。
- 用户管理:服务器端负责管理玩家的账户、角色和权限等信息。它可以处理用户注册、登录、验证和身份验证等操作。服务器端还可以管理玩家之间的好友关系、排行榜、成就系统等。
- 数据存储和持久化:服务器端负责将游戏数据存储在持久化存储介质中,如数据库或文件系统。它可以存储玩家的进度、成就、物品、排行榜数据等。服务器端还可以处理数据的读取、写入和查询等操作。
- 多人游戏支持:服务器端支持多人游戏模式,允许多个玩家同时参与游戏。它可以处理玩家之间的交互、同步游戏状态、处理多个并发操作等。
- 安全和防作弊:服务器端负责确保游戏的安全性和防止作弊行为。它可以验证客户端请求的合法性,检测和阻止作弊行为,并采取必要的安全措施来保护玩家的数据和隐私。
- 扩展和维护:服务器端需要具备可扩展性和易于维护的特性。它应该能够处理大量玩家的同时在线,支持游戏的更新和扩展,以及进行服务器的监控和维护。
这些只是游戏服务器端可能承担的一些常见任务和功能。具体的服务器端功能取决于游戏的类型、规模和需求。不同的游戏可能有不同的服务器端架构和功能设计。
http/https服务器框架推荐
直接用就行,不会扣分
javalin : https://javalin.io/documentation#getting-started <-有详细的官方教程,也可以参考我的后端项目 https://github.com/xCipHanD/happyMatchServer
简单的javalin程序
- 需要先配置
pom.xml
,在里面加上这一段1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19<dependencies>
<dependency>
<groupId>io.javalin</groupId>
<artifactId>javalin</artifactId>
<version>5.6.3</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>2.0.7</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.30</version>
<scope>compile</scope>
</dependency>
</dependencies> - 创建主类
Main.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38import io.javalin.Javalin;
import io.javalin.http.staticfiles.Location;
import lombok.extern.slf4j.Slf4j;
import java.io.File;
import static io.javalin.apibuilder.ApiBuilder.*;
@Slf4j
public class Main {
public static void main(String[] args) {
Javalin app = Javalin.create(config -> {
//静态资源,可以放置一些文件、图片、音频、视频等静态文件。
config.staticFiles.add(staticFiles -> {
//外部访问路径 如 http://ip:port/res/files/example.file
staticFiles.hostedPath = "/res/files";
//内部文件存储路径(可自定义) 这里写的是运行目录下files文件夹
//如果文件夹不存在,则创建文件夹
String directoryPath = System.getProperty("user.dir") + "/files";
File directory = new File(directoryPath);
if (!directory.exists() && !directory.mkdirs()) {
System.out.println("文件夹创建失败");
System.exit(1);
}
staticFiles.directory = directoryPath;
});
}).start(80);
// 访问默认路径的输出,可以放个主页什么的
app.get("/", ctx -> ctx.result("Hello World!"));
//路由不同路径,这里将 Controller中fromGet()路由到/api下,并且方法为GET;fromPost()路由到/api下,方法为POST。
app.routes(() -> {
path("/api", () -> get(Controller::fromGet));
path("/api", () -> post(Controller::fromPost));
});
}
} - 控制类
Controller.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25import io.javalin.http.Context;
public class Controller {
public static void fromGet(Context ctx) {
ctx.contentType("text/html; charset=utf-8");
String flag,result;
try {
flag = ctx.queryParam("flag");
if (flag == null) {
throw new Exception();//如果flag为空,则抛出异常
} else if (flag.equals("kfccrazythursdayvme50")) {
result = "No Way!";
}else {
result = "Your flag is: " + flag;
}
ctx.status(200);//设置正常的状态码
ctx.result(result);//设置返回内容
} catch (Exception e) {
ctx.status(400);
ctx.result("参数不全");
//如果无法解析参数,则报错
}
}
} - 运行查看效果
- 用浏览器访问服务
序列化
序列化是什么
序列化是将对象转换为字节流或其他可存储或传输的格式的过程。在序列化过程中,对象的状态被转换为字节序列,以便可以在网络上传输或存储到磁盘上。反之,将字节流或其他序列化格式转换回对象的过程称为反序列化。
序列化的主要用途如下:
- 数据持久化:通过序列化,可以将对象保存到磁盘上,以便在程序重新启动时恢复对象的状态。这对于需要长时间保存数据或在不同的系统之间传输数据非常有用。
- 数据传输:在网络通信中,可以使用序列化将对象转换为字节流,然后通过网络传输给其他系统。接收方可以通过反序列化将字节流转换回对象,从而获取原始数据。
- 分布式计算:在分布式系统中,不同的计算节点可能需要交换数据。通过序列化和反序列化,可以在节点之间传输对象,以便进行协作和共享数据。
- 缓存和消息队列:序列化还可以用于将对象存储在缓存中或发送到消息队列中。这样可以提高系统的性能和可扩展性。
总之,序列化是一种将对象转换为字节流或其他可存储或传输的格式的机制,它在数据持久化、数据传输、分布式计算以及缓存和消息队列等方面都有重要的应用。
序列化有哪些
常见的序列化方式有以下几种:
- JSON(JavaScript Object Notation):JSON是一种轻量级的数据交换格式,它以文本形式表示结构化的数据。JSON序列化将对象转换为字符串,可以方便地在不同的系统之间传输和存储数据。主流编程语言都提供了JSON的序列化和反序列化库。
- XML(eXtensible Markup Language):XML是一种标记语言,用于描述和存储数据。XML序列化将对象转换为XML格式的字符串,可以用于数据交换和存储。与JSON相比,XML更为灵活,但也更为冗长。
- Protocol Buffers:Protocol Buffers是Google开发的一种高效的二进制序列化格式。它使用描述文件定义数据结构,然后通过编译器生成相应的代码,用于序列化和反序列化。Protocol Buffers具有高效、紧凑和跨平台的特点,被广泛应用于分布式系统和通信协议中。
- YAML(YAML Ain’t Markup Language):YAML是一种人类可读的数据序列化格式,常用于配置文件和数据交换。YAML序列化将对象转换为YAML格式的字符串,具有易读性和可维护性。
- BSON(Binary JSON):BSON是一种二进制表示的JSON格式,用于在MongoDB数据库中存储和传输数据。BSON序列化将对象转换为二进制格式,具有高效性和可扩展性。
除了上述常见的序列化方式,不同的编程语言还可能提供自己的序列化机制,如Java中的Java Serialization、C#中的BinaryFormatter等。这些方式在特定语言和环境中具有一定的优势和适用性。
为什么要在服务器和客户端的通信中使用序列化
主要是方便数据传输:
1.数据传输:服务器和客户端之间需要传输数据,而数据在网络传输中需要以字节流的形式进行传输。序列化可以将对象转换为字节流,使得数据可以在网络上传输。反序列化则可以将字节流转换回对象,以便在接收方进行处理和使用。
2.跨平台通信:服务器和客户端可能运行在不同的操作系统或编程语言中,它们的数据表示方式可能不同。通过使用一种通用的序列化格式,如JSON、XML或Protocol Buffers,可以将对象转换为中立的格式,使得不同平台之间可以相互理解和交换数据。
如何食用 Json
~
- 先在
pom.xml
中导入fastjson
库1
2
3
4
5
6<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>2.0.32</version>
<scope>compile</scope>
</dependency> Controller.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20public static void fromPost(Context ctx) {
ctx.contentType("text/html; charset=utf-8");
String flag;
try {
flag = ctx.formParam("flag");
if (flag == null) {
throw new Exception();//如果flag为空,则抛出异常
}
//使用fastjson解析flag
JSONObject jsonObject = JSONObject.parseObject(flag);
//返回flag节点数
String result = "Your flag has " + jsonObject.size() + " nodes";
ctx.status(200);
ctx.result(result);
} catch (Exception e) {
ctx.status(400);
ctx.result("参数不全");
//如果无法解析参数,则报错
}
}- 运行服务器,使用
postman
工具进行测试 (postman的安装和使用在此不做展开)
Socket 编程
什么是 Socket
Socket(套接字)是计算机网络中用于实现网络通信的一种机制。它提供了一种编程接口,使得应用程序能够通过网络进行数据的发送和接收。
在网络通信中,Socket 是一种抽象概念,表示网络中的一个端点。一个 Socket 包含了一个 IP 地址和一个端口号,它用于标识网络中的一个特定的应用程序。
Socket 可以用于不同的网络通信协议,如 TCP(传输控制协议)和 UDP(用户数据报协议)。TCP 是一种面向连接的协议,提供可靠的、有序的、基于字节流的通信。UDP 是一种无连接的协议,提供不可靠的、无序的、基于数据报的通信。
在编程中,使用 Socket API 可以创建一个 Socket 对象,通过该对象进行网络通信。通过 Socket,应用程序可以建立连接、发送数据、接收数据和关闭连接。
什么情况用http服务端,什么时候用 Socket
当涉及到用户操作和服务器操作的隔离时,HTTP 服务器可以起到很好的作用。通过使用 HTTP 服务器,用户可以通过发送 HTTP 请求与服务器进行通信,而服务器可以根据请求来执行相应的操作。这种方式可以将用户操作与服务器操作分离开来,使得服务器可以独立处理请求并提供相应的响应。HTTP 服务器可以接收用户请求,执行相应的逻辑,然后返回结果给用户。
此外,HTTP 服务器还可以结合数据存储和游戏逻辑处理。HTTP 服务器可以与数据库或其他数据存储系统进行交互,以读取、写入和更新数据。例如,用户可以通过 HTTP 请求发送游戏数据到服务器,服务器将数据存储在数据库中,并在需要时进行游戏逻辑处理。HTTP 服务器可以提供接口来处理用户请求,并将数据存储和游戏逻辑处理委托给其他组件或服务。
另一方面,Socket 在局域网多人联机等场景中发挥重要作用。Socket 提供了一种实时的、双向的数据传输机制,适用于需要高实时性和低延迟的应用场景,如多人联机游戏。通过 Socket,多个玩家可以建立连接并在局域网中进行实时的游戏通信。Socket 允许玩家之间实时地发送和接收游戏数据,以保持游戏状态的同步和交互。
使用方法
挖个坑,日后补上,这里先引用几篇网上的教程:
基于 Java 简单实现 Socket 通信 https://zhuanlan.zhihu.com/p/441460332
Java 实现简单的 Socket 通信 https://www.cnblogs.com/robothy/p/14211690.html
一些碎碎念
万事开头难,前期写铺垫代码的部分总是枯燥的。但一旦你打好了地基,你会发现,想要实现一个新功能时,可以凭借对于项目框架的熟悉,很快地打出你的组合拳(Ctrl C+V),这也是为什么我建议有能力的同学抛弃掉老师给的demo,自己实现一套框架。
非常感谢你能看到这里,希望这篇文章能帮你减轻一些写project的负担,预祝你在答辩中获得好成绩。o( ̄▽ ̄)ブ