当前位置:网站首页 > Java基础 > 正文

java基础五子棋



目录

一、约定前后端交互接口的参数

1、房间准备就绪

(1)配置 websocket 连接路径

(2)构造 游戏就绪 的 响应对象

2、“落子” 的请求和响应

(1)“落子” 请求对象

(2)“落子” 响应对象

二、UserMapper

三、处理 websocket 请求、返回的响应(GameAPI)

1、afterConnectionEstablished

(1)通知玩家玩家进入房间(noticeGameReady)

(2)afterConnectionEstablished

1、首先通过Session拿到玩家信息 

2、通过玩家信息拿到游戏房间

3、判断用户是不是多开了

4、设置房间上线

5、把玩家加入对应的房间中

6、处理不存在的操作

2、handleTextMessage

3、handleTransportError

(1)noticeThatUserWin(通知获胜者)

4、afterConnectionClosed

四、Room

1、棋盘

2、自动注入

3、putChess(处理落子请求、构造返回响应)

4、打印棋盘

5、checkWinner(判断输赢)

行:顶点为左边

列:顶点在上边

主对角线:顶点在左上

副对角线:顶点在右上

五、前端代码的逻辑处理

1、处理游戏就绪响应

2、处理落子请求

3、处理落子响应

六、梳理前后端交互流程

七、代码以及线上云服务器的URL


一、约定前后端交互接口的参数

1、房间准备就绪

        当我们从 游戏大厅页面 跳转到 游戏房间页面,这也意味着:游戏大厅页面的 websocket 连接断开了,跳转到 游戏房间页面,要建立一个新的 websocket 连接

        那么也就说明我们之前的 websocket 连接不能用了,这里新的 websocket 连接最好使用新的 URL,不要和游戏大厅的一样,这样能起到 “解耦合” 的效果

        匹配成功后,是服务器主动给客户端发起响应,客户端就不必发起请求了。约定如图:

(1)配置 websocket 连接路径

        前端代码如下:(使用动态路径,更加灵活,方便后部署在服务器上)

 

        后端代码:

 

注意:配置路径的同时,还要拿到之前HttpSession信息,保存在 新的 websocket连接中

(2)构造 游戏就绪 的 响应对象

        后端需要构造一个响应对象,把其转换为JSON格式的文本信息,再发送给客户端,响应对象如下:

 

2、“落子” 的请求和响应

        双方玩家进入游戏房间后,也就是准备就绪后,那就要开始对弈了,所以,我们要针对玩家 “落子”的操作,构造请求和响应

        因为玩家是主动落子,所以要发送给服务器请求;服务器接收到请求后,也需要处理这个请求,构造响应,把最新棋盘布局发给另一个玩家,同时这个响应也要发送给我,让我知道到对方落子了。

java基础五子棋

(1)“落子” 请求对象

 

(2)“落子” 响应对象

 

二、UserMapper

        在游戏结束之后,我们要给玩家结算胜败,那么玩家的天梯积分和游戏场数相对也会改变,说明我们也就要对数据库进行操作了,这里增加两个修改数据库的操作,代码如下:

 

        一个是针对玩家 游戏胜利 后的修改操作,一个是针对玩家 对局失败 后的修改操作。


三、处理 websocket 请求、返回的响应(GameAPI)

        这里主要涉及的方法有四个:

afterConnectionEstablished在建立 websocket 连接时,要做的处理

handleTextMessage接收玩家的 请求,返回对应的 响应

handleTransportError当 websocket 连接出现错误时,要做的处理

afterConnectionClosed当 websocket 连接关闭时,要做的处理

1、afterConnectionEstablished

        建立了新的websocket连接,需要把就绪的玩家加入到房间中,这里就是处理玩家加入房间的逻辑。

(1)通知玩家玩家进入房间(noticeGameReady)

        这里把通知玩家的逻辑单独封装成一个方法,代码如下:

 

        构造对应的响应数据,然后通过 Session 发送给客户端。

