当前位置: 首页 > 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;构建研产供销协同、业财一…...

告别安装烦恼:在Anaconda Prompt中一站式部署labelimg的完整指南

1. 为什么选择Anaconda环境安装labelimg 第一次接触计算机视觉项目时&#xff0c;最让人头疼的就是各种依赖包的版本冲突问题。我清楚地记得三年前在一个目标检测项目中&#xff0c;因为PyQt5和Python版本不匹配&#xff0c;整整折腾了两天都没能成功运行labelimg。直到后来发现…...

避坑指南:STM32CUBEMX串口配置常见问题及解决方案(USART/printf重定向)

STM32CubeMX串口开发实战&#xff1a;从原理到调试的完整避坑手册 第一次在STM32CubeMX里配置串口时&#xff0c;我盯着那个115200的波特率数值发呆了十分钟——这个看似简单的数字背后&#xff0c;隐藏着多少新手会踩的坑&#xff1f;从时钟树配置到DMA缓冲区&#xff0c;从p…...

别再死记硬背栈顶指针了!用C语言手把手实现顺序栈(附完整可运行代码)

从零构建C语言顺序栈&#xff1a;破解栈顶指针的终极迷思 初学数据结构时&#xff0c;栈顶指针的初始值设定总是让人困惑——为什么有的教材用top -1&#xff0c;有的却用top 0&#xff1f;这看似简单的数字差异&#xff0c;背后却隐藏着对栈本质理解的深刻分歧。本文将用300…...

龙芯k - 走马观碑组MPU驱动移植扒

先回顾&#xff1a;三次握手&#xff08;建立连接&#xff09;核心流程&#xff08;实际版&#xff09; 为了让挥手流程衔接更顺畅&#xff0c;咱们先快速回顾三次握手的实际核心&#xff0c;避免上下文脱节&#xff1a; 第一步&#xff08;客户端→服务器&#xff09;&#xf…...

Gotestsum自定义命令实战:从基础配置到高级用法

Gotestsum自定义命令实战&#xff1a;从基础配置到高级用法 【免费下载链接】gotestsum go test runner with output optimized for humans, JUnit XML for CI integration, and a summary of the test results. 项目地址: https://gitcode.com/gh_mirrors/go/gotestsum …...

FreeRTOS多任务系统看门狗监控策略与事件标志组实践

1. FreeRTOS多任务系统看门狗监控的必要性 在嵌入式系统开发中&#xff0c;系统稳定性是首要考虑的问题。我遇到过不少系统莫名其妙挂掉的案例&#xff0c;排查起来特别头疼。有一次项目交付前三天&#xff0c;设备在现场运行72小时后突然死机&#xff0c;当时用尽了各种调试手…...

建筑热成像检测数据集 建筑物表面缺陷图像识别 建筑外墙保温缺陷检测、管道热损失识别 建筑物表面温度识别第10357期(代码+数据集+模型+界面)

建筑热成像检测数据集 README数据集核心信息表项目详情类别数量及名称1 类&#xff08;定义缺陷具体类别&#xff09;样本数量200张格式种类YOLO 格式核心应用价值支持建筑热工性能检测模型开发、建筑能耗异常定位算法训练、建筑保温层缺陷识别系统搭建数据集核心要素概述 1. 类…...

[tomcat最新漏洞20260218] CVE-2026-24734 Apache Tomcat and Tomcat Native - OCSP revocation bypass

文章目录 I 主机漏洞 漏洞描述 漏洞修复建议: Upgrade to Apache Tomcat 9.0.115 or later II 漏洞处理 下载最新版本tomcat 9.0.117 安装最新tomcat III 为了同一个tomcat版本安装多个服务 安装服务 验证服务是否启动成功 迁移配置信息 Tomcat7迁移到Tomcat9 需要删除JasperL…...

玻璃的前世今生,了解一下?

玻璃的前世今生,了解一下? 玻璃的前世今生 改革开放40年,我国基础建设飞速发展。一栋栋高耸入云端的摩天大楼,一片片一望无边的居民住宅,房地产行业为我国的GDP画上了浓墨重彩的一笔。毫无疑问,为建筑物穿上漂亮外衣的玻璃行业也是突飞猛进,为我们建筑表皮的安全节能美…...

掌握AI专著撰写技巧,借助工具,轻松打造高质量学术专著

学术专著创作困境与AI工具解决方案 许多学者在撰写学术专著时&#xff0c;常常面临着“有限的精力”与“无限的需求”之间的矛盾。写一本专著通常需要耗费3到5年&#xff0c;甚至更长的时间&#xff0c;而研究者在日常生活中还要兼顾教学、科研和学术交流等多重任务&#xff0…...