项目-五子棋双人对战:游戏房间的管理(5)

2024-06-09 21:04

本文主要是介绍项目-五子棋双人对战:游戏房间的管理(5),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

完整代码见: 邹锦辉个人所有代码: 测试仓库 - Gitee.com

之前我们已经实现了玩家匹配的功能, 我们都知道, 匹配完过后就可以进入游戏房间进行对战了, 所以我们下一步关注的重点就是对于游戏房间的管理.

模块详细讲解

功能需求

通过匹配的方式, 自动给玩家加入到一个游戏房间, 也可以手动创建游戏房间, 当游戏结束后, 玩家退出房间, 游戏房间销毁, 在房间中需要关注的就是对于玩家信息的保存.

但是在服务器上, 显然不止是一个游戏房间, 而游戏房间的数量是根据当前匹配成功的玩家对数实时增长的, 因此我们需要在一个房间管理器中管理多个游戏房间.

这里我们就可以发现, 我们的主要工作就是实现Room和RoomManager.

实现细节

对于Room, 我们就显然需要保存双方用户的信息, 用User对象存储, 同时, 它还应该有唯一的roomid, 这样才能标识出唯一的房间信息.

注: 这里房间id使用UUID, 它表示"世界上唯一的身份标识", 通过调用这个算法, 每次生成的字符串必定不同.

对于RoomManager, 我们需要它记录相应的映射关系(需要根据房间id找到房间对象, 通过玩家id找到对应的游戏房间), 即房间和房间id的映射(也就是房间管理的主体部分rooms, 用哈希表来存储), 和房间id和两个用户的映射(userIdToRoomId, 用哈希表来存储).  然后在房间管理器中需要实现的是房间的添加和删除方法, 以及相关辅助方法.

展示: RoomManager

@Component
public class RoomManager {//房间id和房间的映射关系private ConcurrentHashMap<String, Room> rooms = new ConcurrentHashMap<>();//用户id和房间id的映射关系private ConcurrentHashMap<Integer, String> userIdToRoomId = new ConcurrentHashMap<>();public void add(Room room, int userId1, int userId2) {rooms.put(room.getRoomId(), room);userIdToRoomId.put(userId1, room.getRoomId());userIdToRoomId.put(userId2, room.getRoomId());}public void remove(String roomId, int userId1, int userId2) {rooms.remove(roomId);userIdToRoomId.remove(userId1);userIdToRoomId.remove(userId2);}public Room getRoomByRoomId(String roomId) {return rooms.get(roomId);}public Room getRoomByUserId(int userId) {String roomId = userIdToRoomId.get(userId);if(roomId == null) {//userId -> roomId 映射不存在, 直接返回nullreturn null;}return rooms.get(roomId);}
}

 

然后对于房间创建的时机, 我们之前就说过, 在匹配器中, 匹配成功且无异常状态时, 在匹配器中就创建了一个房间实例, 然后将两个用户放入房间.(然后向用户返回响应).

接下来就是通过websocket对于进入游戏房间的具体处理(主要是用户的上线, 在匹配器中只是将用户实体关联到了房间, 用户想要后续操作, 仍然需要获取到用户会话, 也就是上线):

1.获取到用户的身份信息(从HttpSession中拿到当前用户对象)

2.判定当前用户是否已经进入房间(拿着用户房间管理器进行查询)

3.判定用户的多开(前面实际已经判定过一次了, 这里为了保险起见又进行了一次判定)

4.对于当前用户进行上线操作

5.这时真正地将两个用户放入房间(这时就要对战了, 我们需要设定玩家1和玩家2标识两个用户, 同时还需要指定先手方(后面对战模块就会讲), 当第二个用户就绪时, 通知双方玩家, 游戏开始).

6.如果还有用户进入到房间, 就会报错(理论上是不存在的, 加这部分完全是为了严谨, 因为之前用户加入房间的过程是线程安全的)

在这里websocket对于异常和连接断开的连接, 应对的也就是玩家离开游戏房间的情况, 主要是如果中途有玩家退出, 另一个玩家也不能干等(就直接告诉他赢了), 这里就展示一下对应逻辑:

