项目实战--网页五子棋(匹配模块)(5)

embedded/2025/2/26 10:22:36/

上期我们实现了websocket后端的大部分代码,这期我们实现具体的匹配逻辑

1. 定义Mather类

我们新建一个Matcher类用来实现匹配逻辑

java">@Component
public class Matcher {//每个匹配队列代表不同的段位,这里约定每一千分为一个段位private ArrayList<Queue<User>> matchQueueList = new ArrayList<>();@Autowiredprivate ObjectMapper objectMapper;@Autowiredprivate OnlineUserManager onlineUserManager;public Matcher() {//暂定三个段位for(int i = 0; i < 3; i++) {matchQueueList.add(new LinkedList<>());}}public void add(User user) {int index = Math.min(user.getScore() / 3, 2);Queue<User> queue = matchQueueList.get(index);//对操作的队列加锁保证线程安全synchronized (queue) {queue.offer(user);queue.notify();}System.out.println("用户 " + user.getUsername() + " 加入了 " + index + "号 队列");}public void remove(User user) {int index = Math.min(user.getScore() / 3, 2);Queue<User> queue = matchQueueList.get(index);synchronized (queue) {queue.remove(user);}System.out.println("把用户 " + user.getUsername() + " 从 " + index + "号 队列中删除");}
}

2.修改websocket后端代码

java">    //接收到请求后执行@Overrideprotected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {User user = (User) session.getAttributes().get("user");MatchRequest request = objectMapper.readValue(message.getPayload(), MatchRequest.class);MatchResponse response = new MatchResponse();if(request.getMessage().equals("startMatch")) {//开始匹配,把用户加入匹配队列matcher.add(user);response.setOk(true);response.setMessage("startMatch");}else if(request.getMessage().equals("stopMatch")) {//取消匹配,从匹配队列中移除用户matcher.remove(user);response.setOk(true);response.setMessage("stopMatch");}else{response.setOk(false);response.setErrMsg("非法请求");}//返回响应session.sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));}

由于存在在匹配中途断开连接的情况,所有我们还要在断开连接代码中增加退出队列的代码进行:

java">    //连接异常时执行@Overridepublic void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {//连接异常断开,玩家下线try {User user = (User)session.getAttributes().get("user");//防止重复登录时删除正常登录的在线信息if(onlineUser.getFromHall(user.getId()).equals(session)) {onlineUser.exitGameHall(user.getId());System.out.println("用户:" + user.getUsername() + " 已下线");}//用户可能还在匹配队列中matcher.remove(user);}catch (NullPointerException e) {e.printStackTrace();MatchResponse response = new MatchResponse();response.setOk(false);response.setErrMsg("用户未登录");session.sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));}}//连接正常断开后执行@Overridepublic void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {//连接正常断开,玩家下线try {User user = (User)session.getAttributes().get("user");//防止重复登录时删除正常登录的在线信息if(onlineUser.getFromHall(user.getId()).equals(session)) {onlineUser.exitGameHall(user.getId());System.out.println("用户:" + user.getUsername() + " 已下线");}//用户可能还在匹配队列中matcher.remove(user);}catch (NullPointerException e) {e.printStackTrace();MatchResponse response = new MatchResponse();response.setOk(false);response.setErrMsg("用户未登录");session.sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));}}

3. 实现匹配功能

3.1 创建线程扫描队列

我们为每个匹配队列创建一个线程,用来实现匹配功能,我们在构造方法中创建线程:

java">    public Matcher() {//暂定三个段位for(int i = 0; i < 3; i++) {matchQueueList.add(new LinkedList<>());}//每个队列创建一个线程扫描完成匹配功能for(Queue<User> q : matchQueueList) {Thread t = new Thread(()->{while(true) {//调用handlerMatch()完成匹配功能handlerMatch(q);}});}}
3.2 实现handlerMatch()方法进行匹配
java">public void handlerMatch(Queue<User> matchQueue) {try {//对操作的队列加锁保证线程安全synchronized (matchQueue) {//1.检测队列中是否有两个元素while(matchQueue.size() < 2) {matchQueue.wait();}//2.从队列中取出两个玩家User user1 = matchQueue.poll();User user2 = matchQueue.poll();//3.获取到两个玩家的会话信息WebSocketSession session1 = onlineUserManager.getFromHall(user1.getId());WebSocketSession session2 = onlineUserManager.getFromHall(user2.getId());//4.todo 把两个玩家放到一个游戏房间中//5.给用户返回匹配成功的响应MatchResponse response = new MatchResponse();response.setOk(true);response.setMessage("success");String json = objectMapper.writeValueAsString(response);session1.sendMessage(new TextMessage(json));session2.sendMessage(new TextMessage(json));}}catch (IOException | InterruptedException e) {e.printStackTrace();}}

