本次面向对象编程课程设计,是制作一款五子棋联机对战游戏。在上学期做过一款五子棋单机版,其耦合度低,便将其拿来直接制作联机版本。
主要应用的技术:C/S架构 JAVA swing,JAVA socket,mysql+jdbc,多线程等,这里我着重把与网络传输的知识点进行细讲。
服务器-客户机,即Client-Server(C/S)结构。C/S结构通常采取两层结构。服务器负责数据的管理,客户机负责完成与用户的交互任务。
在C/S结构中,应用程序分为两部分:服务器部分和客户机部分。服务器部分是多个用户共享的信息与功能,执行后台服务,如控制共享数据库的操作等;客户机部分为用户所专有,负责执行前台功能,在出错提示、在线帮助等方面都有强大的功能,并且可以在子程序间自由切换。
需要使用到两个类, 来实现Client和Server的连接
1.ServerSocket 搭建服务器
2.Socket 搭建客户端
两方使用socket(套接字 , 通信端点) 进行交流
serversocket用于创建服务器 . 创建完毕后, 会绑定一个端口号. 然后此服务器可以等待客户端连接 . 每连接一个客户端 , 服务器就会得到一个新的Socket对象, 用于跟客户端进行通信 .
Serversocket的创建:
基本的单连接在此就不做叙述,因为服务器需要同时连接多个客户端,因此这里需要将每个连接赋予给单独的线程进行操作,实现多个客户端同时交互数据。
(至于这里线程调用的request方法,在后面服务器端详细叙述)
Socket是两台计算机之间通信的端点 , 是网络驱动提供给应用程序编程的一种接口 一套标准, 一种机制 .
Socket的创建:
服务器端在整个过程中的职责是处理客户端发送过来的数据以及将需要的数据发送给客户端。因此其不需要考虑游戏本身的逻辑,只需要传输数据即可。那么,数据究竟是如何传输的呢?这里就需要用到I/O流了。
什么是IO?
我们的电脑中,硬盘,内存等储存了我们平时使用电脑时所使用的数据,我们可以通过U盘,网络等获得他人的数据或将数据发送给他人。我们把这种数据的传输,称为一种数据的流动(即IO),通过流动的反向,分为输入(Input)和输出(Output),即流向内存时输入,流出内存是输出。
IO的分类:
通过数据的流向,分为输入流和输出流。
通过数据的类型,分为字节流和字符流
I/O流拥有许多子类,在本程序中我们通过使用ObjectOutputStream和ObjectInputStream来进行传输,你要是想问为什么,答案就是他可以直接传输Object类型的数据,即所有类型的数据,(简单粗暴,不是吗)。
使用方法:
首先,通过连接的套接字,获得其输入流和输出流,然后将其转换为OOS和OIS流,这样就可以发送和接收消息了!
可能你还有疑问,这里是获得流了,但没有实现真正的数据传输啊?那我们就拿代码的一部分做例子。
首先,客户端向服务器发送了字符串:log,然后发送了一个数据user,(注意:每次发送数据之后需要刷新管道,否则可能出问题,然后异常处理也不能少)
在服务器端接收了log的信号,服务器得知需要进行log的操作,然后接收到user数据,将其转换为User类型,获得数据(后面的数据库操作一会再说)
这样,数据的交互操作就完成了。现在,开搞游戏。
服务器端负责将客户端发送的数据进行处理并响应,可以把他理解成一个数据中转站,在这里为了实现数据的保存,引入了数据库,保存用户账号密码等信息以及对局信息(功能还有很多地方可以迭代,这里仅实现了重要功能)本程序使用mysql数据库,通过jdbc进行连接。
Mysql应该不用介绍了,简单介绍一下JDBC:
DataBase Connectivity,java数据库连接)是一种用于执行SQL语句的Java API,可以为多 种关系数据库提供统一访问,它由一组用Java语言编写的类和接口组成。JDBC提供了一种基准,据此可 以构建更高级的工具和接口,使数据库开发人员能够编写数据库应用程序
写一个工具类DBUtil,专用于连接数据库:
静态代码块,类加载时加载,通过读取db.properties中的信息,交给德鲁伊连接池。
连接,获得预状态通道,获得参数,修改以及查询。(功能不做详解,不是重点)
提前定义好需要的sql语句,DBS中接收的各种数据和响应不做赘述了,需要知道的是我们是对战游戏,那么服务器需要连接的客户端就至少有两个,前面只是实现了客户端和服务器单独的交互,并没有提到如何使一个客户端获得其他客户端的信息,这里我们创建一个保存用户名以及其输出流的的Map集合,用于存储每个用户的输出流,便于后续多个客户端的数据传输。
在用户创建房间时,将用户的信息存储到sessionMap当中
服务器大概功能就是这样,接下来看用户端。
用户端就比较繁琐了,其包括了五子棋游戏的逻辑以及各窗口的实现以及客户端的连接和数据传输。
首先说五子棋的底层逻辑(Chess,Game,Map):
Map类中将16X16的棋格进行绘制:
Chess类用于绘制棋子以及创建16X16的二维数组保存数据(简单不贴代码了)
Game类将其他们两个结合,并实现了各方法,用于五子棋游戏所需的各逻辑:
Paint方法:绘制棋盘,以及已经下过的棋子(通过反复重绘实现对战)
落子:通过获得棋子的i,j值来判断其在数组中的位置,将其改为对应颜色的数据:(1是黑,2是白,0是空),Judge用于通过true,false改变棋子颜色
判断胜利:
横向:
纵向:
斜上和斜下看源码吧,太长了截不下来。
清空棋盘(认输,一方胜利之后都需要调用):
平局:(地图上有未满则false,全满了没分出胜负则返回true)
User类:用于保存用户信息,实现Serializable接口是用于I/O流传输
Log登录界面以及Hall游戏大厅逻辑简单,不做详细解释了,主要解释以下Room对战界面:
这里分为两种情况:
1(你是房主):
这种情况下,你是第一个进入房间的,这时打开你的监听器(后面再讲),等待对手进入,在创建过程中调用只有一个用户的构造。
2(你是挑战者):
你进入别人的房间,进入时会给对方发送进入房间的消息,然后打开监听器,创建过程中调用两个用户的构造
准备(房间只有一个人的时候不能准备,会有提示)双方都准备后开始游戏:
认输:(发送认输信息,游戏结束,清空棋盘,双方处于未准备状态):
退出(如果你不是房主,则你退出房间,如果你是房主,则解散房间):
客户端的连接工具(MSUtil),用于连接服务器以及进入房间后对操作的监听
连接服务器
监听器:每次进入房间后,创建一个线程用于监听服务器发送来的数据,这也是实现客户端之间数据传输的条件。
退出房间时一定要关闭监听器,给服务器发送关闭监听器的信息
最后,上运行图:登录:
登陆成功:
斜下获胜:
和棋
源码的话我已经放到我的GitHub库里了,有需要的铁子可以从下网址下载,下载记得给兄弟点一个小星星哦。(附:如果不想用数据库的小伙伴可以把存储的数据写到服务器端,写几个集合就行了,都给存到集合里)
网址:https://github.com/Glinkky/FiveChess