JAVA面向对象编程课程设计——web版斗地主

一、团队课程设计博客链接

JAVA面向对象编程课程设计——网络版单机斗地主

二、个人负责模块或任务说明

  • 实体类的设计
  • 斗地主规则的实现
  • 人机自动出牌的算法
  • 实现数据库的DAO模式

三、自己的代码提交记录


注:这里只有部分提交记录,详细的提交记录在团队课程设计博客里有

四、自己负责模块或任务详细说明

1、实体类的设计的代码分析

游戏设计需要用到卡片类(Card)正反面,还有牌型(CardType)的设计,以及各种牌的组合,还要设计在游戏中的抢地主、出牌倒计时、出牌和不出牌等等以及需要判断是否能够出牌和人机自动出牌等。
整体的设计需要用户类(User)用于存储用户的账号密码,以及用户信息类(UserInformation)用于存储用户的账号、昵称、积分等等个人信息。

2、斗地主规则的实现的代码分析

既然是一个游戏,那就要有规则,其中最主要的就是,判断所选的牌型是否正确,即是否符合规则。在牌型符合规则时,需要判断是否能够出牌。
在判断所选的牌型是否符合规则的设计中,因为规则中的牌型是固定的,所以设计了一个常量CardType类,这个常量类中包括了符合斗地主规则的所有可选牌型以及不允许出牌的常量。
常量
判断牌型的时候,需要根据所选的牌的数量,以及各个牌型的特征,如:连对的基本特征为,需要连续3对,并且这三对的数值是连续的等等,来判断用户所选的牌是否为规则内的牌型,是的话返回相应的牌型,供后面的算法判断,如果不是则返回c0,服务器就会给客户端相应的反馈,禁止用户出所选的牌。
判断牌型
判断完牌型后,如果返回的不是c0,则需要判断用户是否能够出所选的牌。在这个判断中,首先就需要判断用户是主动出牌还是跟牌,如果为主动出牌,则服务器就会给客户端相应的反馈,同意用户出牌;如果为被动出牌,则需要判断当前用户所选的牌,与前面的用户出的最大的牌进行比较。
当前面出的牌不是炸弹,而用户选的牌型为炸弹时,既可以出牌。当用户选的牌型不为炸弹时,需要判断该用户所选的牌是否与前面用户所出的牌型相符合,若符合,则判断该用户所选的牌是否比前面用户所出的牌大,若符合则允许出牌,否则禁止用户出牌。
判断是否可以出牌

3、人机自动出牌的算法的代码分析

本次课程设计实现的是单人单机游戏,则需要电脑自动判断除用户外的另外两幅牌该如何出。
判断人机如何出牌时,首先先判断人机为主动出牌还是被动出牌,若为主动出牌,则把人机的牌进行拆分,拆分成符合规则的相关牌型,然后按先出单牌,再出对子,在出连对等等的顺序,按序选择该轮人机所要出的牌。
人机主动出牌
如果为被动出牌,则将人机的牌进行拆分,拆分成符合规则的相关牌型,然后通过判断目前所出的最大的牌的牌型,根据该牌型判断目前该人机手中是否拥有符合条件的牌,若有,再判断该人机的下一个出牌人是否为地主,如果是,则选择最大的出,如果不是则选择最小的出。如果没有符合条件的牌,则该人机就不出牌。
人机跟牌

由于两个操作都涉及到对人机牌的拆分,在拆分的过程中,按照炸弹优先,拆分三带,拆分飞机等等的顺序,将人机的手牌拆分成符合规则的各个种类的手牌,防止拆了规则中的大牌,如炸弹等等。

人机拆牌

最后就是,一开始的抢地主环节,当用户抢地主时,则地主就为用户,当用户不抢地主时,需要根据人机当前手牌的权重大小,来判断是那个人机要抢地主。该权重的计算方法为,统计两幅人机手牌中大小王、A以及2的多少来计算,权重大的获得地主牌。
计算人机权重

4、数据存储DAO模式代码分析

DAO(Data Access Object)顾名思义是一个为数据库或其他持久化机制提供了抽象接口的对象,在不暴露底层持久化方案实现细节的前提下提供了各种数据访问操作。
本次课程设计的底层数据存储为数据库,为了以防以后使用文件等其他形式存储数据,为了方便日后修改小量代码,使用了DAO模式设计数据存储。
在本次课程设计的DAO模式的设计中,使用了两个DAO接口类,UserDAO以及UserInformationDAO类,里面分别包括对User以及UserInformation的操作的相关方法。

因为使用了数据库实现数据的存储,所以在数据库的操作类分别实现了上面的两个接口。由于在对数据库的每次操作中,均需要链接数据库以及断开与数据库的链接,所以将链接数据库以及断开与数据的链接的操作拿出来,另外写了一个JDBCUtil工具类。

5、多人同时访问并进行游戏(多线程)的代码分析

本次课程设计要实现的最终目标即为该斗地主游戏可以实现多人同时进行游戏。
则涉及到了多线程,当多人同时向服务器发出请求时,服务器需要判断该请求来自哪位玩家,该玩家所属的牌局当前的状态,并进行相关的计算,给浏览器返回相应的计算结果。
所以,我们写了一个InitServlet,用于当Tomcat服务器启动时,就将一个牌局组对象(CardGames)写入application中,则这牌局组对象就会一直存在,直到Tomcat服务器关闭。
牌局组对象初始化

这个牌局组(CardGames)对象,包括了一个Map类型的牌局组,一个Integer类型的标志(sign),并且包括一个新建牌局的对象,在新建牌局的时候,将标志,以及新建的牌局放入Map中,并且将改标志赋值给相应的用户中的牌局标识,在后期的数据传输中,后台只要从客户端获取该请求的用户,即可通过该用户对应的牌局标识来从application中获取的牌局组的对象中,获得相应的牌局,从而得到正确的结果。为了防止多个用户同时向服务器发送新家牌局的请求,导致出现了错误,所以为创建牌局的方法添加了互斥锁。
牌局组对象的设计

牌局的对象中定义了初始牌对象,地主标识符,对应角色是否出牌标识,当前的出牌,3个玩家的所分到的牌,以及地主牌。
牌局对象的设计

五、课程设计感想

在本次课程设计中,我主要负责的模块为后端的代码。最为难忘的便是在实体类的设计中,使用了public属性,并且最初的设计中,基本没有涉及到对象,导致后期在实现多人同时访问时出现了各种各样的错误,最后只好对已有的代码进行重构,花费了更多的时间,特别是在对牌型判断的公共方法中,进行了大修改。
本次课程设计,实现了网络web版的单人斗地主,无法支持多人同时进行游戏,可以在次基础上进行迭代,进而实现多人游戏。在对人机自动出的牌较为简单,对人机出牌的判断方法较为笨拙,可以进行优化,如添加人工智能算法等使得人机更加的“聪明”。
通过本次课程设计,让我对JAVA的面向对象设计有了更加深刻的理解,平时上课讲的比较基础,再加上有时候可能没有认真听课,PTA上的题目较为简单,未能对面向对象编程有更加深入的了解,虽然花费了大量的时间(将近两周吧),但是收获多多。

posted @ 2019-01-22 11:52  兰翔  阅读(1749)  评论(0编辑  收藏  举报