Skip to content

Commit c62dca0

Browse files
author
hero
committed
添加匹配算法
1 parent 6d86e46 commit c62dca0

File tree

2 files changed

+162
-0
lines changed

2 files changed

+162
-0
lines changed

game/match/match.go

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
package match
2+
3+
import (
4+
"fmt"
5+
"sort"
6+
"strconv"
7+
"sync"
8+
"time"
9+
)
10+
11+
type Match struct {
12+
Uid int
13+
Rating int
14+
StartTime int64 //单位豪秒
15+
}
16+
17+
type MatchPool struct {
18+
allUser *sync.Map
19+
timeout int64 //匹配超时时间 单位豪秒
20+
mu sync.Mutex
21+
num int //需要匹配人数
22+
isWork bool
23+
count int64 //匹配成功次数
24+
}
25+
26+
func NewMatchPool(t int64) *MatchPool {
27+
pool := &MatchPool{
28+
allUser: new(sync.Map),
29+
timeout: t,
30+
}
31+
go pool.run()
32+
return pool
33+
}
34+
func (m *MatchPool) Add(u *Match) {
35+
m.allUser.Store(strconv.Itoa(u.Uid), u)
36+
}
37+
38+
func (m *MatchPool) Remove(id int) {
39+
m.allUser.Delete(strconv.Itoa(id))
40+
}
41+
42+
func (m *MatchPool) run() {
43+
for {
44+
select {
45+
case <-time.After(time.Second * 1):
46+
{
47+
m.match()
48+
}
49+
}
50+
}
51+
}
52+
53+
func (m *MatchPool) match() {
54+
if m.isWork {
55+
return
56+
}
57+
m.mu.Lock()
58+
m.count++
59+
m.isWork = true
60+
defer func() {
61+
m.mu.Unlock()
62+
m.isWork = false
63+
}()
64+
fmt.Println("开始匹配时间", time.Now().UnixNano()/1e6)
65+
//给每个分段都添加分别的队列 (这里可以设置区间)
66+
var ratingMap sync.Map
67+
m.allUser.Range(func(_, value interface{}) bool {
68+
user := value.(*Match)
69+
if time.Now().Unix()-user.StartTime > m.timeout { //该用户匹配时间超时,剔除队列
70+
m.Remove(user.Uid)
71+
} else {
72+
//加入对应的分数队列
73+
valRating, ok := ratingMap.Load(user.Rating)
74+
if ok {
75+
val := valRating.([]Match)
76+
val = append(val, *user)
77+
//进行排序
78+
sort.Slice(val, func(i, j int) bool {
79+
return val[i].StartTime < val[j].StartTime
80+
})
81+
ratingMap.Store(user.Rating, val)
82+
} else {
83+
var userArray []Match
84+
userArray = append(userArray, *user)
85+
ratingMap.Store(user.Rating, userArray)
86+
}
87+
}
88+
return true
89+
})
90+
ratingMap.Range(func(rating, value interface{}) bool {
91+
//找出同一分数段里,等待时间最长的玩家
92+
continueMatch := true
93+
for continueMatch {
94+
userArray := value.([]Match)
95+
if len(userArray) > 0 {
96+
var MatchUser []Match
97+
maxUser := userArray[0]
98+
MatchUser = append(MatchUser, maxUser)
99+
fmt.Println("用户 UID", maxUser.Uid, "是分数", maxUser.Rating, " 上等待最久的玩家", "已经等待时间 ", time.Now().UnixNano()/1e6-maxUser.StartTime, "开始匹配时间 ", time.Now().UnixNano()/1e6)
100+
//先从本分数段上取数据
101+
for _, v := range userArray {
102+
if v.Uid == maxUser.Uid {
103+
continue
104+
}
105+
MatchUser = append(MatchUser, v)
106+
if len(MatchUser) >= m.num {
107+
break
108+
}
109+
}
110+
if len(MatchUser) >= m.num { //人员已经够了,不再判断
111+
continue
112+
}
113+
//再上下每次加1分取 如果加到50都没成功者失败
114+
115+
} else {
116+
continueMatch = false //该分段没有数据
117+
}
118+
}
119+
return true
120+
})
121+
122+
}

game/match/match_test.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package match
2+
3+
import (
4+
"testing"
5+
"time"
6+
)
7+
8+
func Test_NewMatchPool(t *testing.T) {
9+
macth:=NewMatchPool(10000)
10+
macth.Add(&Match{
11+
Uid: 1,
12+
Rating: 1599,
13+
StartTime: time.Now().UnixNano()/1e6,
14+
})
15+
time.Sleep(time.Second/10)
16+
macth.Add(&Match{
17+
Uid: 2,
18+
Rating: 1600,
19+
StartTime: time.Now().UnixNano()/1e6,
20+
})
21+
time.Sleep(time.Second/10)
22+
macth.Add(&Match{
23+
Uid: 3,
24+
Rating: 1599,
25+
StartTime: time.Now().UnixNano()/1e6,
26+
})
27+
time.Sleep(time.Second/10)
28+
macth.Add(&Match{
29+
Uid: 4,
30+
Rating: 1599,
31+
StartTime: time.Now().UnixNano()/1e6,
32+
})
33+
time.Sleep(time.Second/10)
34+
macth.Add(&Match{
35+
Uid: 5,
36+
Rating: 1666,
37+
StartTime: time.Now().UnixNano()/1e6,
38+
})
39+
select {}
40+
}

0 commit comments

Comments
 (0)