当前位置: 首页 > news >正文

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

上期我们完成了游戏大厅的前端部分内容,今天我们实现后端部分内容 

1. 维护在线用户

在用户登录成功后,我们可以维护好用户的websocket会话,把用户表示为在线状态,方便获取到用户的websocket会话

package org.ting.j20250110_gobang.game;import org.springframework.stereotype.Component;
import org.springframework.web.socket.WebSocketSession;import java.util.HashMap;
import java.util.Map;@Component
public class OnlineUserManager {//使用ConcurrentHashMap保证线程安全private Map<Integer, WebSocketSession> onlineUser = new ConcurrentHashMap<>();public void enterGameHall(int userId, WebSocketSession session) {//用户上线onlineUser.put(userId, session);}public void exitGameHall(int userId) {//用户下线onlineUser.remove(userId);}public WebSocketSession getFromHall(int userId) {//获取用户的websocket会话return onlineUser.get(userId);}
}

这里我们借助一个哈希表就可以实现。

2. 实现webSocket相关方法

上期我们定义了webSocket的处理类,但是并没有完成重写的方法,接下来我们借助维护的在线用户具体实现如下方法

在实现这些方法之前,我们还需要按照上期约定好的信息交互形式定义两个实体类,代表请求和响应:

package org.ting.j20250110_gobang.game;public class MatchRequest {private String message;public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}
}
package org.ting.j20250110_gobang.game;public class MatchResponse {private boolean ok;private String errMsg;private String message;public boolean isOk() {return ok;}public void setOk(boolean ok) {this.ok = ok;}public String getErrMsg() {return errMsg;}public void setErrMsg(String errMsg) {this.errMsg = errMsg;}public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}
}

2.1 连接成功

//连接成功后执行@Overridepublic void afterConnectionEstablished(WebSocketSession session) throws Exception {//玩家上线try {//获取登录时储存在session中的用户信息,这里WebSocketSession在注册时通过拦截器获取到了session中的内容User user = (User)session.getAttributes().get("user");if(onlineUser.getFromHall(user.getId()) == null) {onlineUser.enterGameHall(user.getId(), session);System.out.println("用户:" + user.getUsername() + " 已上线");}else{//防止重复登录MatchResponse response = new MatchResponse();response.setOk(false);response.setErrMsg("用户已在别处登录");session.sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));session.close();}}catch (NullPointerException e) {e.printStackTrace();MatchResponse response = new MatchResponse();response.setOk(false);response.setErrMsg("用户未登录");session.sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));}}

2.2 连接断开

    //连接异常时执行@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() + " 已下线");}}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() + " 已下线");}}catch (NullPointerException e) {e.printStackTrace();MatchResponse response = new MatchResponse();response.setOk(false);response.setErrMsg("用户未登录");session.sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));}}

2.3 处理匹配请求

    //接收到请求后执行@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")) {//开始匹配,把用户加入匹配队列//todoresponse.setOk(true);response.setMessage("startMatch");}else if(request.getMessage().equals("stopMatch")) {//取消匹配,从匹配队列中移除用户//todoresponse.setOk(true);response.setMessage("stopMatch");}else{response.setOk(false);response.setErrMsg("非法请求");}}

这里=具体的匹配队列功能我们下期再实现

相关文章:

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

上期我们完成了游戏大厅的前端部分内容&#xff0c;今天我们实现后端部分内容 1. 维护在线用户 在用户登录成功后&#xff0c;我们可以维护好用户的websocket会话&#xff0c;把用户表示为在线状态&#xff0c;方便获取到用户的websocket会话 package org.ting.j20250110_g…...

P8716 [蓝桥杯 2020 省 AB2] 回文日期

1 题目说明 2 题目分析 暴力不会超时&#xff0c;O(n)的时间复杂度&#xff0c; < 1 0 8 <10^8 <108。分析见代码&#xff1a; #include<iostream> #include<string> using namespace std;int m[13]{0,31,28,31,30,31,30,31,31,30,31,30,31};// 判断日期…...