游戏房间功能我们下一期再实现。


http://www.ppmy.cn/embedded/167241.html

相关文章

Elasticsearch中的CURL请求详解

在Elasticsearch(简称ES)的日常管理和操作中&#xff0c;CURL命令因其轻量级和高效性而备受青睐。CURL是一个利用URL语法在命令行方式下工作的开源文件传输工具&#xff0c;可以简单实现常见的GET/POST请求&#xff0c;是开发者与ES进行交互的重要桥梁。本文将详细介绍在ES中常…

低延迟,高互动:EasyRTC的全场景实时通信解决方案

在数字化时代&#xff0c;实时通信技术已成为连接人与人、人与设备的重要桥梁。无论是在线教育、远程医疗、智能家居&#xff0c;还是企业协作&#xff0c;高效的实时互动体验都是提升效率和满意度的关键。而 EasyRTC&#xff0c;作为领先的实时通信解决方案&#xff0c;凭借其…

【Python 入门基础】—— 人工智能“超级引擎”,AI界的“瑞士军刀”,

欢迎来到ZyyOvO的博客✨&#xff0c;一个关于探索技术的角落&#xff0c;记录学习的点滴&#x1f4d6;&#xff0c;分享实用的技巧&#x1f6e0;️&#xff0c;偶尔还有一些奇思妙想&#x1f4a1; 本文由ZyyOvO原创✍️&#xff0c;感谢支持❤️&#xff01;请尊重原创&#x1…

计算机网络:从底层原理到前沿应用,解锁数字世界的连接密码

计算机网络&#xff1a;从底层原理到前沿应用&#xff0c;解锁数字世界的连接密码 在信息如洪流般奔涌的时代&#xff0c;计算机网络宛如无形的脉络&#xff0c;贯穿于我们生活的每一个角落。它不仅是数据传输的通道&#xff0c;更是连接全球、驱动创新的核心力量。从日常的网络…

【股票数据API接口43】如何获取股票指历史分时交易数据之Python、Java等多种主流语言实例代码演示通过股票数据接口获取数据

​ 如今&#xff0c;量化分析在股市领域风靡一时&#xff0c;其核心要素在于数据&#xff0c;获取股票数据&#xff0c;是踏上量化分析之路的第一步。你可以选择亲手编写爬虫来抓取&#xff0c;但更便捷的方式&#xff0c;莫过于利用专业的股票数据API接口。自编爬虫虽零成本&a…

Jenkins重启后Maven的Project加载失败

个人博客地址&#xff1a;Jenkins重启后Maven的Project加载失败 | 一张假钞的真实世界 Jenkins重启后发现Maven的项目都没有正常加载。检查Jenkins的启动日志发现以下错误信息&#xff1a; java.io.IOException: Unable to read /home/jenkins/.jenkins/jobs/test-maven/conf…

PDF无限使用,永久免费!

今天我给大家安利一个超好用的PDF处理网站&#xff0c;简直是处理文件的神器&#xff01; 这个网站完全免费&#xff0c;没有任何限制&#xff0c;用起来特别爽&#xff01; 它是一个在线的PDF编辑平台&#xff0c;完全不用担心付费或者注册的问题。 这里没有VIP和普通用户的区…

自定义提交按钮触发avue-form绑定的submit事件

场景 使用avue-form时&#xff0c;提交按钮会绑定至form区域下方&#xff0c;如果想自定义按钮位置&#xff0c;需要通过dialog的footer位置进行编写&#xff0c;例如&#xff1a; <avue-form ref"form" v-model"dataInfo" :option"dataInfoOpti…