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 }