Clash of Clans和其他游戏是如何有效地排名和匹配他们的玩家的?

所以,几天前,我设计了一个相当标准的ELO系统。一位玩家可以攻击另一位玩家的防御,并根据结果重新分配积分。

起初,它运作得非常好,但最终低排名的玩家无法找到匹配,因为系统查找匹配的方式是:

  • 从排名第一的玩家开始
  • 向下逐个查找,直到找到请求匹配的玩家

显然,如果参与者的排名接近2000,则必须请求2000位玩家的数据。

因此,现在不太可能请求低排名玩家。

我注意到在其他流行的游戏中,如召唤师战争和部落冲突中,每当您的积分调整时,您的排名就会立即显示出来,而我不可能想象他们会一直下去,直到找到第200000名为止。

我无法使用心中最先想到的方法(猜数字游戏),即如果有100个玩家,则检查第50个玩家的积分。如果您的积分较低,则检查第75个积分,如果积分较低:检查第88个积分等等。由于有序数据存储的性质,我无法检查第50个排名而不同时检查第2、第3等。

我正在尝试以这样的方式存储数据:

  • 可以显示前50名玩家
  • 一个算法可以快速找到与您排名接近的4个玩家的防御
  • 您可以查看自己的排名。

有什么解决方案吗?

点赞
用户13691762
用户13691762

你应该可以这样获取前50名玩家(假设你的排行榜列表只叫“ranks”):

ranks.GetSortedAsync(false, 50).GetCurrentPage() -- 这将仅仅是前50名玩家的数组。

找到与你等级相近的特定玩家应该像下面这样容易:

local playerRating -- 将其设置为你玩家的Elo值
local searchWidth = 5
ranks.GetSortedAsync(false, 100, playerRating - searchWidth, playerRating + searchWidth)
--[[上面是一个DataStorePages,其中包含在searchWidth Elo点内的所有玩家;
     如果没有找到匹配,您可能需要扩大搜索范围,这就是为什么
     searchWidth是一个变量而不是一个魔幻数字]]

获取排名确实是最困难的部分;实际上,我认为解决方案可能是类似于您所说的:

local playerRating -- 设置为玩家的Elo值
local playerRank = 0
local allRanks = ranks.GetSortedAsync(false, 100, playerRating)
while not allRanks.IsFinished do
    allRanks.AdvanceToNextPageAsync()
    playerRank = playerRank + #allRanks.GetCurrentPage()
end
playerRank = playerRank + #allRanks.GetCurrentPage() --也必须加上最后一页

由于限流,最好在商店更新时将前50名缓存在自己的数据存储中。

您是正确的,他们可能不会在所有排行中进行线性搜索,但似乎在这里是必要的。

2020-07-14 03:10:51