github.com/lianghucheng/zrddz@v0.0.0-20200923083010-c71f680932e2/src/game/poker/landlord.go (about)

     1  package poker
     2  
     3  import (
     4  	"common"
     5  	"sort"
     6  )
     7  
     8  // 出牌动作类型
     9  const (
    10  	_                                = iota
    11  	ActionLandlordDiscardMust        // 1 必须
    12  	ActionLandlordDiscardAlternative // 2 可选择的(可出可不出)
    13  	ActionLandlordDiscardNothing     // 3 要不起
    14  )
    15  
    16  // 斗地主牌型
    17  const (
    18  	Error            = iota // 0 牌型错误
    19  	Solo                    // 1 单张
    20  	Pair                    // 2 对子
    21  	Trio                    // 3 三张
    22  	TrioSolo                // 4 三带一
    23  	TrioPair                // 5 三带一对
    24  	SoloChain               // 6 顺子
    25  	PairSisters             // 7 连对
    26  	AirplaneChain           // 8 飞机
    27  	TrioSoloAirplane        // 9 飞机带小翼
    28  	TrioPairChain           // 10 飞机带大翼
    29  	FourDualsolo            // 11 四带两单
    30  	FourDualpair            // 12 四带两对
    31  	Bomb                    // 13 炸弹
    32  	KingBomb                // 14 王炸
    33  )
    34  
    35  var (
    36  	LandlordAllCards   = landlordAllCards()
    37  	LandlordAllCards2P = landlordAllCards2P()
    38  )
    39  
    40  type LandlordRule struct {
    41  	RoomType      int   // 房间类型: 0 练习、1 底分匹配、2 底分私人、3 VIP私人、4 红包匹配、5 红包私人
    42  	MaxPlayers    int   // 人数: 2、3
    43  	BaseScore     int   // 底分: 100、5千、1万、3万、5万、10万
    44  	RedPacketType int   // 红包种类(元): 1、10、100、999
    45  	MinChips      int64 // 最小筹码: 底分x10/红包种类x1万
    46  	Tickets       int64 // 门票金额
    47  	IPAntiCheat   bool  // IP 防作弊
    48  	GPSAntiCheat  bool  // GPS 防作弊
    49  }
    50  
    51  // 玩家单局成绩
    52  type LandlordPlayerRoundResult struct {
    53  	Nickname   string  // 昵称
    54  	Headimgurl string  // 头像
    55  	Landlord   bool    // 地主
    56  	BaseScore  int     // 底分
    57  	Multiple   int     // 倍数
    58  	Chips      int64   // 筹码
    59  	RedPacket  float64 // 红包金额
    60  }
    61  
    62  // 斗地主所有的扑克牌
    63  func landlordAllCards() []int {
    64  	cards := append([]int{}, Diamonds...)
    65  	cards = append(cards, Clubs...)
    66  	cards = append(cards, Hearts...)
    67  	cards = append(cards, Spades...)
    68  	cards = append(cards, Jokers...)
    69  	return cards
    70  }
    71  
    72  // 二人斗地主所有扑克牌
    73  func landlordAllCards2P() []int {
    74  	cards := append([]int{}, Diamonds[2:]...)
    75  	cards = append(cards, Clubs[2:]...)
    76  	cards = append(cards, Hearts[2:]...)
    77  	cards = append(cards, Spades[2:]...)
    78  	cards = append(cards, Jokers...)
    79  	return cards
    80  }
    81  
    82  func ToLandlordTypeString(cardsType int) string {
    83  	switch cardsType {
    84  	case Solo: // 1 单张
    85  		return "单张"
    86  	case Pair: // 2 对子
    87  		return "对子"
    88  	case Trio: // 3 三张
    89  		return "三张"
    90  	case TrioSolo: // 4 三带一
    91  		return "三带一"
    92  	case TrioPair: // 5 三带一对
    93  		return "三带一对"
    94  	case SoloChain: // 6 顺子
    95  		return "顺子"
    96  	case PairSisters: // 7 连对
    97  		return "连对"
    98  	case AirplaneChain: // 8 飞机
    99  		return "飞机"
   100  	case TrioSoloAirplane: // 9 飞机带小翼
   101  		return "飞机带小翼"
   102  	case TrioPairChain: // 10 飞机带大翼
   103  		return "飞机带大翼"
   104  	case FourDualsolo: // 11 四带两单
   105  		return "四带两单"
   106  	case FourDualpair: // 12 四带两对
   107  		return "四带两对"
   108  	case Bomb: // 13 炸弹
   109  		return "炸弹"
   110  	case KingBomb: // 14 王炸
   111  		return "王炸"
   112  	default:
   113  		return "牌型错误"
   114  	}
   115  }
   116  
   117  // 与手牌比较大小
   118  func CompareLandlordHands(discards []int, hands []int) bool {
   119  	discardsType := GetLandlordCardsType(discards)
   120  	switch discardsType {
   121  	case KingBomb:
   122  		return true
   123  	case Error:
   124  		return false
   125  	}
   126  	analyzer := new(LandlordAnalyzer)
   127  	analyzer.Analyze(hands)
   128  	if analyzer.hasKingBomb {
   129  		return false
   130  	}
   131  	if discardsType == Bomb {
   132  		if analyzer.hasBomb && CardValue(discards[0]) < CardValue(analyzer.bombs[0][0]) {
   133  			return false
   134  		}
   135  		return true
   136  	}
   137  	if analyzer.hasBomb {
   138  		return false
   139  	}
   140  	discardsLen, handsLen := len(discards), len(hands)
   141  	if discardsLen > handsLen || discardsType == FourDualsolo || discardsType == FourDualpair {
   142  		return true
   143  	}
   144  	switch discardsType {
   145  	case Solo:
   146  		if CardValue(discards[0]) < CardValue(hands[0]) {
   147  			return false
   148  		}
   149  		return true
   150  	case Pair:
   151  		if analyzer.hasPair && CardValue(discards[0]) < CardValue(analyzer.pairs[0][0]) {
   152  			return false
   153  		}
   154  		return true
   155  	case Trio, TrioSolo:
   156  		if analyzer.hasTrio && CardValue(discards[0]) < CardValue(analyzer.trios[0][0]) {
   157  			return false
   158  		}
   159  		return true
   160  	case TrioPair:
   161  		if analyzer.hasTrio && CardValue(discards[0]) < CardValue(analyzer.trios[0][0]) {
   162  			remain := common.Remove(hands, analyzer.trios[0])
   163  			for _, card := range remain {
   164  				if CountCardValue(remain, card) > 1 {
   165  					return false
   166  				}
   167  			}
   168  		}
   169  		return true
   170  	case SoloChain:
   171  		if analyzer.hasSoloChain && discardsLen <= len(analyzer.soloChains[0]) && CardValue(discards[0]) < CardValue(analyzer.soloChains[0][0]) {
   172  			return false
   173  		}
   174  		return true
   175  	case PairSisters:
   176  		if analyzer.hasPairSisters && discardsLen <= len(analyzer.pairSisterss[0]) && CardValue(discards[0]) < CardValue(analyzer.pairSisterss[0][0]) {
   177  			return false
   178  		}
   179  		return true
   180  	case AirplaneChain: // 飞机
   181  		if analyzer.hasAirplaneChain && discardsLen <= len(analyzer.airplaneChains[0]) && CardValue(discards[0]) < CardValue(analyzer.airplaneChains[0][0]) {
   182  			return false
   183  		}
   184  		return true
   185  	case TrioSoloAirplane: // 飞机带小翼
   186  		discardAirplaneLen := discardsLen / 4 * 3
   187  		discardAirplane := discards[:discardAirplaneLen]
   188  		if analyzer.hasAirplaneChain && discardAirplaneLen <= len(analyzer.airplaneChains[0]) && CardValue(discardAirplane[0]) < CardValue(analyzer.airplaneChains[0][0]) {
   189  			remain := common.Remove(hands, analyzer.airplaneChains[0][:discardAirplaneLen])
   190  			if len(remain) >= discardsLen/4 {
   191  				return false
   192  			}
   193  		}
   194  		return true
   195  	case TrioPairChain: // 飞机带大翼
   196  		discardAirplaneLen := discardsLen / 5 * 3
   197  		discardAirplane := discards[:discardAirplaneLen]
   198  		if analyzer.hasAirplaneChain && discardAirplaneLen <= len(analyzer.airplaneChains[0]) && CardValue(discardAirplane[0]) < CardValue(analyzer.airplaneChains[0][0]) {
   199  			remain, countPair := common.Remove(hands, analyzer.airplaneChains[0][:discardAirplaneLen]), 0
   200  			for _, card := range remain {
   201  				if CountCardValue(remain, card) > 1 {
   202  					countPair++
   203  				}
   204  			}
   205  			if countPair >= discardsLen/5 {
   206  				return false
   207  			}
   208  		}
   209  		return true
   210  	}
   211  	return false
   212  }
   213  
   214  // 与出的牌比较大小
   215  func CompareLandlordDiscard(discards []int, preDiscards []int) bool {
   216  	discardsType := GetLandlordCardsType(discards)
   217  	preDiscardsType := GetLandlordCardsType(preDiscards)
   218  	if discardsType == preDiscardsType {
   219  		if len(discards) == len(preDiscards) && CardValue(discards[0]) > CardValue(preDiscards[0]) {
   220  			return true
   221  		}
   222  		return false
   223  	}
   224  	switch discardsType {
   225  	case KingBomb, Bomb:
   226  		return true
   227  	}
   228  	return false
   229  }
   230  
   231  func GetLandlordCardsType(cards []int) int {
   232  	cardsLen := len(cards)
   233  	if cardsLen == 1 {
   234  		return Solo // 单张
   235  	}
   236  	if cardsLen == 2 {
   237  		if cards[0] == 53 && cards[1] == 52 {
   238  			return KingBomb // 王炸
   239  		}
   240  		if CardValue(cards[0]) == CardValue(cards[1]) {
   241  			return Pair // 对子
   242  		}
   243  	}
   244  	if cardsLen == 3 {
   245  		if CountCardValue(cards, cards[0]) == 3 {
   246  			return Trio // 三张
   247  		}
   248  	}
   249  	if cardsLen == 4 {
   250  		count1stCardValue := CountCardValue(cards, cards[0])
   251  		if count1stCardValue == 4 {
   252  			return Bomb // 炸弹
   253  		}
   254  		if count1stCardValue == 3 || CountCardValue(cards[1:], cards[1]) == 3 {
   255  			return TrioSolo // 三带一
   256  		}
   257  	}
   258  	if cardsLen == 5 {
   259  		for i := 0; i < 2; i++ {
   260  			if CountCardValue(cards[i*2:i*2+3], cards[i*2]) == 3 {
   261  				remain := common.Remove(cards, cards[i*2:i*2+3])
   262  				if CardValue(remain[0]) == CardValue(remain[1]) {
   263  					return TrioPair // 三带一对
   264  				}
   265  			}
   266  		}
   267  	}
   268  	if cardsLen >= 5 {
   269  		if CardValue(cards[0]) < 15 && Sequence(cards) { // < 2
   270  			return SoloChain // 顺子
   271  		}
   272  	}
   273  	if cardsLen == 6 {
   274  		for i := 0; i < 3; i++ {
   275  			if CountCardValue(cards[i:i+4], cards[i]) == 4 {
   276  				return FourDualsolo // 四带两单
   277  			}
   278  		}
   279  	}
   280  	if cardsLen >= 6 && cardsLen%2 == 0 {
   281  		if CardValue(cards[0]) < 15 { // < 2
   282  			allPair, seq := AllPair(cards)
   283  			if allPair && seq {
   284  				return PairSisters // 连对
   285  			}
   286  		}
   287  	}
   288  	if cardsLen >= 6 && cardsLen%3 == 0 {
   289  		if CardValue(cards[0]) < 15 { // < 2
   290  			allTrio, seq := AllTrio(cards)
   291  			if allTrio && seq {
   292  				return AirplaneChain // 飞机
   293  			}
   294  		}
   295  	}
   296  	if cardsLen == 8 {
   297  		for i := 0; i < 3; i++ {
   298  			if CountCardValue(cards[i*2:i*2+4], cards[i*2]) == 4 {
   299  				remain := common.Remove(cards, cards[i*2:i*2+4])
   300  				if allPair, _ := AllPair(remain); allPair && CountCardValue(remain, remain[0]) == 2 {
   301  					return FourDualpair // 四带两对
   302  				}
   303  			}
   304  		}
   305  	}
   306  	if cardsLen >= 8 && cardsLen%4 == 0 {
   307  		for i := 0; i <= cardsLen/4; i++ { // 遍历小翼的个数
   308  			if CardValue(cards[i]) < 15 { // < 2
   309  				allTrio, seq := AllTrio(cards[i : i+cardsLen/4*3])
   310  				if allTrio && seq {
   311  					valueMap := GetCardValueMap(cards[i : i+cardsLen/4*3])
   312  					remain := RemoveCardByValue(cards, valueMap)
   313  					if len(remain) == cardsLen/4 {
   314  						return TrioSoloAirplane // 飞机带小翼
   315  					}
   316  				}
   317  			}
   318  		}
   319  	}
   320  	if cardsLen >= 10 && cardsLen%5 == 0 {
   321  		for i := 0; i <= cardsLen/5; i++ { // 遍历大翼的个数
   322  			if CardValue(cards[i*2]) < 15 { // < 2
   323  				allTrio, seq := AllTrio(cards[i*2 : i*2+cardsLen/5*3])
   324  				if allTrio && seq {
   325  					valueMap := GetCardValueMap(cards[i*2 : i*2+cardsLen/5*3])
   326  					remain := RemoveCardByValue(cards, valueMap)
   327  					allPair, _ := AllPair(remain)
   328  					if allPair && len(remain) == cardsLen/5*2 {
   329  						return TrioPairChain // 飞机带大翼
   330  					}
   331  				}
   332  			}
   333  		}
   334  	}
   335  	return Error
   336  }
   337  
   338  // cards 的长度至少为6且是3的倍数
   339  func GetLandlordAirplaneChains(cards []int) [][]int {
   340  	airplaneChains := [][]int{}
   341  	cardsLen := len(cards)
   342  	if cardsLen > 5 && cardsLen%3 == 0 {
   343  		temp := append([]int{}, cards[:3]...)
   344  		for i := 1; i < cardsLen/3; i++ {
   345  			trio := cards[i*3 : i*3+3]
   346  			if Sequence([]int{temp[len(temp)-1], trio[0]}) {
   347  				temp = append(temp, trio...)
   348  			} else {
   349  				if len(temp) > 5 {
   350  					airplaneChains = append(airplaneChains, temp)
   351  				}
   352  				temp = append([]int{}, trio...)
   353  			}
   354  		}
   355  		if len(temp) > 5 {
   356  			airplaneChains = append(airplaneChains, temp)
   357  		}
   358  	}
   359  	return airplaneChains
   360  }
   361  
   362  // cards 的长度至少为6且是2的倍数
   363  func GetLandlordPairSisters(cards []int) [][]int {
   364  	pairSisters := [][]int{}
   365  	cardsLen := len(cards)
   366  	if cardsLen > 5 && cardsLen%2 == 0 {
   367  		temp := append([]int{}, cards[:2]...)
   368  		for i := 1; i < cardsLen/2; i++ {
   369  			pair := cards[i*2 : i*2+2]
   370  			if CardValue(temp[len(temp)-1]) == CardValue(pair[0]) {
   371  				continue
   372  			}
   373  			if Sequence([]int{temp[len(temp)-1], pair[0]}) {
   374  				temp = append(temp, pair...)
   375  			} else {
   376  				if len(temp) > 5 {
   377  					pairSisters = append(pairSisters, temp)
   378  				}
   379  				temp = append([]int{}, pair...)
   380  			}
   381  		}
   382  		if len(temp) > 5 {
   383  			pairSisters = append(pairSisters, temp)
   384  		}
   385  	}
   386  	return pairSisters
   387  }
   388  
   389  // cards 的长度至少为5
   390  func GetLandlordSoloChains(cards []int) [][]int {
   391  	cardsLen := len(cards)
   392  	if cardsLen < 5 {
   393  		return [][]int{}
   394  	}
   395  	soloChains := [][]int{}
   396  	temp := []int{cards[0]}
   397  	for i := 1; i < cardsLen; i++ {
   398  		solo := cards[i]
   399  		if CardValue(temp[len(temp)-1]) == CardValue(solo) {
   400  			continue
   401  		}
   402  		if Sequence([]int{temp[len(temp)-1], solo}) {
   403  			temp = append(temp, solo)
   404  		} else {
   405  			if len(temp) > 4 {
   406  				soloChains = append(soloChains, temp)
   407  			}
   408  			temp = []int{solo}
   409  		}
   410  	}
   411  	if len(temp) > 4 {
   412  		soloChains = append(soloChains, temp)
   413  	}
   414  	return soloChains
   415  }
   416  
   417  func GetDiscardHint(preDiscards []int, hands []int) [][]int {
   418  	preDiscardsType := GetLandlordCardsType(preDiscards)
   419  	switch preDiscardsType {
   420  	case Solo: // 单张
   421  		return GetGreaterThanSolo(CardValue(preDiscards[0]), hands)
   422  	case Pair: // 对子
   423  		return GetGreaterThanPair(CardValue(preDiscards[0]), hands)
   424  	case Trio: // 三张
   425  		return GetGreaterThanTrio(CardValue(preDiscards[0]), hands)
   426  	case TrioSolo: // 三带一
   427  		return GetGreaterThanTrioSolo(CardValue(preDiscards[0]), hands)
   428  	case TrioPair: // 三带一对
   429  		return GetGreaterThanTrioPair(CardValue(preDiscards[0]), hands)
   430  	case SoloChain: // 顺子
   431  		return GetGreaterThanSoloChain(preDiscards, hands)
   432  	case PairSisters: // 连对
   433  		return GetGreaterThanPairSisters(preDiscards, hands)
   434  	case AirplaneChain: // 飞机
   435  		return GetGreaterThanAirplaneChain(preDiscards, hands)
   436  	case TrioSoloAirplane: // 飞机带小翼
   437  		return GetGreaterThanTrioSoloAirplane(preDiscards, hands)
   438  	case TrioPairChain: // 飞机带大翼
   439  		return GetGreaterThanTrioPairChain(preDiscards, hands)
   440  	case FourDualsolo, FourDualpair: // 四带两单、四带两对
   441  		return GetBombs(hands)
   442  	case Bomb: // 炸弹
   443  		return GetGreaterThanBomb(CardValue(preDiscards[0]), hands)
   444  	}
   445  	return [][]int{}
   446  }
   447  
   448  func GetBombs(cards []int) [][]int {
   449  	analyzer := new(LandlordAnalyzer)
   450  	analyzer.Analyze(cards)
   451  
   452  	bombs := [][]int{}
   453  	if analyzer.hasBomb {
   454  		bombsLen := len(analyzer.bombs)
   455  		for i := bombsLen - 1; i > -1; i-- {
   456  			bombs = append(bombs, analyzer.bombs[i])
   457  		}
   458  	}
   459  	if analyzer.hasKingBomb {
   460  		bombs = append(bombs, []int{53, 52})
   461  	}
   462  	return bombs
   463  }
   464  
   465  // 获取大于单张的牌
   466  func GetGreaterThanSolo(cardValue int, cards []int) [][]int {
   467  	analyzer := new(LandlordAnalyzer)
   468  	analyzer.Analyze(cards)
   469  
   470  	m, melds := make(map[int]bool), [][]int{}
   471  	remain := append([]int{}, cards...)
   472  	if analyzer.hasSoloChain {
   473  		for _, soloChain := range analyzer.soloChains {
   474  			remain = common.Remove(remain, soloChain)
   475  		}
   476  	}
   477  	sort.Ints(remain)
   478  	for _, card := range remain {
   479  		cardValue2 := CardValue(card)
   480  		if m[cardValue2] {
   481  			continue
   482  		}
   483  		m[cardValue2] = true
   484  		if cardValue2 > cardValue {
   485  			melds = append(melds, []int{card})
   486  		}
   487  	}
   488  	melds = ReSortHint(Solo, melds, remain)
   489  	if analyzer.hasSoloChain {
   490  		temp := common.Remove(cards, remain)
   491  		sort.Ints(temp)
   492  		for _, card := range temp {
   493  			cardValue2 := CardValue(card)
   494  			if m[cardValue2] {
   495  				continue
   496  			}
   497  			m[cardValue2] = true
   498  			if cardValue2 > cardValue {
   499  				melds = append(melds, []int{card})
   500  			}
   501  		}
   502  	}
   503  	bombs := GetBombs(cards)
   504  	melds = append(melds, bombs...)
   505  	return melds
   506  }
   507  
   508  // 获取大于对子的牌
   509  func GetGreaterThanPair(cardValue int, cards []int) [][]int {
   510  	analyzer := new(LandlordAnalyzer)
   511  	analyzer.Analyze(cards)
   512  
   513  	melds := [][]int{}
   514  	if analyzer.hasPair {
   515  		m := make(map[int]bool)
   516  		pairsLen := len(analyzer.pairs)
   517  		for i := pairsLen - 1; i > -1; i-- {
   518  			value := CardValue(analyzer.pairs[i][0])
   519  			if m[value] {
   520  				continue
   521  			}
   522  			m[value] = true
   523  			if value > cardValue {
   524  				melds = append(melds, analyzer.pairs[i])
   525  			}
   526  		}
   527  	}
   528  	melds = ReSortHint(Pair, melds, cards)
   529  	bombs := GetBombs(cards)
   530  	melds = append(melds, bombs...)
   531  	return melds
   532  }
   533  
   534  // 获取大于三张的牌
   535  func GetGreaterThanTrio(cardValue int, cards []int) [][]int {
   536  	analyzer := new(LandlordAnalyzer)
   537  	analyzer.Analyze(cards)
   538  
   539  	melds := [][]int{}
   540  	if analyzer.hasTrio {
   541  		triosLen := len(analyzer.trios)
   542  		for i := triosLen - 1; i > -1; i-- {
   543  			value := CardValue(analyzer.trios[i][0])
   544  			if value > cardValue {
   545  				melds = append(melds, analyzer.trios[i])
   546  			}
   547  		}
   548  	}
   549  	melds = ReSortHint(Trio, melds, cards)
   550  	bombs := GetBombs(cards)
   551  	melds = append(melds, bombs...)
   552  	return melds
   553  }
   554  
   555  // 获取大于三带一的牌
   556  func GetGreaterThanTrioSolo(cardValue int, cards []int) [][]int {
   557  	analyzer := new(LandlordAnalyzer)
   558  	analyzer.Analyze(cards)
   559  
   560  	melds := [][]int{}
   561  	if analyzer.hasTrio {
   562  		triosLen := len(analyzer.trios)
   563  		for i := triosLen - 1; i > -1; i-- {
   564  			cardValue2 := CardValue(analyzer.trios[i][0])
   565  			if cardValue2 > cardValue {
   566  				valueMap := GetCardValueMap(analyzer.trios[i])
   567  				remain := RemoveCardByValue(cards, valueMap)
   568  				solo := GetSoloByCount(remain)
   569  				if len(solo) == 1 {
   570  					trioSolo := append([]int{}, analyzer.trios[i]...)
   571  					trioSolo = append(trioSolo, solo...)
   572  					melds = append(melds, trioSolo)
   573  				}
   574  			}
   575  		}
   576  	}
   577  	melds = ReSortHint(TrioSolo, melds, cards)
   578  	bombs := GetBombs(cards)
   579  	melds = append(melds, bombs...)
   580  	return melds
   581  }
   582  
   583  // 获取大于三带一对的牌
   584  func GetGreaterThanTrioPair(cardValue int, cards []int) [][]int {
   585  	analyzer := new(LandlordAnalyzer)
   586  	analyzer.Analyze(cards)
   587  
   588  	melds := [][]int{}
   589  	if analyzer.hasTrio {
   590  		triosLen := len(analyzer.trios)
   591  		for i := triosLen - 1; i > -1; i-- {
   592  			value := CardValue(analyzer.trios[i][0])
   593  			if value > cardValue {
   594  				valueMap := GetCardValueMap(analyzer.trios[i])
   595  				remain := RemoveCardByValue(cards, valueMap)
   596  				pair := GetPairByCount(remain)
   597  				if len(pair) == 2 {
   598  					trioPair := append([]int{}, analyzer.trios[i]...)
   599  					trioPair = append(trioPair, pair...)
   600  					melds = append(melds, trioPair)
   601  				}
   602  			}
   603  		}
   604  	}
   605  	melds = ReSortHint(TrioPair, melds, cards)
   606  	bombs := GetBombs(cards)
   607  	melds = append(melds, bombs...)
   608  	return melds
   609  }
   610  
   611  // 获取大于顺子的牌
   612  func GetGreaterThanSoloChain(preSoloChain []int, cards []int) [][]int {
   613  	analyzer := new(LandlordAnalyzer)
   614  	analyzer.Analyze(cards)
   615  
   616  	melds := [][]int{}
   617  	preSoloChainLen := len(preSoloChain)
   618  	cardValue := CardValue(preSoloChain[0])
   619  	if analyzer.hasSoloChain {
   620  		m, temp := make(map[string]bool), [][]int{}
   621  		for _, soloChain := range analyzer.soloChains {
   622  			key := MeldKey(soloChain)
   623  			if m[key] {
   624  				continue
   625  			}
   626  			m[key] = true
   627  			soloChainLen := len(soloChain)
   628  			for i, card := range soloChain {
   629  				cardValue2 := CardValue(card)
   630  				if i+preSoloChainLen <= soloChainLen && cardValue2 > cardValue {
   631  					temp = append(temp, soloChain[i:i+preSoloChainLen])
   632  				} else {
   633  					break
   634  				}
   635  			}
   636  		}
   637  		tempLen := len(temp)
   638  		for i := tempLen - 1; i > -1; i-- {
   639  			melds = append(melds, temp[i])
   640  		}
   641  	}
   642  	bombs := GetBombs(cards)
   643  	melds = append(melds, bombs...)
   644  	return melds
   645  }
   646  
   647  // 获取大于连对的牌
   648  func GetGreaterThanPairSisters(prePairSisters []int, cards []int) [][]int {
   649  	analyzer := new(LandlordAnalyzer)
   650  	analyzer.Analyze(cards)
   651  
   652  	melds := [][]int{}
   653  	prePairSistersLen := len(prePairSisters)
   654  	cardValue := CardValue(prePairSisters[0])
   655  	if analyzer.hasPairSisters {
   656  		m, temp := make(map[string]bool), [][]int{}
   657  		for _, pairSisters := range analyzer.pairSisterss {
   658  			key := MeldKey(pairSisters)
   659  			if m[key] {
   660  				continue
   661  			}
   662  			m[key] = true
   663  			pairSistersLen := len(pairSisters)
   664  			for i := 0; i < pairSistersLen/2; i++ {
   665  				cardValue2 := CardValue(pairSisters[i*2])
   666  				if i*2+prePairSistersLen <= pairSistersLen && cardValue2 > cardValue {
   667  					temp = append(temp, pairSisters[i*2:i*2+prePairSistersLen])
   668  				} else {
   669  					break
   670  				}
   671  			}
   672  		}
   673  		tempLen := len(temp)
   674  		for i := tempLen - 1; i > -1; i-- {
   675  			melds = append(melds, temp[i])
   676  		}
   677  	}
   678  	bombs := GetBombs(cards)
   679  	melds = append(melds, bombs...)
   680  	return melds
   681  }
   682  
   683  // 获取大于飞机的牌
   684  func GetGreaterThanAirplaneChain(preAirplaneChain []int, cards []int) [][]int {
   685  	analyzer := new(LandlordAnalyzer)
   686  	analyzer.Analyze(cards)
   687  
   688  	melds := [][]int{}
   689  	preAirplaneChainLen := len(preAirplaneChain)
   690  	cardValue := CardValue(preAirplaneChain[0])
   691  	if analyzer.hasAirplaneChain {
   692  		temp := [][]int{}
   693  		for _, airplaneChain := range analyzer.airplaneChains {
   694  			airplaneChainLen := len(airplaneChain)
   695  			for i := 0; i < airplaneChainLen/3; i++ {
   696  				cardValue2 := CardValue(airplaneChain[i*3])
   697  				if i*3+preAirplaneChainLen <= airplaneChainLen && cardValue2 > cardValue {
   698  					temp = append(temp, airplaneChain[i*3:i*3+preAirplaneChainLen])
   699  				} else {
   700  					break
   701  				}
   702  			}
   703  		}
   704  		tempLen := len(temp)
   705  		for i := tempLen - 1; i > -1; i-- {
   706  			melds = append(melds, temp[i])
   707  		}
   708  	}
   709  	bombs := GetBombs(cards)
   710  	melds = append(melds, bombs...)
   711  	return melds
   712  }
   713  
   714  // 获取大于飞机带小翼的牌
   715  func GetGreaterThanTrioSoloAirplane(preTrioSoloAirplane []int, cards []int) [][]int {
   716  	analyzer := new(LandlordAnalyzer)
   717  	analyzer.Analyze(cards)
   718  
   719  	melds := [][]int{}
   720  	preTrioSoloAirplaneLen := len(preTrioSoloAirplane)
   721  	preAirplaneChainLen := preTrioSoloAirplaneLen / 4 * 3
   722  	cardValue := CardValue(preTrioSoloAirplane[0])
   723  	if analyzer.hasAirplaneChain {
   724  		temp := [][]int{}
   725  		for _, airplaneChain := range analyzer.airplaneChains {
   726  			airplaneChainLen := len(airplaneChain)
   727  			for i := 0; i < airplaneChainLen/3; i++ {
   728  				cardValue2 := CardValue(airplaneChain[i*3])
   729  				if i*3+preAirplaneChainLen <= airplaneChainLen && cardValue2 > cardValue {
   730  					valueMap := GetCardValueMap(airplaneChain[i*3 : i*3+preAirplaneChainLen])
   731  					remain := RemoveCardByValue(cards, valueMap)
   732  					remainLen := len(remain)
   733  					if remainLen >= preTrioSoloAirplaneLen/4 {
   734  						trioSoloAirplane := append([]int{}, airplaneChain[i*3:i*3+preAirplaneChainLen]...)
   735  						trioSoloAirplane = append(trioSoloAirplane, remain[remainLen-preTrioSoloAirplaneLen/4:]...)
   736  						temp = append(temp, trioSoloAirplane)
   737  					}
   738  				} else {
   739  					break
   740  				}
   741  			}
   742  		}
   743  		tempLen := len(temp)
   744  		for i := tempLen - 1; i > -1; i-- {
   745  			melds = append(melds, temp[i])
   746  		}
   747  	}
   748  	bombs := GetBombs(cards)
   749  	melds = append(melds, bombs...)
   750  	return melds
   751  }
   752  
   753  // 获取大于飞机带大翼的牌
   754  func GetGreaterThanTrioPairChain(preTrioPairChain []int, cards []int) [][]int {
   755  	analyzer := new(LandlordAnalyzer)
   756  	analyzer.Analyze(cards)
   757  
   758  	melds := [][]int{}
   759  	preTrioPairChainLen := len(preTrioPairChain)
   760  	preAirplaneChainLen := preTrioPairChainLen / 5 * 3
   761  	cardValue := CardValue(preTrioPairChain[0])
   762  	temp, tempLen := [][]int{}, 0
   763  	if !analyzer.hasAirplaneChain {
   764  		goto END
   765  	}
   766  	for _, airplaneChain := range analyzer.airplaneChains {
   767  		airplaneChainLen := len(airplaneChain)
   768  		for i := 0; i < airplaneChainLen/3; i++ {
   769  			cardValue2 := CardValue(airplaneChain[i*3])
   770  			if i*3+preAirplaneChainLen <= airplaneChainLen && cardValue2 > cardValue {
   771  				valueMap := GetCardValueMap(airplaneChain[i*3 : i*3+preAirplaneChainLen])
   772  				remain := RemoveCardByValue(cards, valueMap)
   773  
   774  				analyzer2 := new(LandlordAnalyzer)
   775  				analyzer2.Analyze(remain)
   776  				if !analyzer2.hasPair {
   777  					continue
   778  				}
   779  				m, pairs := make(map[int]bool), [][]int{}
   780  				pairsLen := len(analyzer2.pairs)
   781  				for i := pairsLen - 1; i > -1; i-- {
   782  					pair := analyzer2.pairs[i]
   783  					if !m[CardValue(pair[0])] {
   784  						pairs = append(pairs, pair)
   785  						m[CardValue(pair[0])] = true
   786  					}
   787  				}
   788  				pairs = ReSortHint(Pair, pairs, remain)
   789  				pairsLen = len(pairs)
   790  				if pairsLen >= preTrioPairChainLen/5 {
   791  					trioPairChain := append([]int{}, airplaneChain[i*3:i*3+preAirplaneChainLen]...)
   792  					pairChain := []int{}
   793  					for _, pair := range pairs[:preTrioPairChainLen/5] {
   794  						pairChain = append(pairChain, pair...)
   795  					}
   796  					trioPairChain = append(trioPairChain, pairChain...)
   797  					temp = append(temp, trioPairChain)
   798  				}
   799  			} else {
   800  				break
   801  			}
   802  		}
   803  	}
   804  	tempLen = len(temp)
   805  	for i := tempLen - 1; i > -1; i-- {
   806  		melds = append(melds, temp[i])
   807  	}
   808  END:
   809  	bombs := GetBombs(cards)
   810  	melds = append(melds, bombs...)
   811  	return melds
   812  }
   813  
   814  // 获取大于炸弹的牌
   815  func GetGreaterThanBomb(cardValue int, cards []int) [][]int {
   816  	analyzer := new(LandlordAnalyzer)
   817  	analyzer.Analyze(cards)
   818  
   819  	melds := [][]int{}
   820  	if analyzer.hasBomb {
   821  		bombsLen := len(analyzer.bombs)
   822  		for i := bombsLen - 1; i > -1; i-- {
   823  			cardValue2 := CardValue(analyzer.bombs[i][0])
   824  			if cardValue2 > cardValue {
   825  				melds = append(melds, analyzer.bombs[i])
   826  			}
   827  		}
   828  	}
   829  	if analyzer.hasKingBomb {
   830  		melds = append(melds, []int{53, 52})
   831  	}
   832  	return melds
   833  }
   834  
   835  // 获取单张
   836  func GetSoloByCount(cards []int) []int {
   837  	analyzer := new(LandlordAnalyzer)
   838  	analyzer.Analyze(cards)
   839  
   840  	remain := append([]int{}, cards...)
   841  	if analyzer.hasSoloChain {
   842  		for _, soloChain := range analyzer.soloChains {
   843  			remain = common.Remove(remain, soloChain)
   844  		}
   845  	}
   846  	cardValueMarker := make(map[int]int)
   847  	for _, card := range remain {
   848  		cardValueMarker[CardValue(card)]++
   849  	}
   850  	count := 1
   851  NEXT:
   852  	for cardValue := 3; cardValue < 18; cardValue++ {
   853  		if cardValueMarker[cardValue] == count {
   854  			temp := GetCardsByValue(remain, cardValue)
   855  			return temp[:1]
   856  		}
   857  	}
   858  	count++
   859  	if count < 5 {
   860  		goto NEXT
   861  	}
   862  	if analyzer.hasSoloChain {
   863  		temp := common.Remove(cards, remain)
   864  		sort.Ints(temp)
   865  		return temp[:1]
   866  	}
   867  	return []int{}
   868  }
   869  
   870  // 获取对子
   871  func GetPairByCount(cards []int) []int {
   872  	analyzer := new(LandlordAnalyzer)
   873  	analyzer.Analyze(cards)
   874  
   875  	count := 2
   876  NEXT:
   877  	for cardValue := 3; cardValue < 16; cardValue++ {
   878  		if analyzer.cardValueMarker[cardValue] == count {
   879  			temp := GetCardsByValue(analyzer.cards, cardValue)
   880  			return temp[:2]
   881  		}
   882  	}
   883  	count++
   884  	if count < 5 {
   885  		goto NEXT
   886  	}
   887  	return []int{}
   888  }