@Overridepublic void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {User user = (User) session.getAttributes().get("user");if(user == null) {// 此处简单处理, 断开连接时不再给客户端响应了return;}WebSocketSession exitSession = onlineUserManager.getFromGameRoom(user.getUserId());if(session == exitSession) {//加上这个判定, 目的是为了避免在多开的情况下, 第二个用户退出连接动作onlineUserManager.exitGameRoom(user.getUserId());}log.info("当前用户 " + user.getUsername() + " 游戏房间连接异常!");noticeThatUserWin(user);}@Overridepublic void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {User user = (User) session.getAttributes().get("user");if(user == null) {// 此处简单处理, 断开连接时不再给客户端响应了return;}WebSocketSession exitSession = onlineUserManager.getFromGameRoom(user.getUserId());if(session == exitSession) {//加上这个判定, 目的是为了避免在多开的情况下, 第二个用户退出连接动作onlineUserManager.exitGameRoom(user.getUserId());}log.info("当前用户 " + user.getUsername() + " 离开游戏房间!");//通知对手获胜noticeThatUserWin(user);}

 下一节中我们将会讲到对战模块的处理(实际主要是在Room中实现的), 白!

 

这篇关于项目-五子棋双人对战:游戏房间的管理(5)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1046295

相关文章

高效管理你的Linux系统: Debian操作系统常用命令指南

《高效管理你的Linux系统:Debian操作系统常用命令指南》在Debian操作系统中,了解和掌握常用命令对于提高工作效率和系统管理至关重要,本文将详细介绍Debian的常用命令,帮助读者更好地使... Debian是一个流行的linux发行版,它以其稳定性、强大的软件包管理和丰富的社区资源而闻名。在使用

Python 中 requests 与 aiohttp 在实际项目中的选择策略详解

《Python中requests与aiohttp在实际项目中的选择策略详解》本文主要介绍了Python爬虫开发中常用的两个库requests和aiohttp的使用方法及其区别,通过实际项目案... 目录一、requests 库二、aiohttp 库三、requests 和 aiohttp 的比较四、requ

SpringBoot项目启动后自动加载系统配置的多种实现方式

《SpringBoot项目启动后自动加载系统配置的多种实现方式》:本文主要介绍SpringBoot项目启动后自动加载系统配置的多种实现方式,并通过代码示例讲解的非常详细,对大家的学习或工作有一定的... 目录1. 使用 CommandLineRunner实现方式:2. 使用 ApplicationRunne

使用IntelliJ IDEA创建简单的Java Web项目完整步骤

《使用IntelliJIDEA创建简单的JavaWeb项目完整步骤》:本文主要介绍如何使用IntelliJIDEA创建一个简单的JavaWeb项目,实现登录、注册和查看用户列表功能,使用Se... 目录前置准备项目功能实现步骤1. 创建项目2. 配置 Tomcat3. 项目文件结构4. 创建数据库和表5.

Python项目打包部署到服务器的实现

《Python项目打包部署到服务器的实现》本文主要介绍了PyCharm和Ubuntu服务器部署Python项目,包括打包、上传、安装和设置自启动服务的步骤,具有一定的参考价值,感兴趣的可以了解一下... 目录一、准备工作二、项目打包三、部署到服务器四、设置服务自启动一、准备工作开发环境:本文以PyChar

多模块的springboot项目发布指定模块的脚本方式

《多模块的springboot项目发布指定模块的脚本方式》该文章主要介绍了如何在多模块的SpringBoot项目中发布指定模块的脚本,作者原先的脚本会清理并编译所有模块,导致发布时间过长,通过简化脚本... 目录多模块的springboot项目发布指定模块的脚本1、不计成本地全部发布2、指定模块发布总结多模

SpringBoot项目删除Bean或者不加载Bean的问题解决

《SpringBoot项目删除Bean或者不加载Bean的问题解决》文章介绍了在SpringBoot项目中如何使用@ComponentScan注解和自定义过滤器实现不加载某些Bean的方法,本文通过实... 使用@ComponentScan注解中的@ComponentScan.Filter标记不加载。@C

javafx 如何将项目打包为 Windows 的可执行文件exe

《javafx如何将项目打包为Windows的可执行文件exe》文章介绍了三种将JavaFX项目打包为.exe文件的方法:方法1使用jpackage(适用于JDK14及以上版本),方法2使用La... 目录方法 1:使用 jpackage(适用于 JDK 14 及更高版本)方法 2:使用 Launch4j(

Docker集成CI/CD的项目实践

《Docker集成CI/CD的项目实践》本文主要介绍了Docker集成CI/CD的项目实践,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学... 目录一、引言1.1 什么是 CI/CD?1.2 docker 在 CI/CD 中的作用二、Docke

SpringBoot项目引入token设置方式

《SpringBoot项目引入token设置方式》本文详细介绍了JWT(JSONWebToken)的基本概念、结构、应用场景以及工作原理,通过动手实践,展示了如何在SpringBoot项目中实现JWT... 目录一. 先了解熟悉JWT(jsON Web Token)1. JSON Web Token是什么鬼