游戏房间管理模块

前言:

需要设计一个房间类,能够实现房间的实例化,房间类主要是对匹配成对的玩家建立一个小范围的关联关系,一个房间中任意用户发生的任何动作,都会被广播给房间中的其他用户。

因为这些类似的房间会有很多,因此需要将这些房间管理起来以便对房间的生命周期进行控制;

因此要实现两个部分:1.房间的设计 2. 房间管理的设置

请求格式

此项目,是依托于Websocket协议来实现的,正文采用的是json格式进行正文数据的格式组;

聊天时的请求格式:

进入游戏房间的请求格式:

房间类实现

管理的数据:

这些数据都是之后要用到的

房间中会产生的动作有那些:

  就两种 1. 聊天  2. 下棋

而且不管是那种动作都是要广播给房间中的其他通用化的,只有这个动作合理

房间的操作

当然,这些都是根据实际情况,总结出的操作,若后续还需要什么,还应该添加;

这些简单来说就是基本框架

对下棋胜利的判断:

五子棋胜负判断方向说明

五星连珠的四个判断方向

1. 横行五星

  • 向右统计:行不变,列++

  • 向左统计:行不变,列--

2. 纵列五星

  • 向上统计:列不变,行--

  • 向下统计:列不变,行++

3. 正斜

  • 右上方向:行--,列++

  • 左下方向:行++,列--

4. 反斜

  • 左上方向:行--,列--

  • 右下方向:行++,列++

房间管理实现

根据 上一篇 服务器流程图可以知道,房间管理需要什么操作,需要什么数据

房间管理

  1. 创建房间(两个玩家对战匹配完成了,为他们创建一个房间,需要传入两个玩家的用户ID

  2. 查找房间(通过房间ID查找房间信息;通过用户ID查找所在房间信息

  3. 销毁房间(根据房间ID销毁房间;房间中所有用户都退出了,销毁房间

需要管理的数据


using room_ptr = std::shared_ptr<room>; 房间信息的空间使用shared_ptr进行管理

  1. 数据管理模块句柄;

  2.  在线用户管理模块句柄;

  3.  房间ID分配计数器;(分配每个房间的ID)

  4.  互斥锁

  5. unorderedmap<room_id, room_ptr> 房间信息管理(建立起房间ID与房间信息的映射关系)

  6. unorderedmap<uid, rid> 房间ID与用户ID的关联关系管理(先通过用户ID找到所在房间ID,再去查找房间信息)

session数据与管理模块

什么是session

在WEB开发中,HTTP协议是⼀种无状态短链接的协议这就导致一个客户端连接到服务器上之后,服务器不知道当前的连接对应的是哪个用户,也不知道客⼾端是否登录成功,这时候为客户端提所有服务是不合理的。

因此,服务器为每个用户浏览器创建一个会话对象(session对象);

注意:一个浏览器独占一个 session对象(默认情况下)。因此,在需要保存用户数据时,服务器程序可以把用户数据写到用户浏览器独占的session中,当用户使用浏览器访问其它程序时,其它程序可以从用户的session中取出该用户的数据,识别该连接对应的用户,并为用户提供服务

session工作原理

为什么要使用session

为什么要使用session,而不是一直使用 cookie来进行用户状态管理呢?

如图所示,如果使用cookie,以登入账号为例子,

先服务器发送 账号 与 密码,然后服务器会响应一个状态,用户就可以有了这个statu状态,接着进行自己想要的操作,图中为 chat 操作;

然而,cookie 的status 状态十分容易被修改,会导致账号安全问题很严重;


但使用cookie和session进行http在短连接通信的情况下进行用户状态管理,就很安全

  • 要注意的是,这个服务器上管理的session都会有过期时间,超过时间了,就会将对应的session删除,每次客户端与服务器的通信都需要延长session的过期时间;

session类实现

session模块用途保存客户端用户状态信息


根据需要的操作,需要的数据

  1. 有自己的标识:ssid

  2. 用户的状态信息。

  3. 用户ID

  4. session相关的定时器(通过是否包含有定时器,确定当前session是否已经添加了定时销毁任务)

websocketpp库中定时器的使用:
其中的定时器基于 boost::asio::steady_timer

session类管理实现

session管理操作

  1. 创建session

  2. 为session设置过期时间

  3. 获取session

  4. 销毁session(过期自动被销毁)


session管理数据


根据需要的操作,需要的数据

  1. ssid的计数器

  2. 互斥锁

  3. 管理器 unordered_map<ssid, session_ptr>

  4. websocket的server的对象——用于添加定时任务

对战玩家匹配管理模块

基础理念

基础思想还是很简单的:

五子棋对战的玩家匹配是根据自己的天梯分数进行匹配的,而服务器中将玩家天梯分数分为三个档 次:

1. ⻘铜:天梯分数⼩于2000分

2. 白银:天梯分数介于2000~3000分之间

3. ⻩⾦:天梯分数⼤于3000分

而实现玩家匹配的思想十分简单,为不同的档次设计各自的匹配队列,当一个队列中的玩家数量大于等于2的时候,则意味着同一档次中,有2个及以上的人要进行实战匹配,则出队队列中的前两个用户,相当于队首2个玩家匹配成功,这时候为其创建房间,并将两个用户信息加入房间中。


基础流程

根据流程就可以知道下面设计:
  1. 设计一个匹配队列——阻塞队列

  2. 匹配管理,因为匹配队列有三个,因此创建三个线程,阻塞等待指定队列中的玩家数量>=2

设计一个阻塞队列类

设计一个阻塞队列:(目的是用于实现玩家匹配队列)

功能:

  1. 入队数据

  2. 出队数据

  3. 移除指定的数据

  4. 线程安全

  5. 获取队列元素个数

  6. 阻塞

  7. 判断队列是否为空


template <class T>
class match_queue {
private:
    std::list<T> _list;
    std::mutex _mutex;
    std::condition_variable _cond;
}

匹配管理

匹配管理类的数据:

  1. 三个不同档次的队列

  2. 三个线程分别对三个队列中的玩家进行匹配

  3. 房间管理模块的句柄

  4. 在线用户管理模块的句柄

  5. 数据管理模块-用户表的句柄


匹配管理类功能/操作:

  1. 添加用户到匹配队列

  2. 从匹配队列移除用户

  3. 线程入口函数判断指定队列是否人数大于2出队两个玩家
    创建房间,将两个玩家添加到房间中向两个玩家发送对战匹配成功的消息

Logo

火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。

更多推荐