(2)afterConnectionEstablished

        建立连接时,并不可以直接把玩家加入房间,需要经过一系列的校验。

1、首先通过Session拿到玩家信息 

        但拿到后还要判断用户是不是null

 
2、通过玩家信息拿到游戏房间

        也要对房间进行校验,如果为空,就要返回对应响应给前端。

 
3、判断用户是不是多开了

        进行对局时,发现该玩家已经在房间里了,说明前面已经有玩家在登录游戏中,我再登录,就视为多开行为;还有是玩家一边在游戏大厅,一边是在游戏房间,也视为多开。

 
4、设置房间上线

        经过上面一系列校验后,没有问题,才能设置玩家在房间中上线。

 
5、把玩家加入对应的房间中

        把玩家加入对应的房间中,这里设置先手的操作是先加入房间的玩家。

        当双方玩家都加入房间后,要对客户端进行通知,构造对应的响应,发送回去。

 
6、处理不存在的操作

        经过上述操作后,把玩家加入房间中,双方玩家都已经就绪了,这时候还有玩家在尝试连接这个房间,就要给客户端提示报错。(理论上这种情况是不存在的)

 

2、handleTextMessage

        在处理请求和构造响应时,根据用户的Session拿到用户信息,然后根据用户再拿到房间,在房间中进行落子的操作。

        其中落子的请求处理和响应构造放在Room里了。

 

3、handleTransportError

        出现异常时,根据Session拿到该用户的信息,再去房间管理器中找该用户的Session,看连接中的Session和房间管理器的Session是不是一样的

        是一样的,说明是我们预期想要在房间管理器中删除的;如果不一样,说明用户可能是多开,防止该用户退出导致前面用户的Session被删除。

        当我掉线后,就要判定对方获胜,通知封装成了一个方法,逻辑操作在该方法中完成。

 

(1)noticeThatUserWin(通知获胜者)

        1、拿到当前玩家,找到该房间

        2、根据房间找到对手

        3、根据房间管理器找到对手的Session

        4、构造响应,告诉客户端,你赢了

        5、更新玩家的分数信息

 

4、afterConnectionClosed

        关闭连接后,处理的逻辑也和连接错误一样。

 

四、Room

1、棋盘

        在Room对象中,我们把落子的下标存在一个二维数组中:

 

2、自动注入

        因为要在落子的请求后,可能会决出胜负,也就是说,处理落子请求时,我们也需要维护roomManager、onlineUserManager,这也意味着我们需要注入这两个对象。还有更新用户信息—— 维护userMapper。

        仔细想想,我们能使用 @Autowired 注入这两个对象吗?如果要使用 @Autowired 注解,也意味着 Room对象 也要被Spring管理起来,但 Room对象 能使用Spring的注解,交给Spring进行管理吗?

        明显是不能的,因为 如果加入对应的注解,那么被Spring管理起来的这个对象,就是单例的了。

        Room对象 能是单例的吗?明显不能吧,因为有很多玩家都在进行游戏时,这时候房间也会有很多,肯定不可能让Room变成单例的。

        那能不能既实现多例,又能注入这两个对象呢?当然也有办法——自动注入

        在Spring启动方法里,添加context:

 

        通过Room的构造方法里,手动注入这两个对象

 

3、putChess(处理落子请求、构造返回响应)

        1、根据请求,拿到当前落子的位置;然后判断当前这个棋子,是玩家1落的棋子、还是玩家2落的棋子。

        2、在控制台上打印出棋盘信息(方便观察)

        3、进行胜负判断,此时也可能是胜负未分(也封装成一个方法了,后面介绍)

        4、给房间的所有客户端都返回响应(根据房间的用户,分别获取不同用户的Session,有了Session,就能对客户端发送消息了;当获取不到用户的Session,说明用户下线了,那就判断对方赢)

        5、当数据发送完毕后,再判断现在是不是胜负已分,如果比赛已经结束了,那也要更新玩家数据,这个房间也没有必要再存在了,要进行销毁。

 