如何在视频中提取关键帧?

在视频处理中&#xff0c;提取关键帧是一项常见的任务。下面将介绍如何基于FFmpeg和Python&#xff0c;结合OpenCV库来实现从视频中提取关键帧的功能。 实现思路 使用FFmpeg获取视频的关键帧时间戳&#xff1a;FFmpeg是一个强大的视频处理工具&#xff0c;可以通过命令行获取…...

為什麼使用不限量動態住宅IP採集數據?

在瞭解“不限量動態住宅IP數據採集”之前&#xff0c;我們需要先搞清楚什麼是“動態住宅IP”。簡單來說&#xff0c;動態IP是一種會定期變化的IP地址&#xff0c;通常由互聯網服務提供商&#xff08;ISP&#xff09;分配給家庭用戶。與固定IP&#xff08;靜態IP&#xff09;不同…...

Go语言中使用viper绑定结构体和yaml文件信息时,标签的使用

在Go中使用Viper将YAML配置绑定到结构体时&#xff0c;主要依赖 mapstructure 标签&#xff08;而非 json 或 yaml 标签&#xff09;实现字段名映射。 --- ### 1. **基础绑定方法** 使用 viper.Unmarshal(&config) 或 viper.UnmarshalKey("key", &subConfi…...

OpenIPC开源FPV之Adaptive-Link安装

OpenIPC开源FPV之Adaptive-Link安装 1. 源由2. 介绍2.1 天空端安装2.2 地面端安装 3. 问题汇总3.1 安装脚本问题3.2 网络安装问题3.3 非SSC30KQ/SSC338Q硬件3.4 代码疑问 4. 总结5. 后续 1. 源由 鉴于飞行过程&#xff0c;发现一些马赛克现象&#xff0c;且60FPS桌面30FPS的录…...

[杂学笔记]OSI七层模型作用、HTTP协议中的各种方法、HTTP的头部字段、TLS握手、指针与引用的使用场景、零拷贝技术

1.OSI七层模型作用 物理层&#xff1a;负责光电信号的传输&#xff0c;以及将光电信号转化为二进制数据数据链路层&#xff1a;主要负责将收到的二进制数据进一步的封装为数据帧报文。同时因为数据在网络中传递的时候&#xff0c;每一个主机都能够收到报文数据&#xff0c;该层…...

RK3568开发笔记-AD7616调试笔记

目录 前言 一、AD7616介绍 高分辨率 高速采样速率 宽模拟输入范围 集成丰富功能 二、原理图连接 三、设备树配置 四、内核驱动配置 五、AD芯片测试 总结 前言 在嵌入式数据采集领域,将模拟信号精准转换为数字信号至关重要。AD7616 作为一款性能卓越的 16 位模数转换器…...

Unity摄像机与灯光相关知识

一、Inspector窗口 Inspector窗口可以查看和编辑对象的属性以及设置 其中包含各种组件&#xff0c;例如用Cube对象来举例 1.Sphere(Mesh)组件&#xff1a; 用来决定对象的网格属性&#xff0c;例如球体网格为Sphere、立方体网格为Cube 2.Mesh Renderer组件&#xff1a; 用来设置…...

AI前端革新金融风控:ScriptEcho助力高效开发

1. 引言&#xff1a;金融风控的挑战与前端效率需求 在当今快速变化的金融环境中&#xff0c;风险评估和反欺诈已成为金融机构运营的核心。金融风控不仅关乎企业的盈利能力&#xff0c;更直接影响着整个金融体系的稳定。一个强大的风控系统需要能够实时监控、分析并预测潜在的风…...

STM32--SPI通信讲解

