V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
arsom
V2EX  ›  PHP

用 PHP 实现 1v1 匹配机制,求思路

  •  
  •   arsom · 2017-12-06 19:08:20 +08:00 · 5064 次点击
    这是一个创建于 2570 天前的主题,其中的信息可能已经有所发展或是发生改变。

    语言:php

    框架:workerman

    需求: 用户点击匹配,然后从匹配大厅里选取一名玩家与该用户对战

    请教一下各路大神“匹配大厅”该用什么思路来实现?

    18 条回复    2018-01-23 14:37:40 +08:00
    arsom
        1
    arsom  
    OP
       2017-12-06 19:11:11 +08:00
    google 无果,知乎上有两个问题跟我类似,但是下面没人回答
    ovear
        2
    ovear  
       2017-12-06 19:13:45 +08:00
    最简单可以直接用 Queue
    依赖外部的话,可以用 MySQL
    update battle set player2 = ? where player2 = '' order time desc limit 1
    或者带排序的 NoSQL,实在不行就用 MQ
    rick09
        3
    rick09  
       2017-12-06 19:20:50 +08:00
    没得其它条件的话,从匹配的人中 rand 一个,然后把它从匹配从群中踢出去。
    arsom
        4
    arsom  
    OP
       2017-12-06 19:23:36 +08:00
    @ovear redis 可以嘛
    chairuosen
        5
    chairuosen  
       2017-12-06 19:24:42 +08:00
    没写过,纯想的。
    开始匹配与匹配到结果是异步的。
    一个队列,新来的放队尾。
    定时从队首拿一个人出来遍历队列找到与他相匹配的人抽走。
    如果玩家有 rank 值就不用遍历,排队的人可以维护一个以 rank 分段的小组,从小组里选就行。
    ovear
        6
    ovear  
       2017-12-06 19:29:05 +08:00
    @arsom 可以的
    gouchaoer
        7
    gouchaoer  
       2017-12-06 19:48:20 +08:00 via Android
    workerman 里面你用了集群了么? 2 个人是 2 条 tcp,找个地方存连接不难
    arsom
        8
    arsom  
    OP
       2017-12-06 21:05:23 +08:00
    @gouchaoer 才玩 workerman,打算写个小游戏。走的 websocket 协议,没有用集群
    arsom
        9
    arsom  
    OP
       2017-12-06 21:31:34 +08:00
    @ovear 用队列的话,假如我有 1000 个人在等待匹配,一个一个出队是不是太慢了
    ovear
        10
    ovear  
       2017-12-06 21:44:12 +08:00
    @arsom 这个队列不可能这么大的呀,这个队列一般只可能<2
    逻辑如下

    1)队列为空,加入自身,等待
    2)队列不为空,出队一个,匹配成功
    zhx1991
        11
    zhx1991  
       2017-12-06 22:20:51 +08:00
    这要考虑一个问题是, 如果按照分数匹配

    假设要匹配的人是 5 分, 那么现在有 1 2 3 4 5 6 7 8 9 10 分 10 个人同时参与匹配

    正常的匹配逻辑是 5 分的人可以匹配到 4-6 分的人, 而 4 分的那个人要匹配到 3-5 的人

    单一队列肯定行不通
    guoer
        12
    guoer  
       2017-12-06 22:31:41 +08:00
    redis set 就行了
    arsom
        13
    arsom  
    OP
       2017-12-06 23:29:37 +08:00 via iPhone
    @ovear 假如有 50 个人同时点击匹配,而且这中间有可能会出现取消匹配或者掉线,也能这么做么
    dilu
        14
    dilu  
       2017-12-07 09:02:43 +08:00
    我的思路是这样的,使用 redis 的 list,因为它是双向链表实现的,读取两头特别快。

    当有人点击匹配的时候,根据 id 来判断,单数扔左边,双数扔右边,然后有个定时任务,只要 list 不为空就把两头的取出来匹配。

    具体能不能行楼主可以测试一下,只是个大概思路。
    realpg
        15
    realpg  
       2017-12-07 09:04:48 +08:00   ❤️ 1
    @arsom #13
    N 年前写过一个基于 MYSQL 的简易匹配 点击匹配的 curgame 改成 0 取消的改成 1
    insert into `games` (`time`) values ($time);
    获取 insert_id (主键 game_id)
    update `user` set `curgame` = $game_id where curgame = 0 order by XXX limit 2
    然后直接用 game_id 去检索 是否匹配成功

    然后这个简易逻辑可以外挂一个当前排队人数量级判断 量级较大就一次性匹配多组 循环几次 量级比较小就一次执行的较少
    arsom
        16
    arsom  
    OP
       2017-12-07 09:44:20 +08:00 via iPhone
    @dilu 好的,谢谢
    iningmeng
        17
    iningmeng  
       2018-01-04 17:53:35 +08:00
    把所有登录用户放进 redis,每次用户请求配对的时候,根据匹配规则去 redis 寻找对手,用户退出时从 redis 删除
    364739377
        18
    364739377  
       2018-01-23 14:37:40 +08:00
    @arsom 这个你做好了吗,,怎么做的???能告诉我吗??谢谢
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3977 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 05:17 · PVG 13:17 · LAX 21:17 · JFK 00:17
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.