1. 程式人生 > >雲原生專案實踐DevOps(GitOps)+K8S+BPF+SRE,從0到1使用Golang開發生產級麻將遊戲伺服器—第8篇

雲原生專案實踐DevOps(GitOps)+K8S+BPF+SRE,從0到1使用Golang開發生產級麻將遊戲伺服器—第8篇

![](https://img2020.cnblogs.com/blog/436453/202103/436453-20210308092102424-64826476.png) ## 麻將牌 (Mahjong tiles) 抽象和編碼實戰 一句話描述麻將遊戲業務: * 三人模式<`三人兩房`>只用 `條` 子和 `筒` 子兩種花色共 `72` 張牌。 * 四人模式<`血戰到底`>使用 `筒`、`條`、`萬` 三種花色共 `108` 張牌。 ### 系列文章 1. [Golang開發生產級麻將遊戲伺服器—第1篇](https://mp.weixin.qq.com/s/Jyq_A1vehrnMwv6AdOtQ1w) 2. [Golang開發生產級麻將遊戲伺服器—第2篇](https://mp.weixin.qq.com/s/jnQaz08fAzQ3J7tZBdil4Q) 3. [Golang開發生產級麻將遊戲伺服器—第3篇](https://mp.weixin.qq.com/s/ktGxVD5VBoSzbBb-vwxxOg) 4. [Golang開發生產級麻將遊戲伺服器—第4篇](https://mp.weixin.qq.com/s/t1E8YleIbgrzkynbBplH3w) 5. [Golang開發生產級麻將遊戲伺服器—第5篇](https://mp.weixin.qq.com/s/FF7Gkoh7EOJBHEQkTp96dQ) 6. [Golang開發生產級麻將遊戲伺服器—第6篇](https://mp.weixin.qq.com/s/mZkzSomUKiOAuqfIeqj5bA) 7. [Golang開發生產級麻將遊戲伺服器—第7篇](https://mp.weixin.qq.com/s/4on-Us-qhLTwIyPizNhWpw) ### 介紹 這將是一個完整的,完全踐行 `DevOps/GitOps` 與 `Kubernetes` 上雲流程的 Golang 遊戲伺服器開發的系列教程。 這個系列教程是對開源專案 `Nanoserver` 的完整拆解,旨在幫助大家快速上手 Golang(遊戲)伺服器後端開發。通過實踐去理解 Golang 開發的精髓 —— `Share memory by communication(通過通訊共享記憶體)`。 同時這個專案可能還會涉及到 `Linux` 效能調優(`BPF` 相關的工具)和系統保障(`SRE`)的相關的工作。 ### Step-By-Step 開發 Mahjong Server * `單體架構`理解 `Mahjong Server` 業務 -> `Nano Distributed Game Server(分散式)` + `微服務` 改造。 * Demo:[go-mahjong-server](https://github.com/Hacker-Linner/go-mahjong-server) ## 牌(Tiles)抽象 ### 定義 Tile struct ![](https://img2020.cnblogs.com/blog/436453/202103/436453-20210308091945961-603250029.png) ```go type Tile struct { Id int Suit int Rank int Index int } ``` * `Id`:`108` 張牌,用 `0~107` 標識每一張牌。 * `Suit`:三種花色,用 `0~2` 標識每一種花色(0:`條`,1:`筒`,2:`萬`)。 * `Rank`:`9` 種點數,用 `1~9` 標識(如:1條,9條,1筒,9筒,1萬,9萬等…)。 * `Index`:索引(條:`1~9`,筒:`11~19`,萬:`21~29`)。 ### 通過一張表來理解 三種花色,每種型別牌的索引(`Index`): | 條(1 ~ 9) | 筒(11 ~ 19) | 萬(21 ~ 29) | | ---- | ---- | ---- | 1 1條 | 11 1筒 | 21 1萬 | 2 2條 | 12 2筒 | 22 2萬 | 3 3條 | 13 3筒 | 23 3萬 | 4 4條 | 14 4筒 | 24 4萬 | 5 5條 | 15 5筒 | 25 5萬 | 6 6條 | 16 6筒 | 26 6萬 | 7 7條 | 17 7筒 | 27 7萬 | 8 8條 | 18 8筒 | 28 8萬 | 9 9條 | 19 9筒 | 29 9萬 | 所有牌(這裡是 `108` 張)的 `ID` 編號: | 條(0 ~ 35) | 筒(36 ~ 71) | 萬(72 ~ 107) | | ---- | ---- | ---- | 0 1條 | 36 1筒 | 72 1萬 | 1 1條 | 37 1筒 | 73 1萬 | 2 1條 | 38 1筒 | 74 1萬 | 3 1條 | 39 1筒 | 75 1萬 | 4 2條 | 40 2筒 | 76 2萬 | 5 2條 | 41 2筒 | 77 2萬 | 6 2條 | 42 2筒 | 78 2萬 | 7 2條 | 43 2筒 | 79 2萬 | 8 3條 | 44 3筒 | 80 3萬 | 9 3條 | 45 3筒 | 81 3萬 | 10 3條 | 46 3筒 | 82 3萬 | 11 3條 | 47 3筒 | 83 3萬 | 12 4條 | 48 4筒 | 84 4萬 | 13 4條 | 49 4筒 | 85 4萬 | 14 4條 | 50 4筒 | 86 4萬 | 15 4條 | 51 4筒 | 87 4萬 | 16 5條 | 52 5筒 | 88 5萬 | 17 5條 | 53 5筒 | 89 5萬 | 18 5條 | 54 5筒 | 90 5萬 | 19 5條 | 55 5筒 | 91 5萬 | 20 6條 | 56 6筒 | 92 6萬 | 21 6條 | 57 6筒 | 93 6萬 | 22 6條 | 58 6筒 | 94 6萬 | 23 6條 | 59 6筒 | 95 6萬 | 24 7條 | 60 7筒 | 96 7萬 | 25 7條 | 61 7筒 | 97 7萬 | 26 7條 | 62 7筒 | 98 7萬 | 27 7條 | 63 7筒 | 99 7萬 | 28 8條 | 64 8筒 | 100 8萬 | 29 8條 | 65 8筒 | 101 8萬 | 30 8條 | 66 8筒 | 102 8萬 | 31 8條 | 67 8筒 | 103 8萬 | 32 9條 | 68 9筒 | 104 9萬 | 33 9條 | 69 9筒 | 105 9萬 | 34 9條 | 70 9筒 | 106 9萬 | 35 9條 | 71 9筒 | 107 9萬 | ## 編碼實戰 ### 通過 ID 獲取 Tile 一個算術問題,沒啥好說的。 * 三種花色,每種有 `9` 類不同的牌,每類又有 `4` 張相同的牌。 `internal/game/tile.go` ```go func TileFromID(id int) *Tile { if id < 0 { panic("illegal tile id") } var ( tmp = id / 4 h = tmp / 9 v = tmp%9 + 1 i = h*10 + v ) return &Tile{Suit: h, Rank: v, Index: i, Id: id} } ``` ### 編寫單元測試函式 `TileFromID` 函式上右擊選擇 `Generate Unit Tests For Function`,我們編寫它的單元測試函式。 ![](https://img2020.cnblogs.com/blog/436453/202103/436453-20210308092003232-1109270936.png) `internal/game/tile_test.go` ```go func TestTileFromID(t *testing.T) { type args struct { id int } tests := []struct { name string args args want *Tile }{ // 定義一堆用例 {"1條", args{id: 0}, &Tile{Suit: 0, Rank: 1, Index: 1, Id: 0}}, {"1條", args{id: 1}, &Tile{Suit: 0, Rank: 1, Index: 1, Id: 1}}, {"1條", args{id: 2}, &Tile{Suit: 0, Rank: 1, Index: 1, Id: 2}}, {"1條", args{id: 3}, &Tile{Suit: 0, Rank: 1, Index: 1, Id: 3}}, {"9條", args{id: 35}, &Tile{Suit: 0, Rank: 9, Index: 9, Id: 35}}, {"1筒", args{id: 36}, &Tile{Suit: 1, Rank: 1, Index: 11, Id: 36}}, {"1筒", args{id: 37}, &Tile{Suit: 1, Rank: 1, Index: 11, Id: 37}}, {"1筒", args{id: 38}, &Tile{Suit: 1, Rank: 1, Index: 11, Id: 38}}, {"1筒", args{id: 39}, &Tile{Suit: 1, Rank: 1, Index: 11, Id: 39}}, {"9筒", args{id: 71}, &Tile{Suit: 1, Rank: 9, Index: 19, Id: 71}}, {"1萬", args{id: 72}, &Tile{Suit: 2, Rank: 1, Index: 21, Id: 72}}, {"1萬", args{id: 73}, &Tile{Suit: 2, Rank: 1, Index: 21, Id: 73}}, {"1萬", args{id: 74}, &Tile{Suit: 2, Rank: 1, Index: 21, Id: 74}}, {"1萬", args{id: 75}, &Tile{Suit: 2, Rank: 1, Index: 21, Id: 75}}, {"9萬", args{id: 107}, &Tile{Suit: 2, Rank: 9, Index: 29, Id: 107}}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if got := TileFromID(tt.args.id); !reflect.DeepEqual(got, tt.want) { t.Errorf("TileFromID() = %v, want %v", got, tt.want) } }) } } ``` 執行: ```sh cd internal/game/mahjong go test -v tile_test.go tile.go mahjong.go ``` ![](https://img2020.cnblogs.com/blog/436453/202103/436453-20210308092019855-272892400.png) ```sh 我是為少 微信:uuhells123 公眾號:黑客下午茶 加我微信(互相學習交流),關注公眾號(獲取更多學習資料~