Как Cla sh кланов и другие игры так эффективно ранжируют своих игроков? - PullRequest
1 голос
/ 14 июля 2020

Итак, несколько дней go я работал над довольно стандартной системой ELO. Игрок может атаковать защиту другого игрока, и в зависимости от результата очки перераспределяются.

Сначала все работало довольно хорошо, но в конечном итоге игроки с более низким рейтингом не смогли найти совпадения, потому что система находит количество матчей:

  • Начать с игрока ранга 1
  • Go вниз, пока не найдется игрок, который запросил матч

Очевидно, это привело к необходимости запрашивать данные для 2000 игроков, если ранг участника был близок к 2000.

Итак, теперь игроки с низким рейтингом не могут запросить данные.

Я заметил в других популярных играх, таких как Summoners War и Cla sh of Clans, ваш рейтинг мгновенно отображается, когда ваши очки корректируются, и я не могу себе представить, чтобы они спускались вниз по списку каждого игрока, пока не достигли # 200000.

Я не могу использовать первую пришедшую в голову стратегию (игра в угадывание чисел), которая была бы, если бы было 100 игроков, проверьте точки №50. Если ваши баллы ниже, отметьте # 75, ниже: отметьте # 88 и т. Д. c. Это потому, что я не могу проверить № 50, не проверив также № 2, № 3 и т. Д. c из-за характера OrderedDataStore

Я пытаюсь хранить данные таким образом, чтобы:

  • Может отображаться 50 лучших игроков
  • Алгоритм может быстро найти 4 защиты игроков, близких к вашему рангу
  • Вы можете просмотреть свой собственный ранг

Есть решения?

1 Ответ

0 голосов
/ 14 июля 2020

Вы должны иметь возможность получить 50 лучших игроков таким образом (при условии, что ваш рейтинг-лист называется просто «ранги»:

ranks.GetSortedAsync(false, 50).GetCurrentPage() -- This will just be an array of the top 50 players.

Поиск определенных c игроков рядом с вашим рангом должен быть таким же простым следующее:

local playerRating -- set this to your player's Elo rating
local searchWidth = 5
ranks.GetSortedAsync(false, 100, playerRating - searchWidth, playerRating + searchWidth)
--[[ the above is a DataStorePages of all players within searchWidth Elo points of your player;
     you may want to widen the search if matches are not found, which is why
     searchWidth is a variable instead of a magic number ]]

Получение ранга - действительно самая сложная часть; действительно, я думаю, что решение может на самом деле совпадать с тем, что вы сказали:

local playerRating -- set to player's Elo rating
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() -- have to add the last page too

Из-за дросселирования лучше всего кэшировать первые 50 данных в собственном хранилище данных всякий раз, когда хранилище обновляется.

Вы правы, они, вероятно, не выполняют линейный поиск по всем ряды, но оказывается, что это необходимо здесь.

...