zoukankan      html  css  js  c++  java
  • 游戏匹配实现

    设计思路

    客户端向服务器发送匹配请求,服务端接收后将客户端Session放入匹配队列中,匹配完成时通知用户。

    使用观察者设计模式可以实现这个功能。

    代码

    观察者代码:

    Java util 包拥有Observer 接口,这里根据实际应用自定义参数 Map。

    import java.util.Map;
    ​
    public interface Observer {
    ​
      public void update(Map<String, String> map);
    ​
    }
    

      

     

    被观察者接口:

    import java.util.List;
    ​
    public interface Observerable {
    ​
      public void registerObserver(MatchNode o);
    ​
      public void removeObserver(MatchNode o);
    ​
      public void notifyObserver(List<MatchNode> matchNodes);
    ​
    ​
    }

     

    匹配节点:

    每个节点存放用户数据,用于进行匹配和查找。

    import java.util.Map;
    ​
    public class MatchNode implements Observer {
    ​
      private Long userId;
    ​
      private Long sessionId;
    ​
      private Long ruleId;
    ​
    ​
    ​
      public Long getUserId() {
          return userId;
      }
    ​
      public void setUserId(Long userId) {
          this.userId = userId;
      }
    ​
      public Long getSessionId() {
          return sessionId;
      }
    ​
      public void setSessionId(Long sessionId) {
          this.sessionId = sessionId;
      }
    ​
      public Long getRuleId() {
          return ruleId;
      }
    ​
      public void setRuleId(Long ruleId) {
          this.ruleId = ruleId;
      }
    ​
    ​
      @Override
      public void update(Map<String, String> map) {
    ​
      }
    }
    

      

     

    匹配线程

    使用被观察接口 registerObserver 和 registerObserver 可以对匹配队列中的用户进行管理,当匹配成功后,会将两个匹配成功的用户移除匹配集合,并对匹配成功的用户发送通知。

    使用单例模式意味着可以在任意位置获取匹配线程的状态,在程序初始化时启动匹配线程即可。

    用户在匹配成功时,由匹配线程生成一个 groupId 用于标记这对用户,可以通过groupId 在后续功能开发中可以起到查询的作用。

    package common.thread;
    ​
    import cn.hutool.core.util.IdUtil;
    import common.util.RandomTable;
    import lombok.extern.slf4j.Slf4j;
    ​
    import java.util.*;
    import java.util.stream.Collectors;
    ​
    @Slf4j
    public class MatchQueueThread implements Runnable, Observerable {
    ​
      List<MatchNode> matchNodes;
    ​
    ​
      @Override
      public void registerObserver(MatchNode o) {
          matchNodes.add(o);
      }
    ​
      @Override
      public void removeObserver(MatchNode o) {
          if (!matchNodes.isEmpty())
              matchNodes.remove(o);
      }
    ​
      @Override
      public void notifyObserver(List<MatchNode> matchNodes) {
          //从匹配队列中移除
          this.matchNodes.removeAll(matchNodes);
          String groupId = IdUtil.randomUUID();
          Map<String, String> dataMap = new HashMap<>();
          dataMap.put("groupId", groupId);
          dataMap.put("tables", RandomTable.randomTableSerial());
          matchNodes.forEach(matchNode -> {
              matchNode.update(dataMap);
          });
      }
    ​
      //单例
      private static class SingletonClassInstance {
          private static final MatchQueueThread instance = new MatchQueueThread();
      }
    ​
      private MatchQueueThread() {
          matchNodes = new ArrayList<>();
      }
    ​
      public static MatchQueueThread getInstance() {
          return SingletonClassInstance.instance;
      }
    ​
      public int getMatchCount() {
          return matchNodes.size();
      }
    ​
      /**
        * |
        * 匹配逻辑
        */
      @Override
      public void run() {
          Map<Long, List<MatchNode>> result = matchNodes.parallelStream()
                  .collect(Collectors.groupingBy(MatchNode::getRuleId));
          for (Map.Entry<Long, List<MatchNode>> group : result.entrySet()) {
              if (group.getValue().size() > 1) {
                  List<MatchNode> matchNodes = group.getValue().subList(0, 2);
                  notifyObserver(matchNodes);
                  log.info("匹配成功 : " + matchNodes.get(0).getUserId() + " " + matchNodes.get(1).getUserId());
              }
          }
      }
    }
    

      

    以上代码尚未经过实际运行测试。

  • 相关阅读:
    入门OJ 4187【周末舞会】
    入门OJ 1532【排队取款】
    洛谷 P3029 [USACO11NOV]【牛的阵容Cow Lineup】
    洛谷 P1638【逛画展】
    入门OJ 1256【排队】
    PKU 1945【Power Hungry Cows】
    RocketMQ重试机制和消息
    Java操作RocketMQ
    RocketMQ概述
    重定向机制
  • 原文地址:https://www.cnblogs.com/yangchaojie/p/12269595.html
Copyright © 2011-2022 走看看