測量玩家技能是一個單獨的話題,我不會給出任何想法。使用現有的方案(例如ELO或Microsoft研究公式http://en.wikipedia.org/wiki/TrueSkill或許多其他方案之一),我認爲這是一個很好的起點。
一旦你有了你的魔法數字,你的(和你的球員)喜好就會有很多考慮因素出現。雖然它不是用C++編寫的,但下面你可以找到我的配對系統的迷你原型(100行f#代碼,你可以在http://www.tryfsharp.org/Create上玩,無需下載任何工具)。
我的設計目標是:
- 使其運行速度快(無長迭代爲球隊平衡的改善)鑑於有可能值設爲100000名球員,這在排隊幾百,要,分配給大概50-100場比賽即可開始,變得太科學可能不是一個好主意。但我寧願把它看作是一個實驗性框架,你可以將你的改進/想法放入的功能稱爲「改進團隊」。
- 不要嘗試優化多個新遊戲在特定時間啓動。
- 嘗試讓玩家在自己的技能水平上獲得遊戲體驗,而不需要爲玩家提供絕對的新手和職業玩家。
工作原理:
- 游泳池被玩家等級降序排序。
- 自上而下(最差的球員是糟糕的球員),球隊通過簡單拼接排名前2 N(N =每支球隊的球員數量)進行拼裝。這樣做會導致A隊總是比B隊更好或者同樣強大。
- 使用team a,b隊和池的其餘部分的信息致電ImproveTeams。改進團隊迭代兩隊,計算技能增量,然後根據是否是正數還是負數混合兩隊陣列中相同位置的球員。
在第一場比賽配對之後,直到服務器容量(免費遊戲插槽)耗盡或玩家池爲空時,池中剩餘的玩家也可以應用相同的策略。
缺點:不好的球員有更長的等待時間,因爲他們總是最後處理。簡單的修改可以通過簡單地在上面描述的算法與從上到下工作的雙重解決方案之間交替進行改進。
type Rating = uint32
type RatingDiff = int32
type Player = { name : string; rating : Rating }
// tuple of: Candidate player in team a, Canditate players in team b, Remainder of pool
type WorkingSet = Player array * Player array * Player array
let pool : Player array =
[| { name = "Hugo"; rating = 1100u }
{ name = "Paul"; rating = 800u }
{ name = "Egon"; rating = 1800u }
{ name = "John"; rating = 1300u }
{ name = "Rob"; rating = 400u }
{ name = "Matt"; rating = 1254u }
{ name = "Bruce"; rating = 2400u }
{ name = "Chuck"; rating = 2286u }
{ name = "Chuck1"; rating = 2186u }
{ name = "Chuck2"; rating = 2860u }
{ name = "Chuck3"; rating = 1286u }
{ name = "Chuck4"; rating = 786u }
|]
let SortByRating (pool : Player array) : Player array =
pool
|> Array.sortWith
(fun (p1 : Player) (p2 : Player) ->
match (p1.rating,p2.rating) with
| (r1,r2) when r1 > r2 -> -1
| (r1,r2) when r1 < r2 -> 1
| _ -> 0
)
let evens n = 2 * n
let odds n = 2 * n + 1
// Note: Since the input is sorted by player level, obviously team A is always stronger or equal in strength to team B
let Split (n : int) (a : Player array) : WorkingSet =
let teamA : Player array = [| for i in 0 .. (n-1) -> a.[evens i] |]
let teamB : Player array = [| for i in 0 .. (n-1) -> a.[odds i] |]
let remainder = Array.sub a (2*n) ((Array.length a) - 2 * n)
(teamA, teamB, remainder)
// This is the function where teams get improved - can be as well a recursive function.
// Anyone is invited to provide alternate, better implementations!
let ImproveTeams (ws : WorkingSet) : WorkingSet =
let a,b,r = ws
let R2RD (r : Rating) : RatingDiff =
let r1 : RatingDiff = int32 r
r1
let UpdateScore (score : RatingDiff) (pa : Player) (pb : Player) : RatingDiff =
score + (R2RD pa.rating) - (R2RD pb.rating)
let improved : RatingDiff * Player array * Player array =
Array.fold2
(fun s pa pb ->
let score,teamA, teamB = s
let betterPlayer p1 p2 =
match (p1.rating,p2.rating) with
| (r1,r2) when r1 >= r2 -> p1
| _ -> p2
let worsePlayer p1 p2 =
match (p1.rating,p2.rating) with
| (r1,r2) when r1 >= r2 -> p2
| _ -> p1
let bp = betterPlayer pa pb
let wp = worsePlayer pa pb
match score with
| x when x > 0 -> (UpdateScore x wp bp, Array.append teamA [| wp |], Array.append teamB [| bp |])
| _ -> (UpdateScore score bp wp, Array.append teamA [| bp |], Array.append teamB [| wp |])
) (0, [||], [||]) a b
let ns,nta,ntb = improved
(nta, ntb,r)
let rec CreateTeams (maxPlayersPerTeam : int) (players : Player array) : WorkingSet =
let sortedPool = SortByRating players
match (Array.length sortedPool) with
| c when c >= (maxPlayersPerTeam * 2) ->
Split maxPlayersPerTeam sortedPool
|> ImproveTeams
| 0 -> ([||], [||], [||])
| _ -> CreateTeams (maxPlayersPerTeam-1) players
let ShowResult (result : WorkingSet) : unit =
let ShowPlayer p =
printf "%s - %d" p.name p.rating
let a,b,r = result
let Score (pl : Player array) : Rating =
Array.fold (fun s p -> s + p.rating) 0u pl
printfn "Team A\t\t\t| Team B"
Array.iter2
(fun pa pb ->
ShowPlayer pa
printf "\t\t\t| "
ShowPlayer pb
printfn ""
) a b
let sa = Score a
let sb = Score b
printfn "Score Team A: %d\t\t\t| Score Team B: %d" sa sb
printfn "Players still in pool: "
Array.iter
(fun p ->
ShowPlayer p
printfn ""
) r
CreateTeams 4 pool |> ShowResult
聽起來像加權隊列調度。 你將需要定義「或多或少的整體」,最小二乘法,逆和逆,eliptical,什麼? – starbolin
等待時間是到達率,遊戲數量,遊戲長度和玩家評分分佈的函數。 – starbolin