4、打印棋盘

        两层for循环,遍历数组

 

5、checkWinner(判断输赢)

        判断输赢,也就是要检查 是否有 “五子连珠” 的情况。

        五子连珠的情况可能是 行有5个子、列有5个子、主对角线有5个子、副对角线有5个子

        那怎么进行判断呢?其实非常简单,在我们拿到落子的下标后,就固定一个顶点,判断这个顶点所在的这一行往下有没有五子连珠的情况(列、对角线同理),没有就继续下一点,直到该坐标。

        其他情况也同理。

        了解了如何判断,那现在我们就固定一下这个 “顶点” 吧。

行:顶点为左边

列:顶点在上边

主对角线:顶点在左上

副对角线:顶点在右上

        具体实现代码如下:(下面的这种方法可能会有空指针异常,但不要紧,我们进行捕获,再continue进入下一个循环就好了)

 

        如果经过上述逻辑判断,还没返回对应的赢家Id,那么就说明是胜负未分,返回0.


五、前端代码的逻辑处理

1、处理游戏就绪响应

        双方进入房间成功后,就会建立一个房间页面的websocket连接,其代码如下:

 

        接收服务器的响应处理主要在 websocket.message() 上,首先,拿到后端返回来的响应,将其转为 js 对象(原本是JSON文本)。

        判断 resp.ok,如果是false,说明连接异常,跳转到登录页面(可能是还没登录,就直接访问游戏房间页面)。

        然后判断resp.message,如果是 'gameReady',说明该玩家加入房间成功,进行判断先手,设置我方和对方的userId,初始化棋盘,设置显示区域(轮到谁落子了)

        resp.message,如果是 'repeatConnection',说明玩家有多开行为,那就给个提示弹窗,返回到登录页面。

2、处理落子请求

        前端发送的请求有用户Id、落子位置。

        这里有一个点击事件,点击对应位置,就会落子,然后给后端发送一个落子请求,代码如下:

        这里也就会处理:如果不是我落子,你在棋盘上再怎么点也没有用,只有到我落子了,才能继续落子;还有一种是游戏结束了,我也不能继续在这个棋盘上落子了。

 

3、处理落子响应

        返回来的响应,如果 resp.message != "putChess",就说明响应数据有问题。

        然后判断这个响应是不是自己落的子,如果是自己落的子,就绘制一个自己的棋子,如果不是自己落的子,那就说明是对方落的子。

        落子之后,要把对应的位置设为1,说明该位置已经有棋子了,不能再在这个位置落子。

        后端返回的响应有用户Id、落子位置、输赢状态。落子后,就要判断输赢了,如果返回resp.winner 是我的 userId,那就说明我赢了,反之则是对方赢了,然后改变对应的提示信息。还有一种情况,就是0,说明胜负未分。

        胜负分出后,就给页面新增一个按钮,点击后返回到游戏大厅

 

六、梳理前后端交互流程

        双方点击开始匹配按钮。

        进入游戏房间:

        进入房间后,建立 websocket 连接,代码逻辑如:

        我落子后,服务器接收到请求,会给双方都发送响应。

        前后端代码处理逻辑,前后端就依次往下看代码,这里就不展开了


七、代码以及线上云服务器的URL

        URL:http://120.79.61.184:9090/login.html

版权声明


相关文章:

  • java软考基础知识2024-10-28 09:50:05
  • PDF java基础2024-10-28 09:50:05
  • 日本零基础java2024-10-28 09:50:05
  • 黑马15天学完JAVA基础2024-10-28 09:50:05
  • java基础面试题spring2024-10-28 09:50:05
  • serverler是java基础吗2024-10-28 09:50:05
  • java基础类型讲解2024-10-28 09:50:05
  • java语言基础实验一2024-10-28 09:50:05
  • 小白0基础学java2024-10-28 09:50:05
  • 有美工基础学web还是java2024-10-28 09:50:05