首页 > 其他 > 详细

游戏匹配实现

时间:2020-02-06 18:46:47      阅读:80      评论:0      收藏:0      [点我收藏+]

设计思路

客户端向服务器发送匹配请求,服务端接收后将客户端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());
          }
      }
  }
}

  

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

游戏匹配实现

原文:https://www.cnblogs.com/yangchaojie/p/12269595.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!