最近打王者被制裁的有点惨,突发奇想,用代码实现下王者的匹配机制。先声明,我不是什么算法大神,轻喷。
分析:王者匹配机制会让一个人的胜率总是保持在50%左右,即胜率高了,给你匹配坑队友降低胜率,低了给你匹配几个大神带你飞。
围绕这个点,进行设计。大概思路为:设置一个隐藏分,如果你的隐藏分高于当前段位,就给你降低胜率,反正则提升胜率,具体代码实现如下。
玩家模型类
package com.ty.atlantis.base.kingofglorymodel;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
/**
* @author :TianYuan
* @date :Created in 2022/3/25 14:51
* @description:高端玩家模型
* @modified By:
*/
public class HighEndPlayer {
/**
* 排位段位和战力息息相关。
* 此处采用的简易算法是:
* 假设玩家初始段位为钻石50,战力为5000,赢一把mvp后段位为51,战力为5000+130=5130
* 51段位对应的战力为5100。为了修正段位对应的战力,系统会匹配几个坑货降低胜率
*/
//排位段位 假设初始为钻石5/0星。枚举值为50
private int rankLevel = 50;
//战力(隐藏分),默认5000,正常输一把减105,正常赢一把加110。败方MVP不减,赢方Mvp加130
private long flightPower = 5000;
//活跃度,默认80,上限100。玩家连续上线每天+5,一天不上线-2,当连续不上线活跃度掉到70就不再减
private int activity = 80;
//贵族等级
private int vipLevel;
//氪金总额
private BigDecimal amount;
public String getRankLevelMean(int rankLevel){
Map map = new HashMap<>();
map.put(39,"铂金二零星");
map.put(40,"铂金二一星");
map.put(41,"铂金二二星");
map.put(42,"铂金二三星");
map.put(43,"铂金二四星");
map.put(44,"铂金二五星");
map.put(45,"铂金一一星");
map.put(46,"铂金一二星");
map.put(47,"铂金一三星");
map.put(48,"铂金一四星");
map.put(49,"铂金一五星");
map.put(50,"钻石五零星");
map.put(51,"钻石五一星");
map.put(52,"钻石五二星");
map.put(53,"钻石五三星");
map.put(54,"钻石五四星");
map.put(55,"钻石五五星");
map.put(56,"钻石四零星");
map.put(57,"钻石四一星");
map.put(58,"钻石四二星");
map.put(59,"钻石四三星");
map.put(60,"钻石四四星");
map.put(61,"钻石四五星");
map.put(62,"钻石三零星");
map.put(63,"钻石三一星");
map.put(64,"钻石三二星");
map.put(65,"钻石三三星");
map.put(66,"钻石三四星");
map.put(67,"钻石三五星");
map.put(68,"钻石二零星");
map.put(69,"钻石二一星");
map.put(70,"钻石二二星");
map.put(71,"钻石二三星");
map.put(72,"钻石二四星");
map.put(73,"钻石二五星");
map.put(74,"钻石一零星");
map.put(75,"钻石二一星");
map.put(76,"钻石一二星");
map.put(77,"钻石一三星");
map.put(78,"钻石一四星");
map.put(78,"钻石一五星");
return map.get(rankLevel);
}
public int getRankLevel() {
return rankLevel;
}
public void setRankLevel(int rankLevel) {
this.rankLevel = rankLevel;
}
public long getFlightPower() {
return flightPower;
}
public void setFlightPower(long flightPower) {
this.flightPower = flightPower;
}
public int getActivity() {
return activity;
}
public void setActivity(int activity) {
this.activity = activity;
}
public int getVipLevel() {
return vipLevel;
}
public void setVipLevel(int vipLevel) {
this.vipLevel = vipLevel;
}
public BigDecimal getAmount() {
return amount;
}
public void setAmount(BigDecimal amount) {
this.amount = amount;
}
}
最终游戏结果类:
package com.ty.atlantis.base.kingofglorymodel;
/**
* @author :TianYuan
* @date :Created in 2022/3/25 15:35
* @description:当前这把游戏的最后结果
* @modified By:
*/
public class CurrentGameResult {
//当前游戏是否胜利
private boolean victoryFlag = false;
//当前游戏是否为mvp(不区分胜方mvp和败方mvp)
private boolean mvpFlag = false;
public boolean isVictoryFlag() {
return victoryFlag;
}
public void setVictoryFlag(boolean victoryFlag) {
this.victoryFlag = victoryFlag;
}
public boolean isMvpFlag() {
return mvpFlag;
}
public void setMvpFlag(boolean mvpFlag) {
this.mvpFlag = mvpFlag;
}
}
对局模型类:(并没有什么用,在设计的时候考虑的太复杂了,没有对这个类进行实现)
package com.ty.atlantis.base.kingofglorymodel;
/**
* @author :TianYuan
* @date :Created in 2022/3/25 15:17
* @description:对局模型
* @modified By:
*/
public class GameModel {
//蓝色方对局总战力
private long blueFlightPowerCount;
//红色发对局总战力
private long redFlightPowerCount;
//蓝色方胜率
private long blueWinRate;
//蓝色方胜率
private long redWinRate;
public long getBlueFlightPowerCount() {
return blueFlightPowerCount;
}
public void setBlueFlightPowerCount(long blueFlightPowerCount) {
this.blueFlightPowerCount = blueFlightPowerCount;
}
public long getRedFlightPowerCount() {
return redFlightPowerCount;
}
public void setRedFlightPowerCount(long redFlightPowerCount) {
this.redFlightPowerCount = redFlightPowerCount;
}
public long getBlueWinRate() {
return blueWinRate;
}
public void setBlueWinRate(long blueWinRate) {
this.blueWinRate = blueWinRate;
}
public long getRedWinRate() {
return redWinRate;
}
public void setRedWinRate(long redWinRate) {
this.redWinRate = redWinRate;
}
}
启动类:
package com.ty.atlantis.base;
import com.ty.atlantis.base.kingofglorymodel.CurrentGameResult;
import com.ty.atlantis.base.kingofglorymodel.GameModel;
import com.ty.atlantis.base.kingofglorymodel.HighEndPlayer;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import java.util.Random;
/**
* @author :TianYuan
* @date :Created in 2022/1/25 16:27
* @description:测试类基类
* @modified By:
*/
@SpringBootTest
@RunWith(SpringRunner.class)
@WebAppConfiguration
public class BaseTest {
@Before
public void init() {
System.out.println("开始测试-----------------");
}
@After
public void after() {
System.out.println("测试结束-----------------");
}
@Test
public void kingOfGlory(){
//模拟一个高端玩家连续五天,每天十把排位,最后的排位分数
HighEndPlayer highEndPlayer = new HighEndPlayer();
for (int i = 0;i<5;i++){
for (int j = 0;j<10;j++){
// if (i == 0 && j == 0){
// //第一天第一把,让他拿个赢方Mvp,谁叫他是大神呢
// highEndPlayer.setRankLevel(highEndPlayer.getRankLevel()+1);//加一星
// highEndPlayer.setFlightPower(highEndPlayer.getFlightPower() + 150L);//赢方mvp战力+150
// continue;
// }
//判断此时战力和当前段位战力差多少
long diff = highEndPlayer.getFlightPower() - highEndPlayer.getRankLevel() * 100L;
//当前游戏结果
CurrentGameResult currentGameResult = null;
//建立游戏模型
GameModel gameModel = new GameModel();
if (diff > 0){
//当前战力超过当前段位战力,需要给你匹配几个坑货降降温
//这里为了简单,当前战力超过当前段位战力就让他胜率低于50%
if (diff <= 150){
//超过0~150,下把胜率40%;
currentGameResult = genGameResult(40);
}else if (diff > 150 && diff <= 200){
//超过150~200,下把胜率30%;
currentGameResult = genGameResult(30);
}else if (diff > 200 && diff <= 250){
//超过200~250,下把胜率20%;
currentGameResult = genGameResult(20);
}else if (diff > 250 && diff <= 300){
//超过250~300,下把胜率10%;
currentGameResult = genGameResult(10);
}else {
//超过300以上,下把胜率0%;
currentGameResult = genGameResult(0);
}
}else if (diff < 0){
//当前战力低于当前段位战力,需要给你匹配几个大神带飞
if (diff < 0 && diff >=-40){
//低于0~40,下把胜率60%;
currentGameResult = genGameResult(60);
}else if (diff < -40 && diff >= -90){
//低于40~90,下把胜率70%;
currentGameResult = genGameResult(70);
}else if (diff < -90 && diff >= -100){
//低于90~100,下把胜率80%;
currentGameResult = genGameResult(80);
}else if (diff < -100 && diff >= -150){
//低于100~150,下把胜率90%;
currentGameResult = genGameResult(90);
}else {
//低于150以上,下把胜率100%;
currentGameResult = genGameResult(100);
}
}else if (diff == 0){
currentGameResult = genGameResult(50);
}
StringBuilder sb = new StringBuilder();
if (currentGameResult.isVictoryFlag()){
//这把赢了
sb.append("这把赢了");
if (currentGameResult.isMvpFlag()){
//并且是mvp
highEndPlayer.setFlightPower(highEndPlayer.getFlightPower() + 130);
sb.append(",并且Carry了,");
}else {
highEndPlayer.setFlightPower(highEndPlayer.getFlightPower() + 110);
}
highEndPlayer.setRankLevel(highEndPlayer.getRankLevel()+1);//加星
}else {
//这把输了
sb.append("这把跪了");
if (currentGameResult.isMvpFlag()){
//败方mvp
highEndPlayer.setFlightPower(highEndPlayer.getFlightPower() - 105);
sb.append(",他们太坑了带不动,");
}else {
highEndPlayer.setFlightPower(highEndPlayer.getFlightPower() - 105);
}
highEndPlayer.setRankLevel(highEndPlayer.getRankLevel()-1);//减星
}
sb.append("当前段位为:"+highEndPlayer.getRankLevelMean(highEndPlayer.getRankLevel()));
System.out.println(sb.toString());
}
}
System.out.println("最后的段位为:"+highEndPlayer.getRankLevelMean(highEndPlayer.getRankLevel()));
}
public static void main(String[] args) {
BaseTest test = new BaseTest();
for (int i = 0;i<100;i++){
CurrentGameResult result = test.genGameResult(10);
System.out.println(result.isVictoryFlag()+":"+result.isMvpFlag());
}
}
/**
* 此处采用java的Random来实现胜率结果算法实现
* 因为Random生成每个数的概率是相等的(虽然是伪随机数,但是这里不考虑那么复杂)
* 例:想获得50%概率的结果,random.nextInt(2);则生成0和1的概率都是50%。取任意0或者1就可以得到概率结果
* @param probability 可输入的值 0,10,20,30,40,50,60,70,80,90,100
* @return
*/
private CurrentGameResult genGameResult(int probability){
CurrentGameResult currentGameResult = new CurrentGameResult();
Random random = new Random();
int randomInt = random.nextInt(11);
if (probability == 0){//0%概率,这把必输
currentGameResult.setVictoryFlag(false);
}else if (probability == 10){//10%概率
if (randomInt == 0){
currentGameResult.setVictoryFlag(true);
}
}else if (probability == 20){//20%概率
if (randomInt == 0 || randomInt == 1){
currentGameResult.setVictoryFlag(true);
}
}else if (probability == 30){//30%概率
if (randomInt == 0 || randomInt == 1 || randomInt == 2){
currentGameResult.setVictoryFlag(true);
}
}else if (probability == 40){//40%概率
if (randomInt == 0 || randomInt == 1 || randomInt == 2 || randomInt == 3){
currentGameResult.setVictoryFlag(true);
}
}else if (probability == 50){//50%概率
if (randomInt == 0 || randomInt == 1 || randomInt == 2 || randomInt == 3 || randomInt == 4){
currentGameResult.setVictoryFlag(true);
}
}else if (probability == 60){//60%概率
if (randomInt == 0 || randomInt == 1 || randomInt == 2 || randomInt == 3 || randomInt == 4 || randomInt == 5){
currentGameResult.setVictoryFlag(true);
}
}else if (probability == 70){//70%概率
if (randomInt == 0 || randomInt == 1 || randomInt == 2 || randomInt == 3 || randomInt == 4 || randomInt == 5 || randomInt == 6){
currentGameResult.setVictoryFlag(true);
}
}else if (probability == 80){//80%概率
if (randomInt == 0 || randomInt == 1 || randomInt == 2 || randomInt == 3 || randomInt == 4 || randomInt == 5 || randomInt == 6 || randomInt == 7){
currentGameResult.setVictoryFlag(true);
}
}else if (probability == 90){//90%概率
if (randomInt == 0 || randomInt == 1 || randomInt == 2 || randomInt == 3 || randomInt == 4 || randomInt == 5 || randomInt == 6 || randomInt == 7 || randomInt == 8){
currentGameResult.setVictoryFlag(true);
}
}else if (probability == 100){//100%概率
currentGameResult.setVictoryFlag(true);
}
//mvp概率假设为70%,因为他是大神
int otherRandomInt = random.nextInt(10);
if (otherRandomInt == 0 || otherRandomInt == 1 || otherRandomInt == 2 || otherRandomInt == 3 || otherRandomInt == 4 || otherRandomInt == 5 || otherRandomInt == 6){
currentGameResult.setMvpFlag(true);
}
return currentGameResult;
}
}
运行结果:
仅供娱乐。