前言 嘿&#xff0c;小伙伴们&#xff01;今天咱们来聊聊STM32的SPI通信。SPI&#xff08;Serial Peripheral Interface&#xff09;是一种超常用的串行通信协议&#xff0c;特别适合微控制器和各种外设&#xff08;比如传感器、存储器、显示屏&#xff09;之间的通信。如果你…...

CryptoJS库中WordArray对象支持哪些输出格式?除了toString() 方法还有什么方法可以输出吗?WordArray对象的作用是什么?

前言&#xff1a;这里只说js用的CryptoJS库里的相关内容&#xff0c;只用js来进行代码操作和讲解。 这里网上相关的帖子很少&#xff0c;不得已问了很长时间AI 想引用CryptoJS库情况分两种&#xff0c;一种是html引用&#xff0c;另一种是在Nodejs里引用。 一、引用CryptoJS库…...

第六次作业

一.对比 LVS 负载均衡群集的 NAT 模式和 DR 模式&#xff0c;比较其各自的优势 。 LVS-NAT模式的优势 配置简单&#xff1a;NAT模式的配置相对容易&#xff0c;无需复杂的网络设置&#xff0c;适合初学者和小型网络环境。 网络架构灵活&#xff1a;由于使用了NAT技术&#xf…...

八、Spring Boot:RESTful API 应用

创建第一个 Spring Boot RESTful API 应用 在现代 Web 开发中&#xff0c;RESTful API 是一种非常流行的设计风格&#xff0c;它基于 HTTP 协议&#xff0c;提供了简单、灵活的方式来构建网络应用。Spring Boot 作为一款强大的微服务框架&#xff0c;提供了丰富的工具和支持&a…...

Pytorch实现之混合成员GAN训练自己的数据集

简介 简介:提出一种新的MMGAN架构,使用常见生成器分布的混合对每个数据分布进行建模。由于生成器在多个真实数据分布之间共享,高度共享的生成器(通过混合权重反映)捕获分布的公共方面,而非共享的生成器捕获独特方面。 论文题目:MIXED MEMBERSHIP GENERATIVE ADVERSARI…...

微信小程序网络请求与API调用:实现数据交互

在前几篇文章中,我们学习了微信小程序的基础知识、数据绑定、事件处理以及页面导航与路由。这些知识帮助我们构建了具备基本交互功能的小程序。然而,一个完整的应用通常需要与服务器进行数据交互,例如获取用户信息、提交表单数据等。本文将深入探讨微信小程序的网络请求与AP…...

Cramér-Rao界:参数估计精度的“理论底线”

Cramr-Rao界&#xff1a;参数估计精度的“理论底线” 在统计学中&#xff0c;当我们用数据估计一个模型的参数时&#xff0c;总希望估计结果尽可能精确。但精度有没有一个理论上的“底线”呢&#xff1f;答案是有的&#xff0c;这就是Cramr-Rao界&#xff08;Cramr-Rao Lower …...

nv docker image 下载与使用命令备忘

1&#xff0c;系统需求 Requirements for GPU Simulation GPU Architectures Volta, Turing, Ampere, Ada, Hopper NVIDIA GPU with Compute Capability 7.0 CUDA 11.x (Driver 470.57.02), 12.x (Driver 525.60.13) Supported Systems CPU architectures x86_64, ARM…...

C#连接sql server

连接时&#xff0c;出现如下提示&#xff1a; ERROR [IM014] [Microsoft][ODBC 驱动程序管理器] 在指定的 DSN 中&#xff0c;驱动程序和应用程序之间的体系结构不匹配 原因是odbc的驱动和应用程序的架构不一致。我的odbc如下所示&#xff1a; 显示为64位&#xff0c;而c#程序显…...

汽车智能制造企业数字化转型SAP解决方案总结

一、项目实施概述 项目阶段划分&#xff1a; 蓝图设计阶段主数据管理方案各模块蓝图设计方案下一阶段工作计划 关键里程碑&#xff1a; 2022年6月6日&#xff1a;项目启动会2022年12月1日&#xff1a;系统上线 二、总体目标 通过SAP实施&#xff0c;构建研产供销协同、业财一…...

浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)

✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义&#xff08;Task Definition&…...

19c补丁后oracle属主变化,导致不能识别磁盘组

补丁后服务器重启&#xff0c;数据库再次无法启动 ORA01017: invalid username/password; logon denied Oracle 19c 在打上 19.23 或以上补丁版本后&#xff0c;存在与用户组权限相关的问题。具体表现为&#xff0c;Oracle 实例的运行用户&#xff08;oracle&#xff09;和集…...

基于FPGA的PID算法学习———实现PID比例控制算法

基于FPGA的PID算法学习 前言一、PID算法分析二、PID仿真分析1. PID代码2.PI代码3.P代码4.顶层5.测试文件6.仿真波形 总结 前言 学习内容&#xff1a;参考网站&#xff1a; PID算法控制 PID即&#xff1a;Proportional&#xff08;比例&#xff09;、Integral&#xff08;积分&…...

(十)学生端搭建

本次旨在将之前的已完成的部分功能进行拼装到学生端&#xff0c;同时完善学生端的构建。本次工作主要包括&#xff1a; 1.学生端整体界面布局 2.模拟考场与部分个人画像流程的串联 3.整体学生端逻辑 一、学生端 在主界面可以选择自己的用户角色 选择学生则进入学生登录界面…...

cf2117E

原题链接&#xff1a;https://codeforces.com/contest/2117/problem/E 题目背景&#xff1a; 给定两个数组a,b&#xff0c;可以执行多次以下操作&#xff1a;选择 i (1 < i < n - 1)&#xff0c;并设置 或&#xff0c;也可以在执行上述操作前执行一次删除任意 和 。求…...

MySQL用户和授权

开放MySQL白名单 可以通过iptables-save命令确认对应客户端ip是否可以访问MySQL服务&#xff1a; test: # iptables-save | grep 3306 -A mp_srv_whitelist -s 172.16.14.102/32 -p tcp -m tcp --dport 3306 -j ACCEPT -A mp_srv_whitelist -s 172.16.4.16/32 -p tcp -m tcp -…...

大数据学习(132)-HIve数据分析

​​​​&#x1f34b;&#x1f34b;大数据学习&#x1f34b;&#x1f34b; &#x1f525;系列专栏&#xff1a; &#x1f451;哲学语录: 用力所能及&#xff0c;改变世界。 &#x1f496;如果觉得博主的文章还不错的话&#xff0c;请点赞&#x1f44d;收藏⭐️留言&#x1f4…...

项目部署到Linux上时遇到的错误(Redis,MySQL,无法正确连接,地址占用问题)

Redis无法正确连接 在运行jar包时出现了这样的错误 查询得知问题核心在于Redis连接失败&#xff0c;具体原因是客户端发送了密码认证请求&#xff0c;但Redis服务器未设置密码 1.为Redis设置密码&#xff08;匹配客户端配置&#xff09; 步骤&#xff1a; 1&#xff09;.修…...

C/C++ 中附加包含目录、附加库目录与附加依赖项详解

在 C/C 编程的编译和链接过程中&#xff0c;附加包含目录、附加库目录和附加依赖项是三个至关重要的设置&#xff0c;它们相互配合&#xff0c;确保程序能够正确引用外部资源并顺利构建。虽然在学习过程中&#xff0c;这些概念容易让人混淆&#xff0c;但深入理解它们的作用和联…...

宇树科技,改名了!

提到国内具身智能和机器人领域的代表企业&#xff0c;那宇树科技&#xff08;Unitree&#xff09;必须名列其榜。 最近&#xff0c;宇树科技的一项新变动消息在业界引发了不少关注和讨论&#xff0c;即&#xff1a; 宇树向其合作伙伴发布了一封公司名称变更函称&#xff0c;因…...