一、房间类游戏的房间基本属性

房间类游戏在我们的生活中并不陌生,像跑跑卡丁车、劲舞团、欢乐麻将等,都是房间匹配的。

1、UUID 全局唯一

2、房间ID 当前唯一,且供客户端显示

3、房间类型

4、房间名字(可选)

5、创建时间

6、密码 可选

7、加入条件 如需要扣除多少金币,房卡等

8、等等。。。。


二、UUID

UUID的设计决定了整个房间管理的复杂度,通常有几个办法

1、数据库自增

2、某进程拥有唯一分配权,或者多进程按段分配

3、自行构建,如时间,MD5码等。

为了便于查看,在开发中,我选择了当前时间戳+房间ID的方式。

时间为当前UTC毫秒数。 13位字符长度, 而房间ID一般是4-7位。 整个UUID的长度可以控制在20位左右。

这样设计有一个好处,即当我看到UUID的时候,也能立即获得房间ID。调试的时候非常方便。


三、房间ID

房间ID作为一个显示和玩家操作房间的入口,一般在4-7位。不宜过长。而长度决定了当前房间的容量。

4位:9999 即九千九百九十九

5位:99999 即九万九千九百九十九

6位:999999 即九十九万九千九百九十九

7位:9999999 即九百九十九万九千九百九十九

当前房间容量*房间人数 即为最大可容在线人数。 大部分情况而言,6位房间ID是完全能够支撑一个大区的。 像王者荣耀这样的也可以,因为他还要分区分服。 更别说棋牌了,欢乐麻将6位数的房间ID也是完全够的。

房间ID的生成可以采用十分简单的办法。如下伪代码所示:

/**
* 房间ID生成函数
*/
function generateRoomId() {
var roomId = "";
for (var i = 0; i < 6; ++i) {
roomId += Math.floor(Math.random() * 10);
}
return roomId;
}

//创建房间伪代码
let ret = null;
//最多尝试10次 避免死循环
for(let i = 0; i < 10; ++i){
let roomId = generateRoomId();
let uuid = '' + Date.now() + roomId;
let success = createRoom(uuid,roomId,roomConf);
if(success){
ret = {
uuid:uuid
roomId:roomId,
}
break;
}
}
if(ret){
//通知客户端创建成功
}
else{
//通知客户端创建失败
}

在数据库表设计的时候,uuid为主键, id要加UNIQUE索引。这样当插入数据库的时候,若已经有相同的id存在,则会报错。


四、UUID和房间ID的使用

由于房间ID用完后会被释放,所以系统之间的引用最好是采用UUID。

比如,加入房间,解散房间,退出房间,查找房间以及记录用户所在的房间等,都要使用UUID。

举一个简单的例子。玩家A进入了房间666666,玩到一半下线了。房间666666的其他玩家解散了房间。此时,另一个玩家创建了一个新房间,刚好分配到了666666这个房间ID。当玩家A再次上线时,如果数据库里记录的是666666,那么系统就会引导玩家进入这个新创建的房间。然而这个房间并非他原来的房间。

由此可之,会复用的ID,是不能作为数据存储依据的。

这里有一个特殊情况,就是玩家会手工输入房间号。对于这样的情况,只需要特殊处理一下这个请求即可。


代码和生活一样,每一个细节都值得去总结,这样才能一天比一天好。