├── src └── algorithm │ ├── card_test.go │ ├── ai.go │ ├── weight.go │ ├── card.go │ ├── cards_test.go │ ├── analyse_cards_test.go │ ├── cards.go │ ├── constan.go │ ├── assemble_test.go │ ├── sort_card_test.go │ ├── sort_card.go │ ├── analyse_cards.go │ ├── ai_test.go │ ├── follow.go │ ├── assemble.go │ ├── prompt.go │ ├── prompt_test.go │ └── follow_test.go ├── README.md └── LICENSE /src/algorithm/card_test.go: -------------------------------------------------------------------------------- 1 | package algorithm 2 | 3 | import ( 4 | "testing" 5 | "github.com/golang/glog" 6 | ) 7 | 8 | func TestCard_GetValue(t *testing.T) { 9 | //hand:=[]byte{0x01,0x11,0x21,0x31,} 10 | for i,v:=range CARDS { 11 | 12 | glog.Errorf("i is %v,before is %v",i,v) 13 | a:=GetValue(v) 14 | glog.Errorf("i is %v,after is %v,card is %v",i,a,v) 15 | } 16 | } 17 | 18 | 19 | func TestCard_Legal(t *testing.T) { 20 | 21 | } 22 | 23 | func TestCard_GetSuits(t *testing.T) { 24 | 25 | } -------------------------------------------------------------------------------- /src/algorithm/ai.go: -------------------------------------------------------------------------------- 1 | package algorithm 2 | 3 | // 搜索当前手牌最优组合 4 | 5 | func AnalyseWeightMax(anList *[]AnalyseCards, cards AnalyseCards) int { 6 | array := cards.GetGroup() 7 | if len(array) == 0 { 8 | return 0 9 | } 10 | 11 | for _, v := range array { 12 | t := cards.Sub(v) 13 | // 提前判断,一手牌能出完的时候 14 | if t.Len() == 0 { 15 | *anList = append(*anList, v) 16 | return v.Weight() 17 | } 18 | } 19 | 20 | v := SearchMaxWeight(array)// 拿出当前权 21 | t := cards.Sub(v) 22 | tweight := v.Weight() + AnalyseWeightMax(anList, t) 23 | *anList = append(*anList, v) 24 | return tweight 25 | } 26 | 27 | -------------------------------------------------------------------------------- /src/algorithm/weight.go: -------------------------------------------------------------------------------- 1 | package algorithm 2 | 3 | func (this *AnalyseCards) Weight() int { 4 | value := int(this.GetValue()) 5 | length := this.Len() 6 | w := int(length) - 17 7 | 8 | var nValue = 0 9 | switch this.GetKind() { 10 | case DAN_TIAO: // 飞机带单 11 | nValue = value - 10 12 | case DUI_ZI: //对牌类型 (-7~7) 13 | nValue = value - 10 14 | case SAN_DAI_YI: //三带一单 (-7~7) 15 | nValue = value - 10 16 | case SAN_DAI_YI_DUI: //三带一对 (-7~7) 17 | nValue = value - 10 18 | case SAN_TIAO: //三条类型(-7~7) 19 | nValue = value - 10 20 | case DAN_SHUN_ZI: //单连类型(-6~6) 21 | nValue = value - 10 + 1 22 | case LIAN_DUI: //对连类型(-6~6) 23 | nValue = value - 10 + 1 24 | case SAN_SHUN_ZI: //三顺(0~6) 25 | nValue = (value - 3 + 1) / 2 26 | case FEI_JI_DAI_DAN: //飞机带单(0~6) 27 | nValue = (value - 3 + 1) / 2 28 | case FEI_JI_DAI_DUI: //飞机带对(0~6) 29 | nValue = (value - 3 + 1) / 2 30 | case SI_DAI_DAN: //四带两单(0~6) 31 | nValue = (value - 3 ) / 2 32 | case SI_DAI_DUI: //四带两对(0~6) 33 | nValue = (value - 3 ) / 2 34 | case ZHA_DAN: //炸弹类型(7~19) 35 | nValue = value - 3 + 7 36 | case WANG_ZHA: //王炸类型 37 | nValue = 20 38 | } 39 | return nValue - 20 + w 40 | } 41 | -------------------------------------------------------------------------------- /src/algorithm/card.go: -------------------------------------------------------------------------------- 1 | package algorithm 2 | 3 | import ( 4 | "utils" 5 | ) 6 | 7 | // 验证给定的牌是否是有效的牌值 8 | func Legal(card byte) bool { 9 | if card == 0xEF || card == 0xFF { 10 | return true 11 | } 12 | if card>>4 > 4 || card>>4 < 0 { 13 | return false 14 | } 15 | 16 | if card&0xF > 0x0E || card&0xF < 0x02 { 17 | return false 18 | } 19 | return true 20 | } 21 | 22 | type Card byte 23 | 24 | // 获取牌的花色 25 | func GetSuits(card byte) int { 26 | return int(card >> 4) 27 | } 28 | 29 | // 获取牌的点数大小 30 | func GetValue(card byte) byte { 31 | if card&0xF == 0x2 { 32 | return TWO 33 | } else if card == 0xEF { 34 | return XIAO_WANG 35 | } else if card == 0xFF { 36 | return DA_WANG 37 | } 38 | return card & 0xF 39 | } 40 | 41 | //拷贝一份完整牌 42 | func Copy(c []byte) []byte { 43 | cards := make([]byte, len(c)) 44 | copy(cards, c) 45 | return cards 46 | } 47 | 48 | // 指定的手牌里是否包括指定的牌型 49 | func VerifyCards(source, target []byte) bool { 50 | for _, tv := range target { 51 | b := false 52 | for _, sv := range source { 53 | if tv == sv { 54 | b = true 55 | break 56 | } 57 | } 58 | if !b { 59 | return false 60 | } 61 | } 62 | return true 63 | } 64 | 65 | //洗牌 66 | func Shuffle() []byte { 67 | d := Copy(CARDS) 68 | for n := 0; n < 3; n++ { 69 | for i := range d { 70 | j := utils.RandInt32N(int32(len(d))) 71 | d[i], d[j] = d[j], d[i] 72 | } 73 | } 74 | return d 75 | } 76 | -------------------------------------------------------------------------------- /src/algorithm/cards_test.go: -------------------------------------------------------------------------------- 1 | package algorithm 2 | 3 | import ( 4 | "testing" 5 | "github.com/golang/glog" 6 | ) 7 | 8 | 9 | // 拷贝测试 10 | func TestCopy(t *testing.T) { 11 | hand:=[]byte{0x02,0x03,0x04,0x05} 12 | a:=Copy(hand) 13 | glog.Errorf("a is %v,addressA is %v,addresshand is %v,addressA content is %v,addressHand is %v", 14 | a,&a[0],&hand[0],&a,&hand) 15 | } 16 | 17 | func TestLegal(t *testing.T) { 18 | //for _, v := range CARDS { 19 | //t.Logf("%v %#x", Legal(v), v) 20 | //} 21 | } 22 | 23 | 24 | func TestValue(t *testing.T) { 25 | //for _, v := range CARDS { 26 | //t.Logf(" %#x %v ", v, GetValue(v)) 27 | //} 28 | } 29 | 30 | func TestAnalyseCardArray(t *testing.T) { 31 | a := Cards{} 32 | //a.AnalyseUnSort( []byte{0x05, 0x15, 0x25,0x06, 0x16, 0x26, 0x27,0x37,0x07, 0x18, 0x28,0x08, 0x38, 0x2D, 0x2D}) 33 | 34 | //t.Log(len(a.Cards)) 35 | 36 | handcards := []byte{0xEF, 0xFF, 0x0a, 0x1a, 0x2a, 0x3a, 0x9, 0x19, 0x29} 37 | //discards := []byte{0x04} 38 | //a.AnalyseUnSort([]byte{0xEF,0xFF,0x02, 0x12, 0x03, 0x13, 0x23, 0x04, 0x14, 0x24, 0x05, 0x15, 0x25, 0x26, 0x36, 0x27, 0x37}) 39 | a.AnalyseUnSort(handcards) 40 | 41 | //for k,v:=range a.analyseCards{ 42 | // t.Log(k,v) 43 | //} 44 | //// 45 | t.Log(a.analyseCards, "====") 46 | for i := uint8(0); i < 21; i++ { 47 | //t.Log(i, a.Get(i)) 48 | } 49 | 50 | //t.Log(a.Get(232)) 51 | } 52 | 53 | func TestInitArray(t *testing.T) { 54 | 55 | //a.InitCardArray() 56 | 57 | } 58 | 59 | func TestShuffle(t *testing.T) { 60 | t.Logf("洗牌: %#x", Shuffle()) 61 | } 62 | 63 | 64 | func TestDEAL(t *testing.T) { 65 | for i:=0;i<5;{ 66 | glog.Errorf("第 %v 次:\n",i) 67 | a, b, c, d := Deal() 68 | glog.Errorf("发牌 %#v,%#v,%#v %#v", a, b, c, d) 69 | glog.Errorf("发牌 %v,%v,%v %v", len(a) == 17, len(b) == 17, len(c) == 17, len(d) == 3) 70 | i++ 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/algorithm/analyse_cards_test.go: -------------------------------------------------------------------------------- 1 | package algorithm 2 | 3 | import "testing" 4 | 5 | func TestAnalyseCards_ColorRecover(t *testing.T) { 6 | var cards AnalyseCards = 0 7 | 8 | //handcards:=[]byte{0xEF, 0xFF, 0x0a, 0x1a, 0x2a, 0x3a, 0x9, 0x19, 0x29, 0x39} 9 | //cards.Set([]byte{0xEF, 0xFF,0x9, 0x19, 0x39, 0x29}) 10 | 11 | handcards := []byte{0xEF, 0xFF, 0x02, 0x12, 0x22, 0x32, 0x9, 0x19, 0x29} 12 | cards.Set([]byte{0xEF, 0xFF}) 13 | 14 | for i := THREE; i <= 17; i++ { 15 | t.Logf("%v %v ", i, cards.Get(i)) 16 | } 17 | 18 | t.Logf("%#v ", cards.ColorRecover(handcards)) 19 | } 20 | 21 | func TestAnalyseCards_AnalyseCards(t *testing.T) { 22 | a := Cards{} 23 | //a.AnalyseUnSort( []byte{0x05, 0x15, 0x25,0x06, 0x16, 0x26, 0x27,0x37,0x07, 0x18, 0x28,0x08, 0x38, 0x2D, 0x2D}) 24 | 25 | //t.Log(len(a.Cards)) 26 | 27 | //handcards := []byte{0xEF, 0xFF, 0x0a, 0x1a, 0x2a, 0x3a, 0x9, 0x19, 0x29} 28 | handcards := []byte{0xEF, 0xFF, 0x9, 0x19, 0x39, 0x29} 29 | //discards := []byte{0x04} 30 | //a.AnalyseUnSort([]byte{0xEF,0xFF,0x02, 0x12, 0x03, 0x13, 0x23, 0x04, 0x14, 0x24, 0x05, 0x15, 0x25, 0x26, 0x36, 0x27, 0x37}) 31 | a.AnalyseUnSort(handcards) 32 | 33 | //for k,v:=range a.analyseCards{ 34 | // t.Log(k,v) 35 | //} 36 | //// 37 | t.Log(a.analyseCards, "====") 38 | for i := uint8(0); i <= 17; i++ { 39 | //t.Log(i, a.Get(i)) 40 | } 41 | 42 | var cards AnalyseCards = 0 43 | 44 | //handcards:=[]byte{0xEF, 0xFF, 0x0a, 0x1a, 0x2a, 0x3a, 0x9, 0x19, 0x29, 0x39} 45 | cards.Set([]byte{0xEF, 0xFF, 0x9, 0x91, 0x39, 0x29}) 46 | 47 | //for i:=THREE ;i<21;i++{ 48 | // t.Logf("%v %v ",i,cards.Get(i)) 49 | //} 50 | 51 | //t.Log(a.Get(232)) 52 | } 53 | 54 | func TestAnalyseStartEnd(t *testing.T) { 55 | handcards := []byte{0xEF, 0xFF, 0x9, 0x19, 0x39, 0x29} 56 | var an AnalyseCards 57 | an.Set(handcards) 58 | 59 | t.Log(an.Start(), an.End(),an.Len()) 60 | } 61 | -------------------------------------------------------------------------------- /src/algorithm/cards.go: -------------------------------------------------------------------------------- 1 | package algorithm 2 | 3 | //发牌 4 | // 最后一个返回为预留3张地主牌 5 | func Deal() ([]byte, []byte, []byte, []byte) { 6 | cards := Shuffle() 7 | cards4 := make([]byte, 3) 8 | copy(cards4, cards[:3]) 9 | cards3 := make([]byte, 17) 10 | copy(cards3, cards[3:20]) 11 | cards2 := make([]byte, 17) 12 | copy(cards2, cards[20:37]) 13 | cards1 := make([]byte, 17) 14 | copy(cards1, cards[37:]) 15 | return cards1, cards2, cards3, cards4 16 | } 17 | 18 | type Cards struct { 19 | Cards []byte //原始牌 20 | analyseCards AnalyseCards 21 | } 22 | 23 | func (this *Cards) Value() byte { 24 | return this.analyseCards.GetValue() 25 | } 26 | 27 | func (this *Cards) Weight() uint8 { 28 | return this.analyseCards.GetWeight() 29 | } 30 | func (this *Cards) Kind() uint8 { 31 | return this.analyseCards.GetKind() 32 | } 33 | 34 | func (this *Cards) Len() uint8 { 35 | return uint8(len(this.Cards)) 36 | } 37 | 38 | func BuildCards(cards []byte) *Cards { 39 | c := &Cards{} 40 | c.AnalyseSort(cards) 41 | return c 42 | } 43 | 44 | func (c *Cards) AnalyseSort(cards []byte) { 45 | c.Cards = cards 46 | c.analyseCards.Analyse(cards) 47 | } 48 | 49 | // 分析选牌是否大于上手所出的牌 50 | func (c *Cards) Follow(discard []byte) bool { 51 | return c.analyseCards.Follow(discard) 52 | } 53 | 54 | //分析牌型 55 | func (this *Cards) AnalyseUnSort(cards []byte) { 56 | this.Cards = cards 57 | this.analyseCards.Set(cards) 58 | } 59 | 60 | // 获取所有可能的牌型组合 61 | func (this *Cards) GetGroup() (result []AnalyseCards) { 62 | return this.analyseCards.GetGroup() 63 | } 64 | 65 | // 压牌提示 66 | func (this *Cards) Prompt(discards []byte) (result []*Cards) { 67 | if len(this.Cards) == 0 || len(discards) == 0 { 68 | return 69 | } 70 | arr := this.analyseCards.Prompt(discards, this.Len()) 71 | // 返回选中的牌,需要把牌转换为正常的牌面值 72 | for _, v := range arr { 73 | c := &Cards{analyseCards: v} 74 | c.Cards = v.ColorRecover(this.Cards) 75 | result = append(result, c) 76 | } 77 | return 78 | } 79 | -------------------------------------------------------------------------------- /src/algorithm/constan.go: -------------------------------------------------------------------------------- 1 | package algorithm 2 | 3 | //扑克牌54张,分别包含普通牌52张 2-10、J、Q、K、A (以上每种牌4个花色 黑桃、梅花、红心、方块)和小王大王 4 | var CARDS = []byte{ 5 | //方块 6 | 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 7 | //梅花 8 | 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 9 | //红桃 10 | 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 11 | //黑桃 12 | 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 13 | //小大王 14 | 0xEF, 0xFF, 15 | } 16 | 17 | // 牌型 18 | const ( 19 | UNKNOW = 0 // 未知牌型 20 | DAN_TIAO = 1 //单条----从3(最小)A<2<小王<大王(最大) 21 | DUI_ZI = 2 //对子----两张大小相同的牌,从3(最小)到2(最大) 22 | DAN_SHUN_ZI = 3 //顺子----至少5张连续大小(从3到A,2和王不能用)的牌,例如8-9-10-J-Q; 23 | LIAN_DUI = 4 //连对----至少3个连续大小(从3到A,2和王不能用)的对子,例如10-10-J-J-Q-Q-K-K; 24 | SAN_TIAO = 5 //三条----三张大小相同的牌 25 | SAN_DAI_YI = 6 //三带单----三张并带上任意一张牌,例如6-6-6-8,根据三张的大小来比较,例如9-9-9-3盖过8-8-8-A; 26 | SAN_DAI_YI_DUI = 7 //三带对----三张并带上一对,类似扑克中的副路(Full House),根据三张的大小来比较,例如Q-Q-Q-6-6盖过10-10-10-K-K; 27 | SAN_SHUN_ZI = 8 //三顺----至少2个连续大小(从3到A)的三张,例如4-4-4-5-5-5; 28 | FEI_JI_DAI_DAN = 9 //飞机带单----“三顺”带同数量的单牌,例如7-7-7-8-8-8-3-6,尽管三张2不能用,但能够带上单张2和王; 29 | FEI_JI_DAI_DUI = 10 //飞机带对----“三顺”带同数量的对子,例如8-8-8-9-9-9-4-4-J-J,尽管三张2不能用,但能够带上一对2,三张带上的单张和一对不能是混合的,例如3-3-3-4-4-4-6-7-7就是不合法的; 30 | SI_DAI_DAN = 11 //四带两个----四张点数相同的牌带任意两张单牌 31 | SI_DAI_DUI = 12 //四带两对----四张点数相同的牌带任意两张两个对子 32 | ZHA_DAN = 13 //炸弹----四张大小相同的牌,炸弹能盖过除火箭外的其他牌型,大的炸弹能盖过小的炸弹 33 | WANG_ZHA = 14 //王炸----一对王,这是最大的组合,能够盖过包括炸弹在内的任何牌型 34 | ) 35 | 36 | // 牌型权重映射表 37 | var Weights = map[uint8]uint8{ 38 | DAN_TIAO: 1, 39 | DAN_SHUN_ZI: 1, 40 | WANG_ZHA: 3, 41 | DUI_ZI: 1, 42 | LIAN_DUI: 1, 43 | SAN_TIAO: 1, 44 | SAN_DAI_YI: 1, 45 | SAN_DAI_YI_DUI: 1, 46 | FEI_JI_DAI_DAN: 1, 47 | FEI_JI_DAI_DUI: 1, 48 | ZHA_DAN: 2, 49 | SI_DAI_DAN: 1, 50 | SI_DAI_DUI: 1, 51 | SAN_SHUN_ZI: 1, 52 | } 53 | 54 | const ( 55 | DA_WANG byte = 17 56 | XIAO_WANG byte = 16 57 | TWO byte = 15 58 | A byte = 14 59 | THREE byte = 3 60 | ) 61 | 62 | const ( 63 | SEAT = 3 64 | TOTAL = 54 65 | HAND_CARDS = 17 66 | HAND_CARDS_LANDLORD = 20 67 | ) 68 | -------------------------------------------------------------------------------- /src/algorithm/assemble_test.go: -------------------------------------------------------------------------------- 1 | package algorithm 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestAssembleAllSanDaiDan(t *testing.T) { 8 | var an AnalyseCards 9 | hand := []byte{0x03, 0x13, 0x23, 0x33, 0x04, 0x14, 0x24, 0x34, 0x15, 0x25, 0x06, 0x16, 0x07, 0x17} 10 | an.Set(hand) 11 | arr := make([]AnalyseCards, 0) 12 | an.AllSanDaiDan(&arr) 13 | 14 | t.Logf("%v ", len(arr) == 8) 15 | for i := len(arr) - 1; i >= 0; i-- { 16 | v := arr[i] 17 | cards := v.ColorRecover(hand) 18 | SortCards(cards, 0, int8(len(cards)-1)) 19 | t.Logf("%#v %v ", cards, v.Weight()) 20 | } 21 | 22 | hand = []byte{0x03, 0x13, 0x23, 0x33, 0x04, 0x14, 0x24, 0x34, 0x15, 0x25, 0x06, 0x16, 0x07, 0x17} 23 | an.Set(hand) 24 | arr = make([]AnalyseCards, 0) 25 | an.AllSanDaiDui(&arr) 26 | 27 | t.Logf("%v ", len(arr) == 8) 28 | for i := len(arr) - 1; i >= 0; i-- { 29 | v := arr[i] 30 | cards := v.ColorRecover(hand) 31 | SortCards(cards, 0, int8(len(cards)-1)) 32 | t.Logf("%#v %v ", cards, v.Weight()) 33 | } 34 | 35 | return 36 | } 37 | func TestAssembleAllSiDaiDan(t *testing.T) { 38 | var an AnalyseCards 39 | hand := []byte{0x03, 0x13, 0x23, 0x33, 0x04, 0x14, 0x24, 0x34, 0x15, 0x25, 0x06, 0x16, 0x07, 0x17} 40 | an.Set(hand) 41 | arr := make([]AnalyseCards, 0) 42 | an.AllSiDaiDan(&arr) 43 | 44 | t.Logf("%v ", len(arr) == 20) 45 | /*for i := len(arr) - 1; i >= 0; i-- { 46 | v := arr[i] 47 | cards := v.ColorRecover(hand) 48 | SortCards(cards, 0, int8(len(cards)-1)) 49 | t.Logf("%#v %v ", cards, v.Weight()) 50 | }*/ 51 | 52 | return 53 | } 54 | func TestAssembleAllSiDaiDui(t *testing.T) { 55 | var an AnalyseCards 56 | hand := []byte{0x03, 0x13, 0x23, 0x33, 0x04, 0x14, 0x24, 0x34, 0x15, 0x25, 0x06, 0x16, 0x07, 0x17} 57 | an.Set(hand) 58 | arr := make([]AnalyseCards, 0) 59 | an.AllSiDaiDui(&arr) 60 | 61 | t.Logf("%v ", len(arr) == 8) 62 | 63 | /*for i := len(arr) - 1; i >= 0; i-- { 64 | v := arr[i] 65 | cards := v.ColorRecover(hand) 66 | SortCards(cards, 0, int8(len(cards)-1)) 67 | t.Logf("%#v %v ", cards, v.Weight()) 68 | } 69 | */ 70 | return 71 | } 72 | func TestAssembleAllFeijiDaiDui(t *testing.T) { 73 | var an AnalyseCards 74 | hand := []byte{0x03, 0x13, 0x04, 0x14, 0x24, 0x15, 0x25, 0x05, 0x06, 0x16, 0x07, 0x17} 75 | an.Set(hand) 76 | arr := make([]AnalyseCards, 0) 77 | an.AllFeijiDaiDui(&arr) 78 | 79 | t.Logf("%v ", len(arr) == 3) 80 | 81 | /*for i := len(arr) - 1; i >= 0; i-- { 82 | v := arr[i] 83 | cards := v.ColorRecover(hand) 84 | SortCards(cards, 0, int8(len(cards)-1)) 85 | t.Logf("%#v %v ", cards, v.Weight()) 86 | } 87 | */ 88 | return 89 | } 90 | func TestAssembleAllFeijiDaiDan(t *testing.T) { 91 | var an AnalyseCards 92 | hand := []byte{0x05, 0x03, 0x04, 0x14, 0x24, 0x15, 0x25, 0x06, 0x16, 0x07} // 不拆对子 93 | an.Set(hand) 94 | arr := make([]AnalyseCards, 0) 95 | an.AllFeijiDaiDan(&arr) 96 | 97 | t.Logf("%v ", len(arr) == 6) 98 | /* 99 | for i := len(arr) - 1; i >= 0; i-- { 100 | v := arr[i] 101 | cards := v.ColorRecover(hand) 102 | SortCards(cards, 0, int8(len(cards)-1)) 103 | t.Logf("%#v %v ", cards, v.Weight()) 104 | }*/ 105 | 106 | return 107 | } 108 | func TestAssemble(t *testing.T) { 109 | var an AnalyseCards 110 | //hand:=[]byte{ 0x02, 0x12, 0x22, 0x32 ,0x04, 0x15, 0x06, 0x17, 0x08, 0x03, 0x04, 0x15, 0x06, 0x17, 0x08, 0x03, 0x04, 0x15, 0x06, 0x17, 0x08} 111 | //hand:=[]byte{ 0x02, 0x12, 0x22, 0x32 ,0x03} 112 | //hand:=[]byte{ 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E} 113 | 114 | //hand := []byte{0x03, 0x04, 0x14, 0x24, 0x15, 0x25, 0x05, 0x06, 0x16, 0x07} // 不拆对子 115 | //hand := []byte{0x05, 0x34, 0x04, 0x14, 0x24, 0x15, 0x25, 0x07} // 拆炸弹做飞机 116 | hand := []byte{0x05, 0x25} // 对子不能拆开打 117 | 118 | an.Set(hand) 119 | /* 120 | arr := an.GetGroup() 121 | for i := len(arr) - 1; i >= 0; i-- { 122 | v := arr[i] 123 | cards := v.ColorRecover(hand) 124 | SortCards(cards, 0, int8(len(cards)-1)) 125 | t.Logf("%#v %v ", cards, v.Weight()) 126 | } 127 | 128 | return*/ 129 | var anList []AnalyseCards 130 | 131 | wei := AnalyseWeightMax(&anList, an) 132 | //wei := AnalyseWeightMax(an) 133 | t.Logf("%v %v ", wei, len(anList)) 134 | 135 | for i := 0; i < len(anList); i++ { 136 | v := anList[i] 137 | cards := v.ColorRecover(hand) 138 | SortCards(cards, 0, int8(len(cards)-1)) 139 | t.Logf("%#v %v ", cards, v.Weight()) 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /src/algorithm/sort_card_test.go: -------------------------------------------------------------------------------- 1 | package algorithm 2 | 3 | import ( 4 | "testing" 5 | "fmt" 6 | "time" 7 | ) 8 | 9 | func Test_Sort(t *testing.T) { 10 | cards := Shuffle() 11 | //SortCards(cards, 0, int8(len(cards))-1) 12 | BigSortCards(cards, 0, int8(len(cards))-1) 13 | t.Logf("排序: %#x", cards) 14 | } 15 | 16 | func count1(m int, n int) int { 17 | if n < m { 18 | return -1 19 | } 20 | x := m 21 | y := n 22 | for i := 0; i < m-1; i++ { 23 | n-- 24 | y *= n 25 | } 26 | 27 | for m--; m > 1; m-- { 28 | x *= m 29 | } 30 | return y / x 31 | } 32 | 33 | func TestValueZuHe(t *testing.T) { 34 | arr := []byte{1, 2, 3, 4, 5} 35 | 36 | rel :=Combine(arr,4) 37 | 38 | for _, v := range rel { 39 | fmt.Println(v) 40 | } 41 | } 42 | 43 | func TestCombine(t *testing.T) { 44 | 45 | } 46 | func TestCombineUnique(t *testing.T) { 47 | arr := []byte{1,2, 2, 3, 4, 5} 48 | 49 | 50 | t.Logf("%+v ",Combine(arr,4)) 51 | 52 | 53 | arr = []byte{1,2, 2, 3} 54 | t.Logf("%+v ",CombineUnique(arr,2)) 55 | } 56 | func TestValueSort(t *testing.T) { 57 | 58 | //cards := []byte{0x0b, 0x0c, 0x2d, 0x1e, 0xFF} 59 | 60 | //cards1 := ConvertValue(cards) 61 | 62 | //t.Logf("%#v %#v ", cards, RecoverValue(cards, cards1)) 63 | } 64 | 65 | 66 | 67 | 68 | /* 69 | 【排列组合问题:n个数中取m个】 70 | */ 71 | func Test10Base(t *testing.T) { 72 | nums := []int{1, 2, 3, 4,4, 5,6} 73 | m := 2 74 | arr:=Combine([]byte{1, 2, 3,4, 4, 5,6},2) 75 | 76 | fmt.Println(arr) 77 | 78 | timeStart := time.Now() 79 | n := len(nums) 80 | indexs := zuheResult(n, m) 81 | result := findNumsByIndexs(nums, indexs) 82 | timeEnd := time.Now() 83 | 84 | fmt.Println("count:", len(result)) 85 | fmt.Println("result:", result) 86 | fmt.Println("time consume:", timeEnd.Sub(timeStart)) 87 | //结果是否正确 88 | rightCount := mathZuhe(n, m) 89 | 90 | fmt.Println(rightCount == len(arr)) 91 | 92 | if rightCount == len(result) { 93 | fmt.Println("结果正确") 94 | } else { 95 | fmt.Println("结果错误,正确结果是:", rightCount) 96 | } 97 | } 98 | 99 | //组合算法(从nums中取出m个数) 100 | func zuheResult(n int, m int) [][]int { 101 | if m < 1 || m > n { 102 | fmt.Println("Illegal argument. Param m must between 1 and len(nums).") 103 | return [][]int{} 104 | } 105 | 106 | //保存最终结果的数组,总数直接通过数学公式计算 107 | result := make([][]int, 0, mathZuhe(n, m)) 108 | //保存每一个组合的索引的数组,1表示选中,0表示未选中 109 | indexs := make([]int, n) 110 | for i := 0; i < n; i++ { 111 | if i < m { 112 | indexs[i] = 1 113 | } else { 114 | indexs[i] = 0 115 | } 116 | } 117 | 118 | //第一个结果 119 | result = addTo(result, indexs) 120 | for { 121 | find := false 122 | //每次循环将第一次出现的 1 0 改为 0 1,同时将左侧的1移动到最左侧 123 | for i := 0; i < n-1; i++ { 124 | if indexs[i] == 1 && indexs[i+1] == 0 { 125 | find = true 126 | 127 | indexs[i], indexs[i+1] = 0, 1 128 | if i > 1 { 129 | moveOneToLeft(indexs[:i]) 130 | } 131 | result = addTo(result, indexs) 132 | 133 | break 134 | } 135 | } 136 | 137 | //本次循环没有找到 1 0 ,说明已经取到了最后一种情况 138 | if !find { 139 | break 140 | } 141 | } 142 | 143 | return result 144 | } 145 | 146 | //将ele复制后添加到arr中,返回新的数组 147 | func addTo(arr [][]int, ele []int) [][]int { 148 | newEle := make([]int, len(ele)) 149 | copy(newEle, ele) 150 | arr = append(arr, newEle) 151 | 152 | return arr 153 | } 154 | 155 | func moveOneToLeft(leftNums []int) { 156 | //计算有几个1 157 | sum := 0 158 | for i := 0; i < len(leftNums); i++ { 159 | if leftNums[i] == 1 { 160 | sum++ 161 | } 162 | } 163 | 164 | //将前sum个改为1,之后的改为0 165 | for i := 0; i < len(leftNums); i++ { 166 | if i < sum { 167 | leftNums[i] = 1 168 | } else { 169 | leftNums[i] = 0 170 | } 171 | } 172 | } 173 | 174 | //根据索引号数组得到元素数组 175 | func findNumsByIndexs(nums []int, indexs [][]int) [][]int { 176 | if len(indexs) == 0 { 177 | return [][]int{} 178 | } 179 | 180 | result := make([][]int, len(indexs)) 181 | 182 | for i, v := range indexs { 183 | line := make([]int, 0) 184 | for j, v2 := range v { 185 | if v2 == 1 { 186 | line = append(line, nums[j]) 187 | } 188 | } 189 | result[i] = line 190 | } 191 | 192 | return result 193 | } 194 | 195 | //数学方法计算排列数(从n中取m个数) 196 | func mathPailie(n int, m int) int { 197 | return jieCheng(n) / jieCheng(n-m) 198 | } 199 | 200 | //数学方法计算组合数(从n中取m个数) 201 | func mathZuhe(n int, m int) int { 202 | return jieCheng(n) / (jieCheng(n-m) * jieCheng(m)) 203 | } 204 | 205 | //阶乘 206 | func jieCheng(n int) int { 207 | result := 1 208 | for i := 2; i <= n; i++ { 209 | result *= i 210 | } 211 | 212 | return result 213 | } -------------------------------------------------------------------------------- /src/algorithm/sort_card.go: -------------------------------------------------------------------------------- 1 | package algorithm 2 | 3 | // 对牌值从小到大排序,采用快速排序算法 4 | func SortCards(arr []byte, start, end int8) { 5 | if start < end { 6 | i, j := start, end 7 | card := arr[(start+end)/2] 8 | key := GetValue(card) 9 | suit := card >> 4 10 | for i <= j { 11 | for GetValue(arr[i]) < key || (GetValue(arr[i]) == key && arr[i]>>4 < suit) { 12 | i++ 13 | } 14 | for GetValue(arr[j]) > key || (GetValue(arr[j]) == key && arr[j]>>4 > suit) { 15 | 16 | j-- 17 | } 18 | if i <= j { 19 | arr[i], arr[j] = arr[j], arr[i] 20 | i++ 21 | j-- 22 | } 23 | } 24 | if start < j { 25 | SortCards(arr, start, j) 26 | } 27 | if end > i { 28 | SortCards(arr, i, end) 29 | } 30 | } 31 | } 32 | 33 | // 对牌值从大到小排序 34 | func BigSortCards(arr []byte, start, end int8) { 35 | if start < end { 36 | i, j := start, end 37 | card := arr[(start+end)/2] 38 | key := GetValue(card) 39 | suit := card >> 4 40 | for i <= j { 41 | for GetValue(arr[i]) > key || (GetValue(arr[i]) == key && arr[i]>>4 < suit) { 42 | i++ 43 | } 44 | for GetValue(arr[j]) < key || (GetValue(arr[j]) == key && arr[j]>>4 > suit) { 45 | j-- 46 | } 47 | if i <= j { 48 | arr[i], arr[j] = arr[j], arr[i] 49 | i++ 50 | j-- 51 | } 52 | } 53 | if start < j { 54 | BigSortCards(arr, start, j) 55 | } 56 | if end > i { 57 | BigSortCards(arr, i, end) 58 | } 59 | } 60 | } 61 | 62 | func Sort(cards []byte, start, end int8) { 63 | if start < end { 64 | i, j := start, end 65 | card := cards[(start+end)/2] 66 | for i <= j { 67 | for cards[i] < card { 68 | i++ 69 | } 70 | for cards[j] > card { 71 | j-- 72 | } 73 | if i <= j { 74 | cards[i], cards[j] = cards[j], cards[i] 75 | i++ 76 | j-- 77 | } 78 | } 79 | if start < j { 80 | Sort(cards, start, j) 81 | } 82 | if end > i { 83 | Sort(cards, i, end) 84 | } 85 | } 86 | } 87 | 88 | func SearchMaxWeight(cards []AnalyseCards) AnalyseCards { 89 | leng := len(cards) 90 | var tmp = cards[0] 91 | var wei = tmp.Weight() 92 | for i := 1; i < leng; i++ { 93 | twei := cards[i].Weight() 94 | if twei > wei { 95 | tmp = cards[i] 96 | wei = twei 97 | } 98 | } 99 | return tmp 100 | } 101 | func SortAnalyseCardsByWeigth(cards []AnalyseCards, start, end int) { 102 | if start < end { 103 | i, j := start, end 104 | card := cards[(start+end)/2].Weight() 105 | for i <= j { 106 | for cards[i].Weight() < card { 107 | i++ 108 | } 109 | for cards[j].Weight() > card { 110 | j-- 111 | } 112 | if i <= j { 113 | cards[i], cards[j] = cards[j], cards[i] 114 | i++ 115 | j-- 116 | } 117 | } 118 | if start < j { 119 | SortAnalyseCardsByWeigth(cards, start, j) 120 | } 121 | if end > i { 122 | SortAnalyseCardsByWeigth(cards, i, end) 123 | } 124 | } 125 | } 126 | 127 | func SortAnalyseCardsByLen(cards []AnalyseCards, start, end int) { 128 | if start < end { 129 | i, j := start, end 130 | card := cards[(start+end)/2].Len() 131 | for i <= j { 132 | for cards[i].Len() < card { 133 | i++ 134 | } 135 | for cards[j].Len() > card { 136 | j-- 137 | } 138 | if i <= j { 139 | cards[i], cards[j] = cards[j], cards[i] 140 | i++ 141 | j-- 142 | } 143 | } 144 | if start < j { 145 | SortAnalyseCardsByLen(cards, start, j) 146 | } 147 | if end > i { 148 | SortAnalyseCardsByLen(cards, i, end) 149 | } 150 | } 151 | } 152 | 153 | func NextSeat(seat uint32) uint32 { 154 | if seat == SEAT { 155 | seat = 1 156 | } 157 | return seat + 1 158 | } 159 | 160 | func combineloop(arr []byte, rel *[][]byte, r []byte, i int, n int) { 161 | if n <= 0 { 162 | return 163 | } 164 | rlen := len(r) - n 165 | alen := len(arr) 166 | for j := i; j < alen; j++ { 167 | r[rlen] = arr[j] 168 | if n == 1 { 169 | or := make([]byte, len(r)) 170 | copy(or, r) 171 | *rel = append(*rel, or) 172 | } else { 173 | combineloop(arr, rel, r, j+1, n-1) 174 | } 175 | } 176 | } 177 | 178 | func CombineUnique(cards []byte, n int) [][]byte { 179 | rel := Combine(cards, n) 180 | for i := 0; i < len(rel)-1; i++ { 181 | for j := i + 1; j < len(rel); j++ { 182 | count:=0 183 | for k := 0; k < n; k++ { 184 | if rel[i][k] != rel[j][k] { 185 | break 186 | } 187 | count++ 188 | } 189 | if count == n{ 190 | rel = append(rel[:i], rel[i+1:]...) 191 | } 192 | } 193 | } 194 | return rel[:] 195 | } 196 | 197 | func Combine(cards []byte, n int) [][]byte { 198 | arr := make([]byte, n) 199 | rel := make([][]byte, 0) 200 | combineloop(cards[:], &rel, arr[:], 0, n) 201 | return rel[:] 202 | } 203 | -------------------------------------------------------------------------------- /src/algorithm/analyse_cards.go: -------------------------------------------------------------------------------- 1 | package algorithm 2 | 3 | type AnalyseCards uint64 4 | 5 | func (this *AnalyseCards) Set(cards []byte) { 6 | *this = 0 7 | l := uint8(len(cards)) 8 | for i := uint8(0); i < l; i++ { 9 | card := (GetValue(cards[i]) - 3) * 3 10 | count := ((*this >> card) & 0x07) + 1 11 | *this &= (^(0x07 << card)) 12 | *this |= (count << card) 13 | } 14 | 15 | this.SetStartEnd() 16 | } 17 | 18 | func (this *AnalyseCards) SetSortCards(cards []byte) { 19 | *this = 0 20 | l := uint8(len(cards)) 21 | for i := uint8(0); i < l; i++ { 22 | card := (cards[i] - 3) * 3 23 | count := ((*this >> card) & 0x07) + 1 24 | *this &= (^(0x07 << card)) 25 | *this |= (count << card) 26 | } 27 | this.SetStartEnd() 28 | } 29 | 30 | func (this *AnalyseCards) Get(card byte) uint8 { 31 | return uint8((*this >> ((card - 3) * 3 )) & 0x07) 32 | } 33 | 34 | func (this *AnalyseCards) SetStartEnd() { 35 | var start, end uint8 36 | for i := uint8(THREE); i <= DA_WANG; i++ { 37 | if start == 0 && this.Get(i) > 0 { 38 | start = i 39 | } 40 | 41 | if end == 0 && this.Get(DA_WANG+THREE-i) > 0 { 42 | end = DA_WANG + THREE - i 43 | } 44 | 45 | if start > 0 && end > 0 { 46 | break 47 | } 48 | } 49 | 50 | card := uint8(46) 51 | *this &= (^(0xF << card)) 52 | *this |= (AnalyseCards(start-3) << card) 53 | 54 | card = uint8(50) 55 | *this &= (^(0xF << card)) 56 | *this |= (AnalyseCards(end-3) << card) 57 | } 58 | 59 | func (this *AnalyseCards) Reset() { 60 | this.SetValue(0) 61 | this.SetKind(0) 62 | this.SetStartEnd() 63 | } 64 | 65 | func (this *AnalyseCards) End() uint8 { 66 | return byte((*this>>50 )&0xF) + 3 67 | } 68 | func (this *AnalyseCards) Start() uint8 { 69 | return byte((*this>>46 )&0xF) + 3 70 | } 71 | 72 | func (this *AnalyseCards) GetValue() byte { 73 | return byte((*this >> 59 ) & 0x1F) 74 | } 75 | 76 | func (this *AnalyseCards) SetValue(value byte) { 77 | card := uint8(59) 78 | *this &= (^(0x1F << card)) 79 | *this |= (AnalyseCards(value) << card) 80 | } 81 | 82 | func (this *AnalyseCards) GetKind() uint8 { 83 | return byte((*this >> 54 ) & 0x1F) 84 | } 85 | 86 | func (this *AnalyseCards) SetKind(kind uint8) { 87 | card := uint8(54) 88 | *this &= (^(0x1F << card)) 89 | *this |= (AnalyseCards(kind) << card) 90 | } 91 | 92 | func (this *AnalyseCards) GetWeight() uint8 { 93 | return Weights[this.GetKind()] 94 | } 95 | 96 | func (this *AnalyseCards) ColorRecover(handcards []byte) []byte { 97 | analyseCards := *this 98 | cards := make([]byte, 0, 10) 99 | for _, v := range handcards { 100 | if analyseCards > 0 { 101 | card := GetValue(v) 102 | if analyseCards.Get(card) > 0 { 103 | cards = append(cards, v) 104 | analyseCards.Incr(card, -1) 105 | } 106 | } 107 | } 108 | return cards 109 | } 110 | 111 | func (this *AnalyseCards) Flat() []byte { 112 | cards := make([]byte, 0, this.Len()) 113 | start := this.Start() 114 | end := this.End() 115 | for i := start; i <= end; i++ { 116 | count := this.Get(i) 117 | if count > 0 { 118 | for j := uint8(0); j < count; j++ { 119 | cards = append(cards, i) 120 | } 121 | } 122 | } 123 | return cards 124 | } 125 | func (this *AnalyseCards) Len() uint8 { 126 | var count uint8 127 | start := this.Start() 128 | end := this.End() 129 | for i := start; i <= end; i++ { 130 | count += this.Get(i) 131 | } 132 | return count 133 | } 134 | 135 | func (this *AnalyseCards) Sub(cards AnalyseCards) AnalyseCards { 136 | t := *this 137 | start := cards.Start() 138 | end := cards.End() 139 | for i := start; i <= end; i++ { 140 | count := cards.Get(i) 141 | if count > 0 { 142 | t.Incr(i, -int8(count)) 143 | } 144 | } 145 | t.SetValue(0) 146 | t.SetKind(0) 147 | return t 148 | } 149 | func (this *AnalyseCards) Add(cards AnalyseCards) AnalyseCards { 150 | t := *this 151 | start := cards.Start() 152 | end := cards.End() 153 | for i := start; i <= end; i++ { 154 | count := cards.Get(i) 155 | if count > 0 { 156 | t.Incr(i, int8(count)) 157 | } 158 | } 159 | t.SetValue(0) 160 | t.SetKind(0) 161 | return t 162 | } 163 | 164 | func (this *AnalyseCards) Incr(card byte, num int8) { 165 | card = (card - 3) * 3 166 | count1 := ((*this >> card) & 0x07) 167 | count := int64(count1) + int64(num) 168 | *this &= (^(0x07 << card)) 169 | if count > 0 { 170 | *this |= ((AnalyseCards(count & 0x07) ) << card) 171 | } 172 | this.SetStartEnd() 173 | } 174 | 175 | func (this *AnalyseCards) Padding(count uint8, length uint8, card byte) { 176 | for m := uint8(0); m < count; m++ { 177 | c := card - m 178 | this.Incr(c, int8(length)) 179 | } 180 | this.SetValue(0) 181 | this.SetKind(0) 182 | } 183 | -------------------------------------------------------------------------------- /src/algorithm/ai_test.go: -------------------------------------------------------------------------------- 1 | package algorithm 2 | 3 | import ( 4 | "testing" 5 | "github.com/golang/glog" 6 | ) 7 | 8 | func yapaitest(handcards, discards []byte, length int, cardType []*Cards) bool { 9 | if length != len(cardType) { 10 | return false 11 | } 12 | for _, v := range cardType { 13 | if !v.Follow(discards) { 14 | //glog.Errorf("%#v %#v %#v", v.Cards, discards, v.Kind()) 15 | glog.Errorf("%#v %v ", v.Value(), v.Kind()) 16 | return false 17 | } 18 | 19 | for _, card := range v.Cards { 20 | exist := false 21 | for _, hcard := range handcards { 22 | if card == hcard { 23 | exist = true 24 | break 25 | } 26 | } 27 | 28 | if !exist { 29 | return false 30 | } 31 | 32 | } 33 | } 34 | return true 35 | } 36 | 37 | func TestSelectCards(t *testing.T) { 38 | 39 | //handcards := []byte{0x03, 0x05, 0x15, 0x25, 0x35, 0x06, 0x16, 0x26, 0x36, 0x18, 0x38, 0x27, 0x08, 0x28, 0x2D} 40 | //ty := &Cards{} 41 | //ty.AnalyseUnSort(handcards) 42 | //cardTypes := ty.GetGroup() 43 | //for _,v:=range cardTypes{ 44 | // t.Logf("%#+v ",v.Cards) 45 | //} 46 | //for k,v:=range ty.analyseCards{ 47 | // t.Log(len(v),k,v) 48 | //} 49 | //t.Logf("%#+v %+v %#+v ", len(cardTypes) ==3 , len(cardTypes),handcards) 50 | 51 | handcards := []byte{0x03, 0x05, 0x15, 0x35, 0x06, 0x26, 0x36, 0x36, 0x17, 0x37, 0x27, 0x08, 0x28, 0x29} 52 | ty := &Cards{} 53 | ty.AnalyseUnSort(handcards) 54 | cardTypes := ty.GetGroup() 55 | //cardTypes = ty.Prompt([]byte{0x03, 0x04, 0x15, 0x37, 0x06}) 56 | for _, v := range cardTypes { 57 | 58 | //t.Logf("%#+v 权重 %v ", v.Cards, v.GetWeight()) 59 | t.Logf("权重 %v ", v) 60 | } 61 | 62 | //t.Logf("%#+v %+v %#+v ", len(cardTypes) == 3, len(cardTypes), handcards) 63 | } 64 | 65 | // 找出手牌中所有的顺子 66 | func TestSearchAllShunZi(t *testing.T) { 67 | 68 | cardType := &Cards{} 69 | cardType.AnalyseUnSort([]byte{0x03, 0x04, 0x15, 0x35, 0x06, 0x2e, 0x3d, 0x3c, 0x17, 0x3b, 0x2a, 0x08, 0x28, 0x29}) 70 | arr := make([]AnalyseCards, 0) 71 | cardType.analyseCards.AllShunZi(&arr) 72 | t.Logf("%+v %#+v", len(arr) == 36, arr) 73 | 74 | cardType = &Cards{} 75 | cardType.AnalyseUnSort([]byte{0x03, 0x04, 0x15, 0x06, 0x17, 0x08, 0x29}) 76 | 77 | arr = make([]AnalyseCards, 0) 78 | cardType.analyseCards.AllShunZi(&arr) 79 | t.Logf("%+v %#+v", len(arr) == 6, arr) 80 | } 81 | 82 | // 找出手牌中所有的连对 83 | func TestSearchAllLianDui(t *testing.T) { 84 | 85 | //cardType:=&Cards{} 86 | //cardType.AnalyseUnSort([]byte{0x03, 0x04, 0x15, 0x35, 0x06, 0x2e, 0x3d, 0x3c, 0x17, 0x3b, 0x2a, 0x08, 0x28, 0x29}) 87 | //t.Logf("%+v %#+v",len(cardType.AllShunZi())==8,cardType.AllShunZi()) 88 | arr := make([]AnalyseCards, 0) 89 | cardType := &Cards{} 90 | cardType.AnalyseUnSort([]byte{0x03, 0x04, 0x15, 0x06, 0x17, 0x08, 0x29, 0x03, 0x04, 0x15, 0x06, 0x17, 0x08, 0x29}) 91 | cardType.analyseCards.AllLianDui(&arr) 92 | t.Logf("%+v %#+v", len(arr) == 15, arr) 93 | } 94 | 95 | // 找出手牌中所有的三顺 96 | func TestSearchAllSanShun(t *testing.T) { 97 | arr := make([]AnalyseCards, 0) 98 | cardType := &Cards{} 99 | cardType.AnalyseUnSort([]byte{0x03, 0x04, 0x15, 0x06, 0x17, 0x08, 0x03, 0x04, 0x15, 0x06, 0x17, 0x08, 0x03, 0x04, 0x15, 0x06, 0x17, 0x08}) 100 | cardType.analyseCards.AllSanShun(&arr) 101 | t.Logf("%+v %#+v", len(arr) == 15, arr) 102 | } 103 | 104 | // 找出手牌中所有的飞机带单 105 | func TestSearchAllFeiJIDaiDan(t *testing.T) { 106 | cardType := &Cards{} 107 | arr := make([]AnalyseCards, 0) 108 | hand := []byte{0x03, 0x04, 0x15, 0x06, 0x17, 0x08, 0x03, 0x04, 0x15, 0x06, 0x17, 0x08, 0x03, 0x04, 0x15, 0x06, 0x17, 0x08} 109 | cardType.AnalyseUnSort(hand) 110 | cardType.analyseCards.AllFeijiDaiDan(&arr) 111 | 112 | for _, v := range arr { 113 | t.Logf("%#+v", v.ColorRecover(hand)) 114 | } 115 | t.Logf("%+v %#+v", len(arr) == 216, arr) 116 | } 117 | 118 | // 找出手牌中所有的飞机带对 119 | func TestSearchAllAllFeiJIDaiDui(t *testing.T) { 120 | cardType := &Cards{} 121 | arr := make([]AnalyseCards, 0) 122 | cardType.AnalyseUnSort([]byte{0x03, 0x04, 0x15, 0x06, 0x17, 0x08, 0x03, 0x04, 0x15, 0x06, 0x17, 0x08, 0x03, 0x04, 0x15, 0x06, 0x17, 0x08}) 123 | cardType.analyseCards.AllFeijiDaiDui(&arr) 124 | t.Logf("%+v %#+v", len(arr) == 5, arr) 125 | } 126 | 127 | func TestSubAndAdd(t *testing.T) { 128 | var an AnalyseCards 129 | an.Set([]byte{0x03, 0x04, 0x15, 0x06, 0x17, 0x08, 0x03, 0x04, 0x15, 0x06, 0x17, 0x08, 0x03, 0x04, 0x15, 0x06, 0x17, 0x08}) 130 | orLen := an.Len() 131 | t.Logf(" %v ", orLen == 18) 132 | var bb AnalyseCards 133 | bb.Set([]byte{0x03, 0x04, 0x15, 0x06, 0x17, 0x08}) 134 | 135 | an.Sub(bb) 136 | an.Add(bb) 137 | t.Logf(" %v ", an.Len() == orLen) 138 | 139 | } 140 | 141 | func TestSearchMax2(t *testing.T) { 142 | var an AnalyseCards 143 | hand := []byte{0x02, 0x12, 0x22, 0x32} 144 | an.Set(hand) 145 | 146 | //discards:=[]byte{ 0x06, 0x16, 0x26 } 147 | 148 | var anList []AnalyseCards 149 | max := AnalyseWeightMax(&anList, an) 150 | t.Logf("%v %v ", max, len(anList)) 151 | 152 | for _, v := range anList { 153 | cards := v.ColorRecover(hand) 154 | SortCards(cards, 0, int8(len(cards)-1)) 155 | t.Logf("%#v %v ", cards, v.Weight()) 156 | } 157 | } 158 | 159 | func TestSearchMax(t *testing.T) { 160 | var an AnalyseCards 161 | an.Set([]byte{0x03, 0x04, 0x15, 0x06, 0x17, 0x08, 0x03, 0x04, 0x15, 0x06, 0x17, 0x08, 0x03, 0x04, 0x15, 0x06, 0x17, 0x08}) 162 | 163 | array := an.GetGroup() 164 | 165 | var anList []AnalyseCards 166 | 167 | max := AnalyseWeightMax(&anList, an) 168 | t.Logf("%v %v %v", len(array) == 78, max == 3, len(anList) == 1) 169 | 170 | } 171 | func TestSearch(t *testing.T) { 172 | 173 | var an AnalyseCards 174 | an.SetKind(12) 175 | 176 | t.Logf("%+v ", an.GetKind() == 12) 177 | 178 | b := an 179 | 180 | //b = 0 181 | b.SetKind(3) 182 | an.SetKind(4) 183 | 184 | t.Logf("%+v %+v %+v", b.GetKind() == 3, an.GetKind() == 4, an != b) 185 | 186 | } 187 | 188 | func TestSearchMax1(t *testing.T) { 189 | var an AnalyseCards 190 | //hand:=[]byte{ 0x02, 0x12, 0x22, 0x32 ,0x04, 0x15, 0x06, 0x17, 0x08, 0x03, 0x04, 0x15, 0x06, 0x17, 0x08, 0x03, 0x04, 0x15, 0x06, 0x17, 0x08} 191 | //hand:=[]byte{ 0x02, 0x12, 0x22, 0x32 ,0x03,0x13,0x13,0x13} 192 | //hand:=[]byte{ 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E} 193 | 194 | hand := []byte{0x05, 0x03, 0x04, 0x14, 0x24, 0x15, 0x25, 0x06, 0x16,0x26, 0x07} // 不拆对子 195 | 196 | //hand := []byte{0x05, 0x34, 0x04, 0x14, 0x24, 0x15, 0x25, 0x07} // 拆炸弹做飞机 197 | //hand:=[]byte{ 0x05,0x25} // 对子不能拆开打 198 | //hand := []byte{0x04, 0x04, 0x05, 0x06, 0x07, 0x08} // 对子不能拆开打 199 | 200 | an.Set(hand) 201 | 202 | /* arr := an.GetGroup() 203 | for i := len(arr) - 1; i >= 0; i-- { 204 | v := arr[i] 205 | cards := v.ColorRecover(hand) 206 | SortCards(cards, 0, int8(len(cards)-1)) 207 | t.Logf("%#v %v ", cards, v.Weight()) 208 | } 209 | t.Logf("%v ", len(arr))*/ 210 | //return 211 | 212 | var anList []AnalyseCards 213 | max := AnalyseWeightMax(&anList, an) 214 | t.Logf("%v %v ", len(anList),max) 215 | 216 | for i := 0; i < len(anList); i++ { 217 | v := anList[i] 218 | cards := v.ColorRecover(hand) 219 | SortCards(cards, 0, int8(len(cards)-1)) 220 | t.Logf("%#v %v ", cards, v.Weight()) 221 | } 222 | } 223 | 224 | type AAA struct { 225 | Value int 226 | } 227 | 228 | func TestZuHe(t *testing.T) { 229 | 230 | //t.Log(-300,-300&0xF) 231 | 232 | 233 | 234 | } 235 | -------------------------------------------------------------------------------- /src/algorithm/follow.go: -------------------------------------------------------------------------------- 1 | package algorithm 2 | 3 | // 分析选牌是否大于上手所出的牌 4 | func (c *AnalyseCards) Follow(dType []byte) bool { 5 | var an AnalyseCards 6 | an.Analyse(dType) 7 | return c.FollowAnalyseCards(an) 8 | } 9 | func (c *AnalyseCards) FollowAnalyseCards(dType AnalyseCards) bool { 10 | if c.Len() != dType.Len() && 11 | c.Len() != 4 && 12 | c.Len() != 2 { //跟牌,但数量不符且不为炸弹 13 | return false 14 | } 15 | 16 | if c.GetKind() == UNKNOW { //所选牌不符合规定 17 | return false 18 | } 19 | 20 | if c.GetWeight() > dType.GetWeight() { // 牌型权重碾压 21 | return true 22 | } 23 | 24 | if c.GetWeight() < dType.GetWeight() { // 牌型权重没碾压 25 | return false 26 | } 27 | 28 | if dType.GetKind() != c.GetKind() { // 牌型不同 29 | return false 30 | } 31 | 32 | if dType.Len() != c.Len() { // 顺子牌型牌张要一致 33 | return false 34 | } 35 | return c.GetValue() > dType.GetValue() // 选牌不大于上家牌 36 | } 37 | 38 | func (c *AnalyseCards) Analyse(cards []byte) { 39 | kind, value := c.analyse(cards) 40 | c.SetValue(value) 41 | c.SetKind(kind) 42 | } 43 | 44 | func (c *AnalyseCards) analyse(cards [] byte) (uint8, byte) { 45 | c.Set(cards) 46 | 47 | length := c.Len() 48 | if length == 1 { 49 | kind, value := c.judgeDan() 50 | if kind > 0 { 51 | return kind, value 52 | } 53 | } 54 | if length == 2 { 55 | kind, value := c.judgePair() 56 | if kind > 0 { 57 | return kind, value 58 | } 59 | kind, value = c.judgeWangZha() 60 | if kind > 0 { 61 | return kind, value 62 | } 63 | return 0, 0 64 | } 65 | if length == 3 { 66 | return c.judge3Same() 67 | } 68 | if length == 4 { 69 | kind, value := c.judgeZhaDan() 70 | if kind > 0 { 71 | return kind, value 72 | } 73 | kind, value = c.judge3And1() 74 | if kind > 0 { 75 | return kind, value 76 | } 77 | return 0, 0 78 | } 79 | if length >= 5 && length <= 12 { 80 | kind, value := c.judgeShunZi(length) 81 | if kind > 0 { 82 | return kind, value 83 | } 84 | } 85 | if length >= 6 && length%2 == 0 { 86 | kind, value := c.judgeLianDui(length) 87 | if kind > 0 { 88 | return kind, value 89 | } 90 | } 91 | if length == 5 { 92 | kind, value := c.judge3AndPair() 93 | if kind > 0 { 94 | return kind, value 95 | } 96 | } 97 | if length == 6 { 98 | kind, value := c.judge4And2() 99 | if kind > 0 { 100 | return kind, value 101 | } 102 | } 103 | if length >= 6 && length%3 == 0 { 104 | kind, value := c.judgeFeiJi(length) 105 | if kind > 0 { 106 | return kind, value 107 | } 108 | } 109 | if length >= 8 && length%4 == 0 { 110 | kind, value := c.judgeFeiJiAndSingle(length) 111 | if kind > 0 { 112 | return kind, value 113 | } 114 | } 115 | if length >= 10 && length%5 == 0 { 116 | kind, value := c.judgeFeiJiAndPair(length) 117 | if kind > 0 { 118 | return kind, value 119 | } 120 | } 121 | if length == 8 { 122 | return c.judge4And2Pair() 123 | } 124 | return 0, 0 125 | } 126 | 127 | //单条 128 | func (c *AnalyseCards) judgeDan() (uint8, byte) { 129 | if c.Get(c.End()) == 1 { 130 | return DAN_TIAO, c.End() 131 | } 132 | return 0, 0 133 | } 134 | 135 | // 对子 136 | func (c *AnalyseCards) judgePair() (uint8, byte) { 137 | if c.Get(c.End()) == 2 { 138 | return DUI_ZI, c.End() 139 | } 140 | return 0, 0 141 | } 142 | 143 | func (c *AnalyseCards) judgeWangZha() (uint8, byte) { 144 | if c.Get(XIAO_WANG) == 1 && c.Get(DA_WANG) == 1 { // 王炸 145 | return WANG_ZHA, DA_WANG 146 | } 147 | return 0, 0 148 | } 149 | 150 | //三条 151 | func (c *AnalyseCards) judge3Same() (uint8, byte) { 152 | if c.Get(c.End()) == 3 { 153 | return SAN_TIAO, c.End() 154 | } 155 | return 0, 0 156 | } 157 | 158 | //炸弹 159 | func (c *AnalyseCards) judgeZhaDan() (uint8, byte) { 160 | if c.Get(c.End()) == 4 { 161 | return ZHA_DAN, c.End() 162 | } 163 | return 0, 0 164 | } 165 | 166 | //三带一 167 | func (c *AnalyseCards) judge3And1() (uint8, byte) { 168 | start := c.Start() 169 | end := c.End() 170 | if end > TWO { 171 | end = TWO 172 | } 173 | for i := start; i <= end; i++ { 174 | count := c.Get(i) 175 | if count == 3 { 176 | return SAN_DAI_YI, i 177 | } else if count == 2 || count == 4 { 178 | break 179 | } 180 | } 181 | return 0, 0 182 | } 183 | 184 | //顺子 185 | func (c *AnalyseCards) judgeShunZi(length uint8) (uint8, byte) { 186 | start := c.Start() 187 | end := c.End() 188 | if end > A { 189 | end = A 190 | } 191 | if ( end - start + 1) != length { 192 | return 0, 0 193 | } 194 | 195 | for i := start; i <= end; i++ { 196 | if c.Get(i) != 1 { 197 | return 0, 0 198 | } 199 | } 200 | 201 | return DAN_SHUN_ZI, end 202 | } 203 | 204 | //连对 205 | func (c *AnalyseCards) judgeLianDui(length uint8) (uint8, byte) { 206 | start := c.Start() 207 | end := c.End() 208 | if end > A { 209 | end = A 210 | } 211 | if ( end-start+1)*2 != length { 212 | return 0, 0 213 | } 214 | 215 | for i := start; i <= end; i++ { 216 | if c.Get(i) != 2 { 217 | return 0, 0 218 | } 219 | } 220 | return LIAN_DUI, end 221 | } 222 | 223 | //三带一对 11122 22333 224 | func (c *AnalyseCards) judge3AndPair() (uint8, byte) { 225 | var value byte 226 | var dui uint8 227 | start := c.Start() 228 | end := c.End() 229 | if end > TWO { 230 | end = TWO 231 | } 232 | for i := end; i >= start; i-- { 233 | count := c.Get(i) 234 | if count == 3 { 235 | value = i 236 | } else if count == 2 { 237 | dui ++ 238 | } else if count > 0 { 239 | break 240 | } 241 | if dui == 1 && value > 0 { 242 | return SAN_DAI_YI_DUI, value 243 | } 244 | } 245 | return 0, 0 246 | } 247 | 248 | //四带两个 111123 233334 456666 249 | func (c *AnalyseCards) judge4And2() (uint8, byte) { 250 | 251 | start := c.Start() 252 | end := c.End() 253 | if end > TWO { 254 | end = TWO 255 | } 256 | for i := end; i >= start; i-- { 257 | count := c.Get(i) 258 | if count == 3 { 259 | break 260 | } else if count == 4 { 261 | return SI_DAI_DAN, i 262 | } 263 | } 264 | return 0, 0 265 | } 266 | 267 | //三顺 333444555 268 | func (c *AnalyseCards) judgeFeiJi(length uint8) (uint8, byte) { 269 | start := c.Start() 270 | end := c.End() 271 | if end > A { 272 | end = A 273 | } 274 | if ( end-start+1)*3 != length { 275 | return 0, 0 276 | } 277 | for i := start; i <= end; i++ { 278 | if c.Get(i) != 3 { 279 | return 0, 0 280 | } 281 | } 282 | 283 | return SAN_SHUN_ZI, end 284 | } 285 | 286 | //飞机带单 287 | func (c *AnalyseCards) judgeFeiJiAndSingle(length uint8) (uint8, byte) { 288 | var num uint8 289 | var value byte 290 | start := c.Start() 291 | end := c.End() 292 | if end > A { 293 | end = A 294 | } 295 | for i := start; i <= end; i++ { 296 | count := c.Get(i) 297 | if count >= 3 { 298 | if value > 0 && value+1 != i { 299 | break 300 | } 301 | num ++ 302 | value = i 303 | } 304 | if length == num*4 { 305 | return FEI_JI_DAI_DAN, value 306 | } 307 | } 308 | return 0, 0 309 | } 310 | 311 | //飞机带对 312 | func (c *AnalyseCards) judgeFeiJiAndPair(length uint8) (uint8, byte) { 313 | var three uint8 314 | var dui uint8 315 | var value byte 316 | start := c.Start() 317 | end := c.End() 318 | if end > TWO { 319 | end = TWO 320 | } 321 | for i := start; i <= end; i++ { 322 | count := c.Get(i) 323 | if count == 3 && i != TWO { 324 | if value > 0 && value+1 != i { 325 | break 326 | } 327 | three ++ 328 | value = i 329 | } else if count == 2 { 330 | dui ++ 331 | } else if count == 4 { 332 | dui += 2 333 | } 334 | if length == three*3+dui*2 { 335 | return FEI_JI_DAI_DUI, value 336 | } 337 | } 338 | return 0, 0 339 | } 340 | 341 | //四带两对 满足 11222233(2-4-2) 11112233(4-2-2) 11223333(2-2-4) 11112222(2-2-4) 342 | func (c *AnalyseCards) judge4And2Pair() (uint8, byte) { 343 | var value byte 344 | var dui uint8 345 | start := c.Start() 346 | end := c.End() 347 | if end > TWO { 348 | end = TWO 349 | } 350 | for i := end; i >= start; i-- { 351 | count := c.Get(i) 352 | if count == 4 && value == 0 { 353 | value = i 354 | } else if count == 4 { 355 | dui += 2 356 | } else if count == 2 { 357 | dui ++ 358 | } else if count > 0 { 359 | break 360 | } 361 | if dui == 2 && value > 0 { 362 | return SI_DAI_DUI, value 363 | } 364 | } 365 | return 0, 0 366 | } 367 | -------------------------------------------------------------------------------- /src/algorithm/assemble.go: -------------------------------------------------------------------------------- 1 | package algorithm 2 | 3 | // 找出手牌中所有的牌型组合 4 | func (this *AnalyseCards) GetGroup() ([]AnalyseCards) { 5 | var length = this.Len() 6 | result := make([]AnalyseCards, 0, length*2) 7 | if length == 0 { 8 | return result 9 | } 10 | 11 | this.PromptDanTiao(0, &result) 12 | 13 | if length >= 4 { 14 | this.PromptZhaDan(0, &result) 15 | } 16 | 17 | if length >= 2 { 18 | this.PromptDuiZi(0, &result) 19 | } 20 | if length >= 3 { 21 | this.PromptSanTiao(0, &result) 22 | } 23 | if length >= 2 { 24 | this.PromptWangZha(&result) 25 | } 26 | if length >= 4 { 27 | this.AllSanDaiDan(&result) 28 | } 29 | if length >= 5 { 30 | this.AllSanDaiDui(&result) 31 | } 32 | 33 | if length >= 6 { 34 | this.AllSiDaiDan(&result) 35 | } 36 | if length >= 8 { 37 | this.AllSiDaiDui(&result) 38 | } 39 | 40 | if length >= 8 { 41 | this.AllFeijiDaiDan(&result) 42 | } 43 | if length >= 10 { 44 | this.AllFeijiDaiDui(&result) 45 | } 46 | if length >= 6 { 47 | this.AllLianDui(&result) 48 | } 49 | if length >= 6 { 50 | this.AllSanShun(&result) 51 | } 52 | if length >= 5 { 53 | this.AllShunZi(&result) 54 | } 55 | 56 | return result 57 | } 58 | 59 | // 找出手牌中所有的顺子 60 | func (this *AnalyseCards) AllShunZi(cardTypes *[]AnalyseCards) { 61 | end := this.End() 62 | start := this.Start() 63 | gap := end - start + 1 64 | if gap < 5 { 65 | return 66 | } 67 | if end > A { 68 | end = A 69 | } 70 | for i := start; i <= end; i++ { 71 | if this.Get(i) >= 1 { 72 | for j := uint8(5); j <= gap; j++ { 73 | k := uint8(0) 74 | for k = uint8(1); k < j; k++ { 75 | if i+k > end || this.Get(i+k) == 0 { 76 | break 77 | } 78 | } 79 | if k == j { 80 | var anCards AnalyseCards 81 | for n := uint8(0); n < j; n++ { 82 | anCards.Incr(i+n, 1) 83 | } 84 | anCards.SetKind(DAN_SHUN_ZI) 85 | anCards.SetValue(i + j - 1) 86 | *cardTypes = append(*cardTypes, anCards) 87 | } 88 | } 89 | } 90 | } 91 | return 92 | } 93 | 94 | // 找出手牌中所有的连对 95 | func (this *AnalyseCards) AllLianDui(cardTypes *[]AnalyseCards) { 96 | end := this.End() 97 | start := this.Start() 98 | if end > A { 99 | end = A 100 | } 101 | 102 | gap := end - start + 1 103 | if gap < 3 { 104 | return 105 | } 106 | for i := start; i <= end; i++ { 107 | if this.Get(i) >= 2 { 108 | for j := uint8(3); j <= gap; j++ { 109 | k := uint8(0) 110 | for k = uint8(1); k < j; k++ { 111 | if i+k > end || this.Get(i+k) < 2 { 112 | break 113 | } 114 | } 115 | if k == j { 116 | var anCards AnalyseCards 117 | for n := uint8(0); n < j; n++ { 118 | anCards.Incr(i+n, 2) 119 | } 120 | anCards.SetKind(LIAN_DUI) 121 | anCards.SetValue(i + j - 1) 122 | *cardTypes = append(*cardTypes, anCards) 123 | } 124 | } 125 | } 126 | } 127 | return 128 | } 129 | 130 | // 找出手牌中所有的三顺 131 | func (this *AnalyseCards) AllSanShun(cardTypes *[]AnalyseCards) { 132 | end := this.End() 133 | start := this.Start() 134 | if end > A { 135 | end = A 136 | } 137 | 138 | gap := end - start + 1 139 | if gap < 2 { 140 | return 141 | } 142 | for i := start; i <= end; i++ { 143 | if this.Get(i) >= 3 { 144 | for j := uint8(2); j <= gap; j++ { 145 | k := uint8(0) 146 | for k = 1; k < j; k++ { 147 | if i+k > end || this.Get(i+k) < 3 { 148 | break 149 | } 150 | } 151 | if k == j { 152 | var anCards AnalyseCards 153 | for n := uint8(0); n < j; n++ { 154 | anCards.Incr(i+n, 3) 155 | } 156 | anCards.SetKind(SAN_SHUN_ZI) 157 | anCards.SetValue(i + j - 1) 158 | *cardTypes = append(*cardTypes, anCards) 159 | } 160 | } 161 | } 162 | } 163 | return 164 | } 165 | 166 | // 找出手牌中所有的飞机带单 167 | func (this *AnalyseCards) AllFeijiDaiDan(cardTypes *[]AnalyseCards) { 168 | arr := make([]AnalyseCards, 0, this.Len()) 169 | this.AllSanShun(&arr) 170 | for key := 0; key < len(arr); key++ { 171 | cards := arr[key] 172 | l := cards.Len() 173 | an := this.Sub(cards) 174 | anL := an.Len() 175 | if l/3 > anL { 176 | continue 177 | } 178 | anFlat := an.Flat() 179 | 180 | combo := CombineUnique(anFlat, int(l/3)) 181 | //combo= combo[:l/3] 182 | for i := 0; i < len(combo); i++ { 183 | //glog.Errorln(combo[i],cards.Flat()) 184 | c := cards 185 | for j := uint8(0); j < l/3; j++ { 186 | c.Incr(combo[i][j], 1) 187 | } 188 | c.SetKind(FEI_JI_DAI_DAN) 189 | c.SetValue(cards.GetValue()) 190 | *cardTypes = append(*cardTypes, c) 191 | } 192 | } 193 | return 194 | } 195 | 196 | // 找出手牌中所有的飞机带对 197 | func (this *AnalyseCards) AllFeijiDaiDui(cardTypes *[]AnalyseCards) { 198 | arr := make([]AnalyseCards, 0, this.Len()) 199 | this.AllSanShun(&arr) 200 | 201 | for _, cards := range arr { 202 | l := cards.Len() 203 | an := this.Sub(cards) 204 | anL := an.Len() 205 | if l/3 > anL/2 { 206 | continue 207 | } 208 | 209 | anFlat := make([]byte, 0, anL/2) 210 | for i := an.Start(); i <= an.End(); i++ { 211 | if an.Get(i) >= 2 { 212 | anFlat = append(anFlat, i) 213 | } 214 | } 215 | 216 | combo := CombineUnique(anFlat, int(l/3)) 217 | 218 | //combo= combo[:l/3] 219 | for i := 0; i < len(combo); i++ { 220 | c := cards 221 | for j := uint8(0); j < l/3; j++ { 222 | c.Incr(combo[i][j], 2) 223 | } 224 | c.SetKind(FEI_JI_DAI_DUI) 225 | c.SetValue(cards.GetValue()) 226 | *cardTypes = append(*cardTypes, c) 227 | } 228 | } 229 | return 230 | } 231 | 232 | func (this *AnalyseCards) AllSiDaiDui(cardTypes *[]AnalyseCards) { 233 | 234 | end := this.End() 235 | if end > TWO { 236 | end = TWO 237 | } 238 | start := this.Start() 239 | for i := end; i >= start; i-- { 240 | if this.Get(i) != 4 { 241 | continue 242 | } 243 | an := *this 244 | an.Incr(i, -4) 245 | anFlat := make([]byte, 0, 2) 246 | for j := an.Start(); j <= an.End(); j++ { 247 | if an.Get(j) == 2 { 248 | anFlat = append(anFlat, j) 249 | } else if an.Get(j) == 4 { 250 | var anCards AnalyseCards 251 | anCards.Incr(i, 4) 252 | anCards.Incr(j, 4) 253 | anCards.SetKind(SI_DAI_DUI) 254 | anCards.SetValue(j) 255 | *cardTypes = append(*cardTypes, anCards) 256 | } 257 | } 258 | 259 | combo := CombineUnique(anFlat, 2) 260 | l := uint8(len(combo)) 261 | for j := uint8(0); j < l; j++ { 262 | var anCards AnalyseCards 263 | anCards.Incr(i, 4) 264 | anCards.Incr(combo[j][0], 2) 265 | anCards.Incr(combo[j][1], 2) 266 | anCards.SetKind(SI_DAI_DUI) 267 | anCards.SetValue(i) 268 | *cardTypes = append(*cardTypes, anCards) 269 | } 270 | } 271 | return 272 | } 273 | 274 | func (this *AnalyseCards) AllSiDaiDan(cardTypes *[]AnalyseCards) { 275 | end := this.End() 276 | start := this.Start() 277 | if end > TWO { 278 | end = TWO 279 | } 280 | for i := end; i >= start; i-- { 281 | if this.Get(i) != 4 { 282 | continue 283 | } 284 | anFlat := make([]byte, 0, 2) 285 | for j := this.Start(); j <= this.End(); j++ { 286 | if i != j && this.Get(j) > 0 { 287 | anFlat = append(anFlat, j) 288 | } 289 | } 290 | 291 | combo := CombineUnique(anFlat, 2) 292 | for j := this.Start(); j <= this.End(); j++ { 293 | if i != j && this.Get(j) >= 2 { 294 | combo = append(combo, []byte{j, j}) 295 | } 296 | } 297 | l := uint8(len(combo)) 298 | for j := uint8(0); j < l; j++ { 299 | var anCards AnalyseCards 300 | anCards.Incr(i, 4) 301 | anCards.Incr(combo[j][0], 1) 302 | anCards.Incr(combo[j][1], 1) 303 | anCards.SetKind(SI_DAI_DAN) 304 | anCards.SetValue(i) 305 | *cardTypes = append(*cardTypes, anCards) 306 | } 307 | } 308 | return 309 | } 310 | 311 | func (this *AnalyseCards) AllSanDaiDui(cardTypes *[]AnalyseCards) { 312 | end := this.End() 313 | start := this.Start() 314 | if end > TWO { 315 | end = TWO 316 | } 317 | for i := end; i >= start; i-- { 318 | if this.Get(i) >=3 { 319 | for j := start; j <= end; j++ { 320 | if i != j && this.Get(j) > 1 { 321 | var anCards AnalyseCards 322 | anCards.Incr(i, 3) 323 | anCards.Incr(j, 2) 324 | anCards.SetKind(SAN_DAI_YI_DUI) 325 | anCards.SetValue(i) 326 | *cardTypes = append(*cardTypes, anCards) 327 | } 328 | } 329 | } 330 | } 331 | return 332 | } 333 | func (this *AnalyseCards) AllSanDaiDan(cardTypes *[]AnalyseCards) { 334 | end := this.End() 335 | start := this.Start() 336 | if end > TWO { 337 | end = TWO 338 | } 339 | for i := end; i >= start; i-- { 340 | if this.Get(i) >= 3 { 341 | for j := start; j <= end; j++ { 342 | if i != j && this.Get(j) > 0 { 343 | var anCards AnalyseCards 344 | anCards.Incr(i, 3) 345 | anCards.Incr(j, 1) 346 | anCards.SetKind(SAN_DAI_YI_DUI) 347 | anCards.SetValue(i) 348 | *cardTypes = append(*cardTypes, anCards) 349 | } 350 | } 351 | } 352 | } 353 | return 354 | } 355 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Go版本实现斗地主核心算法 2 | #### 紧凑的数据结构高效核心算法 3 | 4 | ```go 5 | type AnalyseCards uint64 6 | 7 | func (this *AnalyseCards) Set(cards []byte) { 8 | *this = 0 9 | l := uint8(len(cards)) 10 | for i := uint8(0); i < l; i++ { 11 | card := (GetValue(cards[i]) - 3) * 3 12 | count := ((*this >> card) & 0x07) + 1 13 | *this &= (^(0x07 << card)) 14 | *this |= (count << card) 15 | } 16 | 17 | this.SetStartEnd() 18 | } 19 | 20 | func (this *AnalyseCards) SetSortCards(cards []byte) { 21 | *this = 0 22 | l := uint8(len(cards)) 23 | for i := uint8(0); i < l; i++ { 24 | card := (cards[i] - 3) * 3 25 | count := ((*this >> card) & 0x07) + 1 26 | *this &= (^(0x07 << card)) 27 | *this |= (count << card) 28 | } 29 | this.SetStartEnd() 30 | } 31 | 32 | func (this *AnalyseCards) Get(card byte) uint8 { 33 | return uint8((*this >> ((card - 3) * 3 )) & 0x07) 34 | } 35 | 36 | func (this *AnalyseCards) SetStartEnd() { 37 | var start, end uint8 38 | for i := uint8(THREE); i <= DA_WANG; i++ { 39 | if start == 0 && this.Get(i) > 0 { 40 | start = i 41 | } 42 | 43 | if end == 0 && this.Get(DA_WANG+THREE-i) > 0 { 44 | end = DA_WANG + THREE - i 45 | } 46 | 47 | if start > 0 && end > 0 { 48 | break 49 | } 50 | } 51 | 52 | card := uint8(46) 53 | *this &= (^(0xF << card)) 54 | *this |= (AnalyseCards(start-3) << card) 55 | 56 | card = uint8(50) 57 | *this &= (^(0xF << card)) 58 | *this |= (AnalyseCards(end-3) << card) 59 | } 60 | 61 | func (this *AnalyseCards) Reset() { 62 | this.SetValue(0) 63 | this.SetKind(0) 64 | this.SetStartEnd() 65 | } 66 | 67 | func (this *AnalyseCards) End() uint8 { 68 | return byte((*this>>50 )&0xF) + 3 69 | } 70 | func (this *AnalyseCards) Start() uint8 { 71 | return byte((*this>>46 )&0xF) + 3 72 | } 73 | 74 | func (this *AnalyseCards) GetValue() byte { 75 | return byte((*this >> 59 ) & 0x1F) 76 | } 77 | 78 | func (this *AnalyseCards) SetValue(value byte) { 79 | card := uint8(59) 80 | *this &= (^(0x1F << card)) 81 | *this |= (AnalyseCards(value) << card) 82 | } 83 | 84 | func (this *AnalyseCards) GetKind() uint8 { 85 | return byte((*this >> 54 ) & 0x1F) 86 | } 87 | 88 | func (this *AnalyseCards) SetKind(kind uint8) { 89 | card := uint8(54) 90 | *this &= (^(0x1F << card)) 91 | *this |= (AnalyseCards(kind) << card) 92 | } 93 | 94 | func (this *AnalyseCards) GetWeight() uint8 { 95 | return Weights[this.GetKind()] 96 | } 97 | 98 | func (this *AnalyseCards) ColorRecover(handcards []byte) []byte { 99 | analyseCards := *this 100 | cards := make([]byte, 0, 10) 101 | for _, v := range handcards { 102 | if analyseCards > 0 { 103 | card := GetValue(v) 104 | if analyseCards.Get(card) > 0 { 105 | cards = append(cards, v) 106 | analyseCards.Incr(card, -1) 107 | } 108 | } 109 | } 110 | return cards 111 | } 112 | 113 | func (this *AnalyseCards) Flat() []byte { 114 | cards := make([]byte, 0, this.Len()) 115 | start := this.Start() 116 | end := this.End() 117 | for i := start; i <= end; i++ { 118 | count := this.Get(i) 119 | if count > 0 { 120 | for j := uint8(0); j < count; j++ { 121 | cards = append(cards, i) 122 | } 123 | } 124 | } 125 | return cards 126 | } 127 | func (this *AnalyseCards) Len() uint8 { 128 | var count uint8 129 | start := this.Start() 130 | end := this.End() 131 | for i := start; i <= end; i++ { 132 | count += this.Get(i) 133 | } 134 | return count 135 | } 136 | 137 | func (this *AnalyseCards) Sub(cards AnalyseCards) AnalyseCards { 138 | t := *this 139 | start := cards.Start() 140 | end := cards.End() 141 | for i := start; i <= end; i++ { 142 | count := cards.Get(i) 143 | if count > 0 { 144 | t.Incr(i, -int8(count)) 145 | } 146 | } 147 | t.SetValue(0) 148 | t.SetKind(0) 149 | return t 150 | } 151 | func (this *AnalyseCards) Add(cards AnalyseCards) AnalyseCards { 152 | t := *this 153 | start := cards.Start() 154 | end := cards.End() 155 | for i := start; i <= end; i++ { 156 | count := cards.Get(i) 157 | if count > 0 { 158 | t.Incr(i, int8(count)) 159 | } 160 | } 161 | t.SetValue(0) 162 | t.SetKind(0) 163 | return t 164 | } 165 | 166 | func (this *AnalyseCards) Incr(card byte, num int8) { 167 | card = (card - 3) * 3 168 | count1 := ((*this >> card) & 0x07) 169 | count := int64(count1) + int64(num) 170 | *this &= (^(0x07 << card)) 171 | if count > 0 { 172 | *this |= ((AnalyseCards(count & 0x07) ) << card) 173 | } 174 | this.SetStartEnd() 175 | } 176 | 177 | func (this *AnalyseCards) Padding(count uint8, length uint8, card byte) { 178 | for m := uint8(0); m < count; m++ { 179 | c := card - m 180 | this.Incr(c, int8(length)) 181 | } 182 | this.SetValue(0) 183 | this.SetKind(0) 184 | } 185 | ``` 186 | -------------------------------------------------------------------------------- /src/algorithm/prompt.go: -------------------------------------------------------------------------------- 1 | package algorithm 2 | 3 | func (this *AnalyseCards) Prompt(discards []byte, length uint8) []AnalyseCards { 4 | var cardType AnalyseCards 5 | cardType.Analyse(discards) 6 | result := make([]AnalyseCards, 0, length) 7 | if cardType.GetKind() == WANG_ZHA { // 上手出王炸,直接要不起 8 | return result 9 | } 10 | switch cardType.GetKind() { 11 | case FEI_JI_DAI_DAN: // 飞机带单 12 | if length >= 8 { 13 | this.PromptFeijiDaiDan(cardType.Len(), cardType.GetValue(), &result) 14 | } 15 | case FEI_JI_DAI_DUI: // 飞机带对 16 | if length >= 10 { 17 | this.PromptFeijiDaiDui(cardType.Len(), cardType.GetValue(), &result) 18 | } 19 | case SI_DAI_DAN: // 四带单 20 | if length >= 6 { 21 | this.PromptSiDaiDan(cardType.GetValue(), &result) 22 | } 23 | case SI_DAI_DUI: // 四带对 24 | if length >= 8 { 25 | this.PromptSiDaiDui(cardType.GetValue(), &result) 26 | } 27 | case SAN_SHUN_ZI: // 三顺 28 | if length >= 6 { 29 | this.ShunZiCommon(cardType.Len(), cardType.GetValue(), 3, SAN_SHUN_ZI, &result) 30 | } 31 | case DAN_SHUN_ZI: // 单顺 32 | if length >= 5 { 33 | this.ShunZiCommon(cardType.Len(), cardType.GetValue(), 1, DAN_SHUN_ZI, &result) 34 | } 35 | case LIAN_DUI: // 连对 36 | if length >= 6 { 37 | this.ShunZiCommon(cardType.Len(), cardType.GetValue(), 2, LIAN_DUI, &result) 38 | } 39 | case ZHA_DAN: // 炸弹 40 | if length >= 4 { 41 | this.PromptZhaDan(cardType.GetValue(), &result) 42 | } 43 | case DAN_TIAO: //单条 44 | this.PromptDanTiao(cardType.GetValue(), &result) 45 | case DUI_ZI: // 对子 46 | if length >= 2 { 47 | this.PromptDuiZi(cardType.GetValue(), &result) 48 | } 49 | case SAN_TIAO: // 三条 50 | if length >= 3 { 51 | this.PromptSanTiao(cardType.GetValue(), &result) 52 | } 53 | case SAN_DAI_YI: // 三带单 54 | if length >= 4 { 55 | this.PromptSanDaiDan(cardType.GetValue(), &result) 56 | } 57 | case SAN_DAI_YI_DUI: // 三带对 58 | if length >= 5 { 59 | this.PromptSanDaiDui(cardType.GetValue(), &result) 60 | } 61 | } 62 | // 找手牌的炸弹对抗上手的普通牌 63 | if cardType.GetKind() != ZHA_DAN { 64 | this.PromptZhaDan(cardType.GetValue(), &result) 65 | } 66 | // 王炸 67 | this.PromptWangZha(&result) 68 | return result 69 | } 70 | 71 | func (this *AnalyseCards) PromptSanDaiDui(value byte, cardTypes *[]AnalyseCards) { 72 | if value == TWO { 73 | return 74 | } 75 | 76 | if value == 0 { 77 | value = byte(THREE - 1) 78 | } 79 | 80 | end:= this.End() 81 | start:= this.Start() 82 | if end > TWO{ 83 | end =TWO 84 | } 85 | 86 | for i := end; i > value; i-- { 87 | if this.Get(i) < 3 { 88 | continue 89 | } 90 | 91 | for j := start; j <= end; j++ { 92 | if j != i { 93 | if this.Get(j) > 1 { 94 | var anCards AnalyseCards 95 | anCards.Incr(i, 3) 96 | anCards.Incr(j, 2) 97 | anCards.SetKind(SAN_DAI_YI_DUI) 98 | anCards.SetValue(i) 99 | *cardTypes = append(*cardTypes, anCards) 100 | break 101 | } 102 | } 103 | } 104 | } 105 | return 106 | } 107 | func (this *AnalyseCards) PromptSanDaiDan(value byte, cardTypes *[]AnalyseCards) { 108 | if value == TWO { 109 | return 110 | } 111 | if value == 0 { 112 | value = byte(THREE - 1) 113 | } 114 | end:= this.End() 115 | start:= this.Start() 116 | if end > TWO{ 117 | end =TWO 118 | } 119 | for i := end; i > value; i-- { 120 | if this.Get(i) < 3 { 121 | continue 122 | } 123 | for j := start; j <= end; j++ { 124 | if j != i { 125 | if this.Get(j) > 0 { 126 | var anCards AnalyseCards 127 | anCards.Incr(i, 3) 128 | anCards.Incr(j, 1) 129 | anCards.SetKind(SAN_DAI_YI) 130 | anCards.SetValue(i) 131 | *cardTypes = append(*cardTypes, anCards) 132 | break 133 | } 134 | } 135 | } 136 | } 137 | return 138 | } 139 | func (this *AnalyseCards) PromptSanTiao(value byte, cardTypes *[]AnalyseCards) { 140 | if value == TWO { 141 | return 142 | } 143 | if value == 0 { 144 | value = byte(THREE - 1) 145 | } 146 | 147 | end:= this.End() 148 | if end > TWO{ 149 | end =TWO 150 | } 151 | for i := end; i > value; i-- { 152 | if this.Get(i) < 3 { 153 | continue 154 | } 155 | var anCards AnalyseCards 156 | anCards.Incr(i, 3) 157 | 158 | anCards.SetKind(SAN_TIAO) 159 | anCards.SetValue(i) 160 | *cardTypes = append(*cardTypes, anCards) 161 | } 162 | return 163 | } 164 | func (this *AnalyseCards) PromptDuiZi(value byte, cardTypes *[]AnalyseCards) { 165 | if value == TWO { 166 | return 167 | } 168 | if value == 0 { 169 | value = byte(THREE - 1) 170 | } 171 | end:= this.End() 172 | if end > TWO{ 173 | end =TWO 174 | } 175 | for i := end; i > value; i-- { 176 | if this.Get(i) > 1 { 177 | var anCards AnalyseCards 178 | anCards.Incr(i, 2) 179 | anCards.SetKind(DUI_ZI) 180 | anCards.SetValue(i) 181 | *cardTypes = append(*cardTypes, anCards) 182 | } 183 | } 184 | return 185 | } 186 | func (this *AnalyseCards) PromptDanTiao(value byte, cardTypes *[]AnalyseCards) { 187 | if value == DA_WANG { 188 | return 189 | } 190 | if value == 0 { 191 | value = byte(THREE - 1) 192 | } 193 | 194 | end:= this.End() 195 | 196 | for i := end; i > value; i-- { 197 | if this.Get(i) > 0 { 198 | var anCards AnalyseCards 199 | anCards.Incr(i, 1) 200 | anCards.SetKind(DAN_TIAO) 201 | anCards.SetValue(i) 202 | *cardTypes = append(*cardTypes, anCards) 203 | } 204 | } 205 | return 206 | } 207 | 208 | func (this *AnalyseCards) ShunZiCommon(length uint8, value byte, leng uint8, kind uint8, cardTypes *[]AnalyseCards) { 209 | discardsLength := length / leng 210 | 211 | end:= this.End() 212 | //start:= this.Start() 213 | s:= end 214 | if s > A{ 215 | s = A 216 | } 217 | 218 | for i := s; i > value; i-- { 219 | for k := uint8(0); k < discardsLength; k++ { 220 | if this.Get(i-k) < leng { 221 | goto BR 222 | } 223 | if k+1 == discardsLength { 224 | var anCards AnalyseCards 225 | anCards.Padding(discardsLength, leng, i) 226 | anCards.SetKind(kind) 227 | anCards.SetValue(i) 228 | *cardTypes = append(*cardTypes, anCards) 229 | goto BR 230 | } 231 | } 232 | BR: 233 | } 234 | return 235 | } 236 | 237 | func (this *AnalyseCards) PromptSiDaiDan(value byte, cardTypes *[]AnalyseCards) { 238 | if value == TWO { 239 | return 240 | } 241 | if value == 0 { 242 | value = byte(THREE - 1) 243 | } 244 | 245 | end:= this.End() 246 | start:= this.Start() 247 | s:= end 248 | if s > TWO{ 249 | s = TWO 250 | } 251 | 252 | for i := s; i > value; i-- { 253 | var lastCards byte 254 | if this.Get(i) != 4 { 255 | continue 256 | } 257 | 258 | for j := start; j <= s; j++ { 259 | if j != i { 260 | if this.Get(j) > 0 { 261 | if lastCards == 0 { 262 | lastCards = j 263 | continue 264 | } 265 | var anCards AnalyseCards 266 | anCards.Incr(i, 4) 267 | anCards.Incr(lastCards, 1) 268 | anCards.Incr(j, 1) 269 | anCards.SetKind(SI_DAI_DAN) 270 | anCards.SetValue(i) 271 | *cardTypes = append(*cardTypes, anCards) 272 | break 273 | } 274 | } 275 | } 276 | } 277 | return 278 | } 279 | func (this *AnalyseCards) PromptSiDaiDui(value byte, cardTypes *[]AnalyseCards) { 280 | if value == TWO { 281 | return 282 | } 283 | if value == 0 { 284 | value = byte(THREE - 1) 285 | } 286 | end:= this.End() 287 | start:= this.Start() 288 | s:= end 289 | if s > TWO{ 290 | s = TWO 291 | } 292 | for i := s; i > value; i-- { 293 | count := uint8(0) 294 | var lastCards byte 295 | if this.Get(i) != 4 { 296 | continue 297 | } 298 | 299 | for j := start; j <= s; j++ { 300 | if j != i { 301 | if this.Get(j) > 1 { 302 | count ++ 303 | if lastCards == 0 { 304 | lastCards = j 305 | } 306 | } 307 | if count == 2 { 308 | var anCards AnalyseCards 309 | anCards.Incr(i, 4) 310 | anCards.Incr(lastCards, 2) 311 | anCards.Incr(j, 2) 312 | 313 | anCards.SetKind(SI_DAI_DUI) 314 | anCards.SetValue(i) 315 | *cardTypes = append(*cardTypes, anCards) 316 | break 317 | } 318 | } 319 | } 320 | } 321 | return 322 | } 323 | 324 | func (this *AnalyseCards) PromptFeijiDaiDan(length uint8, value byte, cardTypes *[]AnalyseCards) { 325 | if value == A { 326 | return 327 | } 328 | start:= this.Start() 329 | end:= this.End() 330 | discardsLength := length / 4 331 | s:= end 332 | if s > A{ 333 | s = A 334 | } 335 | for i := A; i > value; i-- { 336 | if this.Get(i) == 0 { 337 | continue 338 | } 339 | 340 | 341 | if end>TWO{ 342 | end = TWO 343 | } 344 | count := uint8(0) 345 | var anCards AnalyseCards 346 | for k := uint8(0); k < discardsLength; k++ { 347 | if this.Get(i-k) < 3 { 348 | goto BR 349 | } 350 | } 351 | 352 | for j := start; j <= end; j++ { 353 | c := this.Get(j) 354 | if c > 0 { 355 | if c <= 3 && j <= i && j > i-discardsLength { 356 | continue 357 | } 358 | anCards.Incr(j, 1) 359 | count ++ 360 | if count == discardsLength { 361 | anCards.Padding(discardsLength, 3, i) 362 | 363 | anCards.SetKind(FEI_JI_DAI_DAN) 364 | anCards.SetValue(i) 365 | *cardTypes = append(*cardTypes, anCards) 366 | goto BR 367 | } 368 | } 369 | } 370 | BR: 371 | } 372 | return 373 | } 374 | func (this *AnalyseCards) PromptZhaDan(value byte, cardTypes *[]AnalyseCards) { 375 | if value == TWO { 376 | return 377 | } 378 | if value == 0 { 379 | value = byte(THREE - 1) 380 | } 381 | end:= this.End() 382 | if end > TWO{ 383 | end = TWO 384 | } 385 | for i := end; i > value; i-- { 386 | if this.Get(i) == 4 { 387 | var anCards AnalyseCards 388 | anCards.Incr(i, 4) 389 | 390 | anCards.SetKind(ZHA_DAN) 391 | anCards.SetValue(i) 392 | *cardTypes = append(*cardTypes, anCards) 393 | } 394 | } 395 | return 396 | } 397 | func (this *AnalyseCards) PromptWangZha(cardTypes *[]AnalyseCards) { 398 | if this.Get(DA_WANG) > 0 && this.Get(XIAO_WANG) > 0 { 399 | var anCards AnalyseCards 400 | anCards.Incr(DA_WANG, 1) 401 | anCards.Incr(XIAO_WANG, 1) 402 | anCards.SetKind(WANG_ZHA) 403 | anCards.SetValue(DA_WANG) 404 | *cardTypes = append(*cardTypes, anCards) 405 | } 406 | return 407 | } 408 | 409 | func (this *AnalyseCards) PromptFeijiDaiDui(length uint8, value byte, cardTypes *[]AnalyseCards) { 410 | if value == A { 411 | return 412 | } 413 | end:= this.End() 414 | start:= this.Start() 415 | s:= end 416 | if s > A{ 417 | s = A 418 | } 419 | discardsLength := length / 5 420 | for i := s; i > value; i-- { 421 | if this.Get(i) == 0 { 422 | continue 423 | } 424 | if this.Get(i) == 1 { 425 | return 426 | } 427 | count := uint8(0) 428 | var anCards AnalyseCards = 0 429 | e := end 430 | if e > TWO{ 431 | e = TWO 432 | } 433 | 434 | for k := uint8(0); k < discardsLength; k++ { 435 | if this.Get(i-k) < 3 { 436 | goto BR 437 | } 438 | } 439 | 440 | for j := start; j <= e; j++ { 441 | if this.Get(j) == 0 { 442 | continue 443 | } 444 | if j > i || j <= i-discardsLength { 445 | if this.Get(j) == 4 { 446 | anCards.Incr(j, 4) 447 | count += 2 448 | } else if this.Get(j) == 2 { 449 | anCards.Incr(j, 2) 450 | count ++ 451 | } 452 | if count == discardsLength { 453 | anCards.Padding(discardsLength, 3, i) 454 | anCards.SetKind(FEI_JI_DAI_DUI) 455 | anCards.SetValue(i) 456 | *cardTypes = append(*cardTypes, anCards) 457 | goto BR 458 | } 459 | } 460 | } 461 | BR: 462 | } 463 | return 464 | } 465 | -------------------------------------------------------------------------------- /src/algorithm/prompt_test.go: -------------------------------------------------------------------------------- 1 | package algorithm 2 | 3 | import "testing" 4 | 5 | func TestPromptFeijiDaiDui(t *testing.T) { 6 | 7 | //handcards := []byte{0x03, 0x05, 0x15, 0x25, 0x35, 0x06, 0x16, 0x26, 0x36, 0x08, 0x38, 0x27, 0x18, 0x28, 0x2D} 8 | //discards := []byte{0x23, 0x13, 0x03, 0x04, 0x24, 0x14, 0x29, 0x19, 0x29, 0x19} 9 | //cardType := SelectCards(handcards, discards) 10 | // 11 | //t.Logf("%#+v 飞机带对 %#+v %#+v ", yapaitest(handcards, discards, 4, cardType), handcards, discards) 12 | // 13 | 14 | handcards := []byte{0x06, 0x16, 0x26, 0x09, 0x19, 0x29, 0x27, 0x37, 0x07, 0x18, 0x29, 0x08, 0x38, 0x2D, 0x3D} 15 | discards := []byte{0x23, 0x13, 0x03, 0x04, 0x24, 0x14, 0x15, 0x25, 0x35, 0x2e, 0x1e, 0x2e, 0x1e, 0x2a, 0x1a} 16 | ty := &Cards{} 17 | 18 | ty.AnalyseUnSort(handcards) 19 | 20 | cardTypes := ty.Prompt(discards) 21 | 22 | for _, v := range cardTypes { 23 | t.Logf("%#+v 飞机带对 ", v.Cards) 24 | /*for i:= THREE;i<=DA_WANG;i++{ 25 | t.Logf("%#v %v ",i,v.analyseCards.Get(i)) 26 | }*/ 27 | } 28 | 29 | t.Logf("%#+v 飞机带对 %#+v %#+v ", yapaitest(handcards, discards, 2, cardTypes), handcards, discards) 30 | } 31 | 32 | func TestPromptFeijiDaiDan(t *testing.T) { 33 | 34 | handcards := []byte{0x03, 0x05, 0x15, 0x25, 0x35, 0x06, 0x16, 0x26, 0x36, 0x18, 0x38, 0x27, 0x08, 0x28, 0x2D} 35 | discards := []byte{0x23, 0x13, 0x03, 0x33, 0x24, 0x14, 0x04, 0x19} 36 | ty := &Cards{} 37 | 38 | ty.AnalyseUnSort(handcards) 39 | 40 | cardTypes := ty.Prompt(discards) 41 | for _, v := range cardTypes { 42 | t.Logf("%#+v 飞机带单 ", v.Cards) 43 | } 44 | 45 | t.Logf("%#+v 飞机带单 %#+v %#+v ", yapaitest(handcards, discards, 4, cardTypes), handcards, discards) 46 | 47 | handcards = []byte{0x02, 0x15, 0x25, 0x35, 0x06, 0x16, 0x26, 0x36} 48 | discards = []byte{0x23, 0x13, 0x03, 0x33, 0x24, 0x14, 0x04, 0x19} 49 | ty = &Cards{} 50 | 51 | ty.AnalyseUnSort(handcards) 52 | 53 | cardTypes = ty.Prompt(discards) 54 | for _, v := range cardTypes { 55 | t.Logf("%#+v 飞机带单 ", v.Cards) 56 | } 57 | 58 | t.Logf("%#+v 飞机带单 %#+v %#+v ", yapaitest(handcards, discards, 2, cardTypes), handcards, discards) 59 | } 60 | 61 | func TestPromptSiDaiDui(t *testing.T) { 62 | handcards := []byte{0x03, 0x05, 0x15, 0x25, 0x35, 0x06, 0x16, 0x26, 0x36, 0x18, 0x08, 0x27, 0x38, 0x28, 0x2D} 63 | discards := []byte{0x23, 0x13, 0x03, 0x33, 0x24, 0x14, 0x29, 0x19} 64 | ty := &Cards{} 65 | ty.AnalyseUnSort(handcards) 66 | /*cardTypes := ty.Prompt(discards) 67 | for _,v:=range cardTypes{ 68 | t.Logf("%#+v 四带对 ",v.Cards) 69 | } 70 | for k,v:=range ty.analyseCards{ 71 | t.Log(len(v),k,v) 72 | } 73 | t.Logf("%#+v 四带对 %#+v %#+v ", yapaitest(handcards, discards, 6, cardTypes), handcards, discards)*/ 74 | 75 | handcards = []byte{0x18, 0x8, 0x38, 0x28, 0x5, 0x15, 0x6, 0x16} 76 | discards = []byte{0x23, 0x13, 0x3, 0x33, 0x24, 0x14, 0x29, 0x19} 77 | ty = &Cards{} 78 | 79 | ty.AnalyseUnSort(handcards) 80 | 81 | cardTypes := ty.Prompt(discards) 82 | 83 | for _, v := range cardTypes { 84 | t.Logf("%#+v 四带对 %#+v", v.Cards, v.Kind) 85 | } 86 | 87 | t.Logf("%#+v 四带对 %#+v %#+v ", yapaitest(handcards, discards, 2, cardTypes), handcards, discards) 88 | } 89 | 90 | func TestPromptSiDaiDan(t *testing.T) { 91 | 92 | handcards := []byte{0x03, 0x05, 0x15, 0x25, 0x35, 0x06, 0x16, 0x26, 0x36, 0x18, 0x38, 0x27, 0x08, 0x28, 0x2D} 93 | discards := []byte{0x23, 0x13, 0x03, 0x33, 0x24, 0x17} 94 | ty := &Cards{} 95 | 96 | ty.AnalyseUnSort(handcards) 97 | 98 | cardTypes := ty.Prompt(discards) 99 | for _, v := range cardTypes { 100 | t.Logf("%#+v 四带单 ", v.Cards) 101 | } 102 | 103 | t.Logf("%#+v 四带单 %#+v %#+v ", yapaitest(handcards, discards, 6, cardTypes), handcards, discards) 104 | } 105 | 106 | func TestPromptSanShun(t *testing.T) { 107 | 108 | handcards := []byte{0x05, 0x15, 0x25, 0x16, 0x26, 0x36, 0x18, 0x27, 0x18, 0x28, 0x2D} 109 | discards := []byte{0x23, 0x13, 0x03, 0x24, 0x14, 0x04} 110 | ty := &Cards{} 111 | 112 | ty.AnalyseUnSort(handcards) 113 | 114 | cardTypes := ty.Prompt(discards) 115 | for _, v := range cardTypes { 116 | t.Logf("%#+v 三顺 ", v.Cards) 117 | } 118 | 119 | t.Logf("%#+v 三顺 %#+v %#+v ", yapaitest(handcards, discards, 1, cardTypes), handcards, discards) 120 | } 121 | 122 | func TestPromptPromptDanTiao(t *testing.T) { 123 | handcards := []byte{0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0x02, 0x12, 0x22, 0x32, 0x9, 0x19, 0x23} 124 | 125 | var an AnalyseCards 126 | an.Set(handcards) 127 | 128 | //t.Logf("%b", an) 129 | 130 | an.SetValue(17) 131 | an.SetKind(14) 132 | //t.Logf("%b", an) 133 | //t.Logf("%v %v", an.GetKind(), an.GetValue()) 134 | arr := make([]AnalyseCards, 0) 135 | an.PromptDanTiao(0x4, &arr) 136 | t.Logf("%v %b", len(arr) == 4, an) 137 | 138 | for _, v := range arr { 139 | t.Logf("%v %#v", v.GetKind(), v.GetValue()) 140 | } 141 | 142 | } 143 | func TestPromptLianDui(t *testing.T) { 144 | 145 | handcards := []byte{0x25, 0x25, 0x26, 0x26, 0x17, 0x27, 0x18, 0x28, 0x2D} 146 | discards := []byte{0x04, 0x14, 0x05, 0x15, 0x06, 0x16} 147 | ty := &Cards{} 148 | 149 | ty.AnalyseUnSort(handcards) 150 | 151 | cardTypes := ty.Prompt(discards) 152 | for _, v := range cardTypes { 153 | t.Logf("%#+v 连对 ", v.Cards) 154 | } 155 | 156 | t.Logf("%#+v 连对 %#+v %#+v ", yapaitest(handcards, discards, 2, cardTypes), handcards, discards) 157 | 158 | handcards = []byte{0x15, 0x05, 0x16, 0x26, 0x18, 0x27, 0x08, 0x28, 0x2D} 159 | discards = []byte{0x04, 0x14, 0x05, 0x15, 0x06, 0x16} 160 | ty = &Cards{} 161 | 162 | ty.AnalyseUnSort(handcards) 163 | 164 | cardTypes = ty.Prompt(discards) 165 | for _, v := range cardTypes { 166 | t.Logf("%#+v 连对 ", v.Cards) 167 | } 168 | 169 | rel := yapaitest(handcards, discards, 0, cardTypes) 170 | t.Logf("%#+v 连对 %#+v %#+v ", rel, handcards, discards) 171 | } 172 | 173 | func TestPromptShunzi(t *testing.T) { 174 | 175 | handcards := []byte{0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x2D} 176 | discards := []byte{0x04, 0x05, 0x06, 0x07, 0x08} 177 | ty := &Cards{} 178 | 179 | ty.AnalyseUnSort(handcards) 180 | 181 | cardTypes := ty.Prompt(discards) 182 | for _, v := range cardTypes { 183 | t.Logf("%#+v 顺子 ", v.Cards) 184 | } 185 | rel := yapaitest(handcards, discards, 5, cardTypes) 186 | t.Logf("%#+v 顺子 %#+v %#+v ", rel, handcards, discards) 187 | 188 | handcards = []byte{0x03, 0x04, 0x25, 0x15, 0x16, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x2D} 189 | discards = []byte{0x03, 0x04, 0x05, 0x06, 0x07, 0x08} 190 | ty = &Cards{} 191 | 192 | ty.AnalyseUnSort(handcards) 193 | 194 | cardTypes = ty.Prompt(discards) 195 | 196 | for _, v := range cardTypes { 197 | t.Logf("%#+v 顺子 ", v.Cards) 198 | } 199 | rel = yapaitest(handcards, discards, 1, cardTypes) 200 | t.Logf("%#+v 顺子 %#+v %#+v ", rel, handcards, discards) 201 | 202 | handcards = []byte{0x03, 0x04, 0x15, 0x25, 0x16, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x2D} 203 | discards = []byte{0x03, 0x04, 0x05, 0x06, 0x07} 204 | ty = &Cards{} 205 | 206 | ty.AnalyseUnSort(handcards) 207 | 208 | cardTypes = ty.Prompt(discards) 209 | 210 | for _, v := range cardTypes { 211 | t.Logf("%#+v 顺子 ", v.Cards) 212 | } 213 | rel = yapaitest(handcards, discards, 2, cardTypes) 214 | t.Logf("%#+v 顺子 %#+v %#+v ", rel, handcards, discards) 215 | } 216 | 217 | func TestPrompt(t *testing.T) { 218 | handcards := []byte{0xEF, 0xFF, 0x02, 0x12, 0x22, 0x32} 219 | discards := []byte{0x04, 0x14} 220 | ty := &Cards{Cards: handcards} 221 | ty.AnalyseUnSort(handcards) 222 | cardTypes := ty.Prompt(discards) 223 | rel := yapaitest(handcards, discards, 3, cardTypes) 224 | t.Logf("%#+v 对子 %#+v %#+v ", rel, handcards, discards) 225 | 226 | handcards = []byte{0xEF, 0xFF, 0x02, 0x12, 0x22, 0x32} 227 | discards = []byte{0x04, 0x14, 0x24, 0x34} 228 | ty = &Cards{Cards: handcards} 229 | ty.AnalyseUnSort(handcards) 230 | cardTypes = ty.Prompt(discards) 231 | rel = yapaitest(handcards, discards, 2, cardTypes) 232 | t.Logf("%#+v 炸弹 %#+v %#+v ", rel, handcards, discards) 233 | 234 | handcards = []byte{0xEF, 0xFF, 0x02, 0x12, 0x22, 0x32, 0x09, 0x19, 0x29, 0x39} 235 | discards = []byte{0x04, 0x14, 0x24, 0x34} 236 | ty = &Cards{} 237 | ty.AnalyseUnSort(handcards) 238 | cardTypes = ty.Prompt(discards) 239 | rel = yapaitest(handcards, discards, 3, cardTypes) 240 | t.Logf("%#+v 炸弹 %#+v %#+v %+v ", rel, handcards, discards, len(cardTypes)) 241 | 242 | handcards = []byte{0xEF, 0xFF, 0x02, 0x12, 0x22, 0x32} 243 | discards = []byte{0x04, 0x14, 0x24} 244 | ty = &Cards{Cards: handcards} 245 | ty.AnalyseUnSort(handcards) 246 | cardTypes = ty.Prompt(discards) 247 | rel = yapaitest(handcards, discards, 3, cardTypes) 248 | t.Logf("%#+v 三条 %#+v %#+v ", rel, handcards, discards) 249 | 250 | handcards = []byte{0xEF, 0xFF, 0x02, 0x12, 0x22, 0x32, 0x9, 0x19, 0x29} 251 | discards = []byte{0x04, 0x14} 252 | ty = &Cards{Cards: handcards} 253 | ty.AnalyseUnSort(handcards) 254 | cardTypes = ty.Prompt(discards) 255 | rel = yapaitest(handcards, discards, 4, cardTypes) 256 | 257 | for _, v := range cardTypes { 258 | t.Logf("%#+v 对子 ", v.Cards) 259 | } 260 | 261 | t.Logf("%#+v 对子 %#+v %#+v ", rel, handcards, discards) 262 | 263 | handcards = []byte{0xEF, 0xFF, 0x02, 0x12, 0x22, 0x32, 0x9, 0x19, 0x29} 264 | discards = []byte{0x04} 265 | ty = &Cards{} 266 | ty.AnalyseUnSort(handcards) 267 | cardTypes = ty.Prompt(discards) 268 | 269 | for _, v := range cardTypes { 270 | t.Logf("cards: %#v %#v", v.Cards, v.Kind) 271 | } 272 | 273 | rel = yapaitest(handcards, discards, 6, cardTypes) 274 | t.Logf("%#+v 单条 %#+v %#+v ", rel, handcards, discards) 275 | 276 | handcards = []byte{0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x2D} 277 | discards = []byte{0x04, 0x05, 0x06, 0x07, 0x08} 278 | ty = &Cards{} 279 | ty.AnalyseUnSort(handcards) 280 | cardTypes = ty.Prompt(discards) 281 | rel = yapaitest(handcards, discards, 5, cardTypes) 282 | t.Logf("%#+v 顺子 %#+v %#+v ", rel, handcards, discards) 283 | } 284 | 285 | func TestPromptSanDaiDan(t *testing.T) { 286 | handcards := []byte{0x03, 0x05, 0x15, 0x25, 0x16, 0x26, 0x36, 0x18, 0x27, 0x28, 0x08, 0x2D} 287 | discards := []byte{0x23, 0x13, 0x03, 0x24} 288 | 289 | ty := &Cards{} 290 | ty.AnalyseUnSort(handcards) 291 | cardTypes := ty.Prompt(discards) 292 | 293 | for _, v := range cardTypes { 294 | t.Logf("%#+v 三带单 ", v.Cards) 295 | } 296 | rel := yapaitest(handcards, discards, 3, cardTypes) 297 | t.Logf("%#+v 三带单 %#+v %#+v ", rel, handcards, discards) 298 | } 299 | 300 | func TestPrompSanDaiDui(t *testing.T) { 301 | 302 | handcards := []byte{0x03, 0x05, 0x15, 0x25, 0x16, 0x26, 0x36, 0x18, 0x27, 0x08, 0x28, 0x2D} 303 | discards := []byte{0x23, 0x13, 0x03, 0x24, 0x24} 304 | 305 | ty := &Cards{} 306 | ty.AnalyseUnSort(handcards) 307 | cardTypes := ty.Prompt(discards) 308 | 309 | for _, v := range cardTypes { 310 | t.Logf("%#+v 三带对 ", v.Cards) 311 | } 312 | 313 | rel := yapaitest(handcards, discards, 3, cardTypes) 314 | t.Logf("%#+v 三带对 %#+v %#+v ", rel, handcards, discards) 315 | } 316 | 317 | func TestPrompDanTiao4(t *testing.T) { 318 | handcards := []byte{0xEF, 0xFF, 0x02, 0x12, 0x22, 0x32, 0x9, 0x19, 0x29} 319 | discards := []byte{0x04} 320 | ty := &Cards{} 321 | ty.AnalyseUnSort(handcards) 322 | cardTypes := ty.Prompt(discards) 323 | 324 | for _, v := range cardTypes { 325 | t.Logf("cards: %#v %v", v.Cards, v.Kind) 326 | } 327 | 328 | rel := yapaitest(handcards, discards, 6, cardTypes) 329 | t.Logf("%#+v 单条 %#+v %#+v ", rel, handcards, discards) 330 | } 331 | func TestPrompDanTiao(t *testing.T) { 332 | //handcards := []byte{0xEF, 0xFF, 0x02, 0x12, 0x22, 0x32, 0x9, 0x19, 0x29} 333 | handcards := []byte{0xEF, 0xFF, 0x0a, 0x1a, 0x2a, 0x3a, 0x9, 0x19, 0x29} 334 | discards := []byte{0x04} 335 | ty := &Cards{} 336 | ty.AnalyseUnSort(handcards) 337 | cardTypes := ty.Prompt(discards) 338 | 339 | for _, v := range cardTypes { 340 | t.Logf("cards: %#v %v", v.Cards, v.Kind) 341 | } 342 | 343 | } 344 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /src/algorithm/follow_test.go: -------------------------------------------------------------------------------- 1 | package algorithm 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | 8 | 9 | func TestIsFollowSanTiao(t *testing.T) { 10 | // 三条 11 | var an AnalyseCards 12 | an.Analyse([]byte{0x02, 0x12, 0x22}) 13 | an.judge3Same() 14 | t.Logf("三条 %v,%v,%v", an.GetKind() == SAN_TIAO, an.GetWeight() == 1, an.GetValue() == GetValue(0x02)) 15 | 16 | } 17 | func TestIsFollow(t *testing.T) { 18 | //cardType := &Cards{} 19 | var an AnalyseCards 20 | an.Analyse([]byte{0xFF, 0xEF}) 21 | t.Logf("能否跟上上手牌 %v ", an.Follow([]byte{0x02, 0x12, 0x22, 0x32}) == true) 22 | 23 | 24 | an.Analyse([]byte{0x02, 0x12, 0x22, 0x32}) 25 | t.Logf("能否跟上上手牌 %v ", an.Follow([]byte{0xFF, 0xEF}) == false) 26 | 27 | 28 | an.Analyse([]byte{0x03, 0x13, 0x23, 0x33}) 29 | 30 | t.Logf("能否跟上上手牌 %v ", an.Follow([]byte{0x02, 0x12, 0x22, 0x32}) == false) 31 | 32 | 33 | an.Analyse([]byte{0x04, 0x05, 0x06, 0x07, 0x08}) 34 | t.Logf("能否跟上上手牌 %v ", an.Follow([]byte{0x03, 0x04, 0x05, 0x06, 0x07}) == true) 35 | 36 | } 37 | 38 | 39 | // 顺子 40 | func TestAnalyseShunzi(t *testing.T) { 41 | cardType := BuildCards([]byte{0x0b, 0x0c, 0x2d, 0x1e, 0xFF}) 42 | t.Logf("顺子 %v,%v,%v %v,%v %v", cardType.Kind() != DAN_SHUN_ZI, cardType.Weight() == 0, cardType.Value() == 0, cardType.Kind(), cardType.Weight(), cardType.Value()) 43 | 44 | //t.Log(a,b,c, ConvertValue([]byte{0x0b, 0x0c, 0x2d, 0x1e, 0xFF})) 45 | cardType = BuildCards([]byte{0x02, 0x03, 0x24, 0x15, 0x36}) 46 | t.Logf("顺子 %v,%v,%v", cardType.Kind() != DAN_SHUN_ZI, cardType.Weight() == 0, cardType.Value() == 0) 47 | 48 | cardType = BuildCards([]byte{0x0b, 0x0c, 0x2d, 0x1e, 0x02}) 49 | 50 | t.Logf("顺子 %v,%v,%v", cardType.Kind() != DAN_SHUN_ZI, cardType.Weight() == 0, cardType.Value() == 0) 51 | } 52 | 53 | // 三顺 54 | func TestAnalyseSanshun(t *testing.T) { 55 | cardType := BuildCards([]byte{0x12, 0x02, 0x12, 0x28, 0x08, 0x18}) 56 | t.Logf("三顺 %v,%v,%v", cardType.Kind() != SAN_SHUN_ZI, cardType.Weight() == 0, cardType.Value() == 0) 57 | 58 | cardType = BuildCards([]byte{0x12, 0x02, 0x12, 0x23, 0x03, 0x13}) 59 | t.Logf("三顺 %v,%v,%v", cardType.Kind() != SAN_SHUN_ZI, cardType.Weight() == 0, cardType.Value() == 0) 60 | 61 | cardType = BuildCards([]byte{0x23, 0x03, 0x13, 0x14, 0x04, 0x14}) 62 | t.Logf("三顺 %v,%v,%v", cardType.Kind() == SAN_SHUN_ZI, cardType.Weight() == 1, cardType.Value() == 4) 63 | 64 | cardType = BuildCards([]byte{0x23, 0x03, 0x14, 0x15, 0x05, 0x16}) 65 | t.Logf("三顺 %v,%v,%v", cardType.Kind() != SAN_SHUN_ZI, cardType.Weight() == 0, cardType.Value() == 0) 66 | 67 | cardType = BuildCards([]byte{0x2d, 0x0d, 0x1d, 0x1e, 0x0e, 0x1e}) 68 | t.Logf("三顺 %v,%v,%v", cardType.Kind() == SAN_SHUN_ZI, cardType.Weight() == 1, cardType.Value() == 0xe) 69 | 70 | cardType = BuildCards([]byte{0x1e, 0x1e, 0x1e, 0x02, 0x02, 0x02}) 71 | t.Logf("三顺 %v,%v,%v", cardType.Kind() != SAN_SHUN_ZI, cardType.Weight() == 0, cardType.Value() == 0) 72 | 73 | cardType = BuildCards([]byte{0x14, 0x24, 0x04, 0x05, 0x15, 0x25, 0x03, 0x13, 0x23, 0x06, 0x16, 0x26}) 74 | t.Logf("三顺 %v,%v,%v", cardType.Kind() == SAN_SHUN_ZI, cardType.Weight() == 1, cardType.Value() == 6) 75 | } 76 | 77 | //飞机带两个 78 | func TestAnalyseFeijidaidan(t *testing.T) { 79 | 80 | cardType := BuildCards([]byte{0x02, 0x12, 0x22, 0x05, 0x15, 0x25, 0x26, 0x27}) 81 | t.Logf("飞机带两个 %v,%v,%v", cardType.Kind() != FEI_JI_DAI_DAN, cardType.Weight() == 0, cardType.Value() == 0) 82 | 83 | cardType = BuildCards([]byte{0x02, 0x12, 0x22, 0x03, 0x13, 0x23, 0x26, 0x27}) 84 | t.Logf("飞机带两个 %v,%v,%v", cardType.Kind() != FEI_JI_DAI_DAN, cardType.Weight() == 0, cardType.Value() == 0) 85 | 86 | cardType = BuildCards([]byte{0x04, 0x14, 0x24, 0x05, 0x15, 0x25, 0x26, 0x27}) 87 | t.Logf("飞机带两个 %v,%v,%v", cardType.Kind() == FEI_JI_DAI_DAN, cardType.Weight() == 1, cardType.Value() == 0x5) 88 | 89 | cardType = BuildCards([]byte{0x1e, 0x1e, 0x1e, 0x02, 0x02, 0x02, 0x27, 0x27}) 90 | t.Logf("飞机带两个 %v,%v,%v", cardType.Kind() != FEI_JI_DAI_DAN, cardType.Weight() == 0, cardType.Value() == 0) 91 | 92 | cardType = BuildCards([]byte{0x1e, 0x0e, 0x2e, 0x3e, 0x0d, 0x0d, 0x0d, 0x0d}) 93 | t.Logf("飞机带两个 %v,%v,%v", cardType.Kind() == FEI_JI_DAI_DAN, cardType.Weight() == 1, cardType.Value() == 0x0e) 94 | 95 | cardType = BuildCards([]byte{0x14, 0x24, 0x04, 0x05, 0x15, 0x25, 0x03, 0x13, 0x23, 0x06, 0x16, 0x26}) 96 | t.Logf("飞机带两个 %v,%v,%v", cardType.Kind() != FEI_JI_DAI_DAN, cardType.Weight() == 1, cardType.Value() == 6) 97 | } 98 | 99 | //飞机带对 100 | func TestAnalyseFeijidaidui(t *testing.T) { 101 | //飞机带对 102 | cardType := BuildCards([]byte{0x03, 0x13, 0x23, 0x05, 0x15, 0x25, 0x26, 0x36, 0x27, 0x37}) 103 | t.Logf("飞机带对 %v,%v,%v", cardType.Kind() != FEI_JI_DAI_DUI, cardType.Weight() == 0, cardType.Value() == 0) 104 | 105 | //飞机带对 106 | cardType = BuildCards([]byte{0x04, 0x14, 0x24, 0x05, 0x15, 0x25, 0x26, 0x36, 0x27, 0x37}) 107 | t.Logf("飞机带对 %v,%v,%v", cardType.Kind() == FEI_JI_DAI_DUI, cardType.Weight() == 1, cardType.Value() == 0x5) 108 | 109 | //飞机带对 110 | cardType = BuildCards([]byte{0x02, 0x12, 0x22, 0x03, 0x13, 0x23, 0x26, 0x36, 0x27, 0x37}) 111 | t.Logf("飞机带对 %v,%v,%v", cardType.Kind() != FEI_JI_DAI_DUI, cardType.Weight() == 0, cardType.Value() == 0) 112 | 113 | //飞机带对 114 | cardType = BuildCards([]byte{0x04, 0x14, 0x24, 0x05, 0x15, 0x25, 0x26, 0x36, 0xEF, 0xFF}) 115 | t.Logf("飞机带对 %v,%v,%v", cardType.Kind() != FEI_JI_DAI_DUI, cardType.Weight() == 0, cardType.Value() == 0) 116 | 117 | //飞机带对 118 | cardType = BuildCards([]byte{0x02, 0x02, 0x03, 0x13, 0x23, 0x04, 0x14, 0x24, 0x05, 0x15, 0x25, 0x26, 0x36, 0x27, 0x37}) 119 | t.Logf("飞机带对 %v,%v,%v", cardType.Kind() == FEI_JI_DAI_DUI, cardType.Weight() == 1, cardType.Value() == 5) 120 | 121 | cardType = BuildCards([]byte{0x1e, 0x1e, 0x1e, 0x02, 0x02, 0x02, 0x27, 0x27, 0x27, 0x27}) 122 | t.Logf("飞机带对 %v,%v,%v", cardType.Kind() != FEI_JI_DAI_DUI, cardType.Weight() == 0, cardType.Value() == 0) 123 | 124 | cardType = BuildCards([]byte{0x1e, 0x1e, 0x1e, 0x02, 0x02, 0x02, 0x26, 0x26, 0x27, 0x27}) 125 | t.Logf("飞机带对 %v,%v,%v", cardType.Kind() != FEI_JI_DAI_DUI, cardType.Weight() == 0, cardType.Value() == 0) 126 | 127 | cardType = BuildCards([]byte{0x1e, 0x1e, 0x1e, 0x0d, 0x0d, 0x0d, 0x27, 0x27, 0x27, 0x27}) 128 | t.Logf("飞机带对 %v,%v,%v", cardType.Kind() == FEI_JI_DAI_DUI, cardType.Weight() == 1, cardType.Value() == 0x0e) 129 | 130 | cardType = BuildCards([]byte{0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05}) 131 | t.Logf("飞机带对 %v,%v,%v", cardType.Kind() == FEI_JI_DAI_DUI, cardType.Weight() == 1, cardType.Value() == 0x04) 132 | } 133 | 134 | //四带两对 135 | func TestAnalyseSidaiDui(t *testing.T) { 136 | cardType := BuildCards([]byte{0x38, 0x08, 0x18, 0x28, 0xEF, 0xFF, 0x1a, 0x2a}) 137 | t.Logf("四带两对 %v,%v,%v", cardType.Kind() != SI_DAI_DUI, cardType.Weight() == 0, cardType.Value() == 0) 138 | 139 | cardType = BuildCards([]byte{0xFF, 0x08, 0x18, 0x28, 0x38, 0xEF, 0x1e, 0x2e}) 140 | t.Logf("四带两对 %v,%v,%v", cardType.Kind() != SI_DAI_DUI, cardType.Weight() == 0, cardType.Value() == 0) 141 | 142 | cardType = BuildCards([]byte{0x1e, 0x0e, 0x2e, 0x3e, 0x0d, 0x0d, 0x0d, 0x0d}) 143 | t.Logf("四带两对 %v,%v,%v", cardType.Kind() != SI_DAI_DUI, cardType.Weight() == 1, cardType.Value() == 0x0e) 144 | 145 | cardType = BuildCards([]byte{0x1e, 0x0e, 0x2e, 0x3e, 0x03, 0x03, 0x0d, 0x0d}) 146 | t.Logf("四带两对 %v,%v,%v", cardType.Kind() == SI_DAI_DUI, cardType.Weight() == 1, cardType.Value() == 0x0e) 147 | 148 | cardType = BuildCards([]byte{0x18, 0x8, 0x38, 0x28, 0x5, 0x15, 0x6, 0x16}) 149 | t.Logf("四带两对 %v,%v,%v", cardType.Kind() == SI_DAI_DUI, cardType.Weight() == 1, cardType.Value() == 0x08) 150 | 151 | cardType = BuildCards([]byte{0x23, 0x13, 0x3, 0x33, 0x24, 0x14, 0x29, 0x19}) 152 | t.Logf("四带两对 %v,%v,%v", cardType.Kind() == SI_DAI_DUI, cardType.Weight() == 1, cardType.Value() == 0x03) 153 | } 154 | 155 | //三带一对 156 | func TestAnalyseSanDaidui(t *testing.T) { 157 | 158 | cardType := BuildCards([]byte{0x1a, 0x08, 0x18, 0x28, 0x0a}) 159 | t.Logf("三带一对 %v,%v,%v", cardType.Kind() == SAN_DAI_YI_DUI, cardType.Weight() == 1, cardType.Value() == 0x8) 160 | 161 | cardType = BuildCards([]byte{0xEF, 0x08, 0x18, 0x28, 0xFF}) 162 | t.Logf("三带一对 %v,%v,%v", cardType.Kind() != SAN_DAI_YI_DUI, cardType.Weight() == 0, cardType.Value() == 0) 163 | } 164 | 165 | //连对 166 | func TestAnalyseLiandui(t *testing.T) { 167 | cardType := BuildCards([]byte{0x23, 0x13, 0x14, 0x04, 0x05, 0x15, 0x06, 0x36}) 168 | t.Logf("连对 %v,%v,%v", cardType.Kind() == LIAN_DUI, cardType.Weight() == 1, cardType.Value() == 0x6) 169 | 170 | cardType = BuildCards([]byte{0x23, 0x13, 0x14, 0x04, 0x05, 0x15, 0x07, 0x37}) 171 | t.Logf("连对 %v,%v,%v", cardType.Kind() != LIAN_DUI, cardType.Weight() == 0, cardType.Value() == 0) 172 | 173 | cardType = BuildCards([]byte{0x0b, 0x0c, 0x2d, 0x1e, 0xff, 0x0b, 0x0c, 0x2d, 0x1e, 0xff}) 174 | t.Logf("连对 %v,%v,%v", cardType.Kind() != LIAN_DUI, cardType.Weight() == 0, cardType.Value() == 0) 175 | } 176 | 177 | func TestAnalyse(t *testing.T) { 178 | 179 | // 顺子 180 | cardType := BuildCards([]byte{0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E}) 181 | t.Logf("顺子 %v,%v,%v", cardType.Kind() != DAN_SHUN_ZI, cardType.Weight() == 0, cardType.Value() == 0) 182 | 183 | // 顺子 184 | cardType = BuildCards([]byte{0x03, 0x04, 0x25, 0x16, 0x02}) 185 | t.Logf("顺子 %v,%v,%v", cardType.Kind() != DAN_SHUN_ZI, cardType.Weight() == 0, cardType.Value() == 0) 186 | 187 | // 顺子 188 | cardType = BuildCards([]byte{0x0b, 0x0c, 0x2d, 0x1e, 0xFF}) 189 | t.Logf("顺子 %v,%v,%v", cardType.Kind() != DAN_SHUN_ZI, cardType.Weight() == 0, cardType.Value() == 0) 190 | 191 | // 王炸 192 | cardType = BuildCards([]byte{0xFF, 0xEF}) 193 | t.Logf("王炸 %v,%v,%v", cardType.Kind() == WANG_ZHA, cardType.Weight() == 3, cardType.Value() == GetValue(0xFF)) 194 | 195 | // 单张 196 | cardType = BuildCards([]byte{0x02}) 197 | t.Logf("单张 %v,%v,%v", cardType.Kind() == DAN_TIAO, cardType.Weight() == 1, cardType.Value() == GetValue(0x02)) 198 | 199 | // 对子 200 | cardType = BuildCards([]byte{0x02, 0x12, 0x22}) 201 | //t.Logf("对子 %v,%v,%v", cardType.Kind(),b,c) 202 | t.Logf("对子 %v,%v,%v", cardType.Kind() != DUI_ZI, cardType.Weight() == 1, cardType.Value() == GetValue(0x02)) 203 | 204 | // 三条 205 | cardType = BuildCards([]byte{0x02, 0x12, 0x22}) 206 | t.Logf("三条 %v,%v,%v", cardType.Kind() == SAN_TIAO, cardType.Weight() == 1, cardType.Value() == GetValue(0x02)) 207 | 208 | // 三带单 209 | cardType = BuildCards([]byte{0x03, 0x02, 0x12, 0x22}) 210 | t.Logf("三带单 %v,%v,%v", cardType.Kind() == SAN_DAI_YI, cardType.Weight() == 1, cardType.Value() == GetValue(0x02)) 211 | 212 | // 炸弹 213 | cardType = BuildCards([]byte{0x02, 0x12, 0x22, 0x32}) 214 | t.Logf("炸弹 %v,%v,%v", cardType.Kind() == ZHA_DAN, cardType.Weight() == 2, cardType.Value() == GetValue(0x02)) 215 | 216 | // 炸弹 217 | cardType = BuildCards([]byte{0x03, 0x13, 0x23, 0x33}) 218 | t.Logf("炸弹 %v,%v,%v", cardType.Kind() == ZHA_DAN, cardType.Weight() == 2, cardType.Value() == 3) 219 | 220 | //连对 221 | cardType = BuildCards([]byte{0x23, 0x04, 0x05, 0x06, 0x13, 0x14, 0x15, 0x36}) 222 | t.Logf("连对 %v,%v,%v", cardType.Kind() == LIAN_DUI, cardType.Weight() == 1, cardType.Value() == 6) 223 | 224 | //连对 225 | cardType = BuildCards([]byte{0x0b, 0x0c, 0x2d, 0x1e, 0xff, 0x0b, 0x0c, 0x2d, 0x1e, 0xff}) 226 | //t.Logf("连对 %v,%v,%v", cardType.Kind(), b, c) 227 | t.Logf("连对 %v,%v,%v", cardType.Kind() != LIAN_DUI, cardType.Weight() == 0, cardType.Value() == 0) 228 | 229 | //三带一对 230 | cardType = BuildCards([]byte{0x17, 0x02, 0x12, 0x22, 0x07}) 231 | t.Logf("三带一对 %v,%v,%v", cardType.Kind() == SAN_DAI_YI_DUI, cardType.Weight() == 1, cardType.Value() == GetValue(0x02)) 232 | 233 | //飞机带单 234 | cardType = BuildCards([]byte{0x02, 0x12, 0x22, 0x05, 0x15, 0x25, 0x26, 0x27}) 235 | t.Logf("飞机带单 %v,%v,%v", cardType.Kind() != FEI_JI_DAI_DAN, cardType.Weight() == 0, cardType.Value() == 0) 236 | 237 | //飞机带单 238 | cardType = BuildCards([]byte{0x02, 0x12, 0x22, 0x03, 0x13, 0x23, 0x26, 0x27}) 239 | t.Logf("飞机带单 %v,%v,%v", cardType.Kind() != FEI_JI_DAI_DAN, cardType.Weight() == 0, cardType.Value() == 0) 240 | 241 | //飞机带单 242 | cardType = BuildCards([]byte{0x04, 0x14, 0x24, 0x05, 0x15, 0x25, 0x26, 0x27}) 243 | t.Logf("飞机带单 %v,%v,%v", cardType.Kind() == FEI_JI_DAI_DAN, cardType.Weight() == 1, cardType.Value() == 5) 244 | 245 | //飞机带对 246 | cardType = BuildCards([]byte{0x03, 0x13, 0x23, 0x05, 0x15, 0x25, 0x26, 0x36, 0x27, 0x37}) 247 | t.Logf("飞机带对 %v,%v,%v", cardType.Kind() != FEI_JI_DAI_DUI, cardType.Weight() == 0, cardType.Value() == 0) 248 | 249 | //飞机带对 250 | cardType = BuildCards([]byte{0x04, 0x14, 0x24, 0x05, 0x15, 0x25, 0x26, 0x36, 0x27, 0x37}) 251 | t.Logf("飞机带对 %v,%v,%v", cardType.Kind() == FEI_JI_DAI_DUI, cardType.Weight() == 1, cardType.Value() == 5) 252 | 253 | //飞机带对 254 | cardType = BuildCards([]byte{0x02, 0x12, 0x22, 0x03, 0x13, 0x23, 0x26, 0x36, 0x27, 0x37}) 255 | t.Logf("飞机带对 %v,%v,%v", cardType.Kind() != FEI_JI_DAI_DUI, cardType.Weight() == 0, cardType.Value() == 0) 256 | 257 | //四带单 258 | cardType = BuildCards([]byte{0x02, 0x12, 0x22, 0x32, 0x06, 0x16}) 259 | t.Logf("四带单 %v,%v,%v", cardType.Kind() == SI_DAI_DAN, cardType.Weight() == 1, cardType.Value() == GetValue(0x02)) 260 | 261 | //四带单 262 | cardType = BuildCards([]byte{0x06, 0x16, 0x07, 0x17, 0x27, 0x37}) 263 | t.Logf("四带单 %v,%v,%v", cardType.Kind() == SI_DAI_DAN, cardType.Weight() == 1, cardType.Value() == 7) 264 | 265 | //四带两对 266 | cardType = BuildCards([]byte{0x02, 0x12, 0x22, 0x32, 0x06, 0x36, 0x0a, 0x3a}) 267 | t.Logf("四带两对 %v,%v,%v", cardType.Kind() == SI_DAI_DUI, cardType.Weight() == 1, cardType.Value() == GetValue(0x02)) 268 | 269 | cardType = BuildCards([]byte{0x0b, 0x0c, 0x2d, 0x1e, 0xFF}) 270 | t.Logf("顺子 %v,%v,%v", cardType.Kind() != DAN_SHUN_ZI, cardType.Weight() == 0, cardType.Value() == 0) 271 | 272 | //t.Log(a,b,c, ConvertValue([]byte{0x0b, 0x0c, 0x2d, 0x1e, 0xFF})) 273 | cardType = BuildCards([]byte{0x02, 0x03, 0x24, 0x15, 0x36}) 274 | t.Logf("顺子 %v,%v,%v", cardType.Kind() != DAN_SHUN_ZI, cardType.Weight() == 0, cardType.Value() == 0) 275 | 276 | // 三顺 277 | cardType = BuildCards([]byte{0x12, 0x02, 0x12, 0x28, 0x08, 0x18}) 278 | t.Logf("三顺 %v,%v,%v", cardType.Kind() != SAN_SHUN_ZI, cardType.Weight() == 0, cardType.Value() == 0) 279 | 280 | cardType = BuildCards([]byte{0x12, 0x02, 0x12, 0x23, 0x03, 0x13}) 281 | t.Logf("三顺 %v,%v,%v", cardType.Kind() != SAN_SHUN_ZI, cardType.Weight() == 0, cardType.Value() == 0) 282 | 283 | cardType = BuildCards([]byte{0x23, 0x03, 0x13, 0x14, 0x04, 0x14}) 284 | t.Logf("三顺 %v,%v,%v", cardType.Kind() == SAN_SHUN_ZI, cardType.Weight() == 1, cardType.Value() == 4) 285 | 286 | cardType = BuildCards([]byte{0x23, 0x03, 0x14, 0x15, 0x05, 0x16}) 287 | t.Logf("三顺 %v,%v,%v", cardType.Kind() != SAN_SHUN_ZI, cardType.Weight() == 0, cardType.Value() ) 288 | 289 | cardType = BuildCards([]byte{0x2d, 0x0d, 0x1d, 0x1e, 0x0e, 0x1e}) 290 | t.Logf("三顺 %v,%v,%v", cardType.Kind() == SAN_SHUN_ZI, cardType.Weight() == 1, cardType.Value() == 0xe) 291 | 292 | //飞机带两个 293 | 294 | cardType = BuildCards([]byte{0x02, 0x12, 0x22, 0x05, 0x15, 0x25, 0x26, 0x27}) 295 | t.Logf("飞机带两个 %v,%v,%v", cardType.Kind() != FEI_JI_DAI_DAN, cardType.Weight() == 0, cardType.Value() == 0) 296 | 297 | cardType = BuildCards([]byte{0x02, 0x12, 0x22, 0x03, 0x13, 0x23, 0x26, 0x27}) 298 | t.Logf("飞机带两个 %v,%v,%v", cardType.Kind() != FEI_JI_DAI_DAN, cardType.Weight() == 0, cardType.Value() == 0) 299 | 300 | cardType = BuildCards([]byte{0x04, 0x14, 0x24, 0x05, 0x15, 0x25, 0x26, 0x27}) 301 | t.Logf("飞机带两个 %v,%v,%v", cardType.Kind() == FEI_JI_DAI_DAN, cardType.Weight() == 1, cardType.Value() == 0x5) 302 | 303 | //飞机带对 304 | //飞机带对 305 | cardType = BuildCards([]byte{0x03, 0x13, 0x23, 0x05, 0x15, 0x25, 0x26, 0x36, 0x27, 0x37}) 306 | t.Logf("飞机带对 %v,%v,%v", cardType.Kind() != FEI_JI_DAI_DUI, cardType.Weight() == 0, cardType.Value() == 0) 307 | 308 | //飞机带对 309 | cardType = BuildCards([]byte{0x04, 0x14, 0x24, 0x05, 0x15, 0x25, 0x26, 0x36, 0x27, 0x37}) 310 | t.Logf("飞机带对 %v,%v,%v", cardType.Kind() == FEI_JI_DAI_DUI, cardType.Weight() == 1, cardType.Value() == 0x5) 311 | 312 | //飞机带对 313 | cardType = BuildCards([]byte{0x02, 0x12, 0x22, 0x03, 0x13, 0x23, 0x26, 0x36, 0x27, 0x37}) 314 | t.Logf("飞机带对 %v,%v,%v", cardType.Kind() != FEI_JI_DAI_DUI, cardType.Weight() == 0, cardType.Value() == 0) 315 | 316 | //飞机带对 317 | cardType = BuildCards([]byte{0x04, 0x14, 0x24, 0x05, 0x15, 0x25, 0x26, 0x36, 0xEF, 0xFF}) 318 | t.Logf("飞机带对 %v,%v,%v", cardType.Kind() != FEI_JI_DAI_DUI, cardType.Weight() == 0, cardType.Value() == 0) 319 | 320 | //飞机带对 321 | cardType = BuildCards([]byte{0x02, 0x02, 0x03, 0x13, 0x23, 0x04, 0x14, 0x24, 0x05, 0x15, 0x25, 0x26, 0x36, 0x27, 0x37}) 322 | t.Logf("飞机带对 %v,%v,%v", cardType.Kind() == FEI_JI_DAI_DUI, cardType.Weight() == 1, cardType.Value() == 5) 323 | 324 | //四带两对 325 | cardType = BuildCards([]byte{0x38, 0x08, 0x18, 0x28, 0xEF, 0xFF, 0x1a, 0x2a}) 326 | t.Logf("四带两对 %v,%v,%v", cardType.Kind() != SI_DAI_DUI, cardType.Weight() == 0, cardType.Value() == 0) 327 | 328 | cardType = BuildCards([]byte{0xFF, 0x08, 0x18, 0x28, 0x38, 0xEF, 0x1e, 0x2e}) 329 | t.Logf("四带两对 %v,%v,%v", cardType.Kind() != SI_DAI_DUI, cardType.Weight() == 0, cardType.Value() == 0) 330 | 331 | cardType = BuildCards([]byte{0x06, 0x16, 0x26, 0x07, 0x17, 0x27, 0x36, 0x37}) 332 | t.Logf("四带两对 %v,%v,%v", cardType.Kind() != SI_DAI_DUI, cardType.Weight() == 1, cardType.Value() == 0x7) 333 | 334 | 335 | 336 | cardType = BuildCards([]byte{0x06, 0x16, 0x36, 0x08, 0x18, 0x28, 0x26, 0x38}) 337 | t.Logf("四带两对 %v,%v,%v", cardType.Kind() == SI_DAI_DUI, cardType.Weight() == 1, cardType.Value() == 0x8) 338 | 339 | //三带一对 340 | cardType = BuildCards([]byte{0x1a, 0x08, 0x18, 0x28, 0x0a}) 341 | t.Logf("三带一对 %v,%v,%v", cardType.Kind() == SAN_DAI_YI_DUI, cardType.Weight() == 1, cardType.Value() == 0x8) 342 | 343 | cardType = BuildCards([]byte{0xEF, 0x08, 0x18, 0x28, 0xFF}) 344 | t.Logf("三带一对 %v,%v,%v", cardType.Kind() != SAN_DAI_YI_DUI, cardType.Weight() == 0, cardType.Value() == 0) 345 | //连对 346 | cardType = BuildCards([]byte{0x23, 0x13, 0x14, 0x04, 0x05, 0x15, 0x06, 0x36}) 347 | t.Logf("连对 %v,%v,%v", cardType.Kind() == LIAN_DUI, cardType.Weight() == 1, cardType.Value() == 0x6) 348 | 349 | cardType = BuildCards([]byte{0x23, 0x13, 0x14, 0x04, 0x05, 0x15, 0x07, 0x37}) 350 | t.Logf("连对 %v,%v,%v", cardType.Kind() != LIAN_DUI, cardType.Weight() == 0, cardType.Value() == 0,) 351 | 352 | cardType = BuildCards([]byte{0x0b, 0x0c, 0x2d, 0x1e, 0xff, 0x0b, 0x0c, 0x2d, 0x1e, 0xff}) 353 | t.Logf("连对 %v,%v,%v", cardType.Kind() != LIAN_DUI, cardType.Weight() == 0, cardType.Value() == 0) 354 | 355 | } 356 | --------------------------------------------------------------------------------