package tienlen import ( "math/rand" "slices" "sort" ) const ( Tienlen_Pass int = iota //nil Single //1 单张 Twin //2 对子 Straight //3 顺子 ColorStraight //4 同花顺 Straight_Twin //5 连对(双顺 Triple //6 三张 Four_Bomb //7 炸弹 Straight_Triple //8三顺 (333,444) Plane_Single //9三带单 444 555 6 7 8 9带4张牌 最后一首可以带小于等于4张牌 Plane_Twin //10三带双 ) // 不同牌分值 const ( Score1 int32 = 1 Score5 int32 = 5 Score10 int32 = 10 Score15 int32 = 15 Score20 int32 = 20 Score25 int32 = 25 ) // 打到底不同牌分值百分比 const ( Score2End5 int32 = 50 Score2End10 int32 = 100 Score2End15 int32 = 150 Score2End20 int32 = 200 Score2End25 int32 = 250 ) // Color 黑桃0 梅花1 方片2 紅桃3 func Color(c int32) int { return int(c) / PER_CARD_COLOR_MAX } func Value(c int32) int { return int(c) % PER_CARD_COLOR_MAX } func ValueStr(c int32) int { if int(c+3)%PER_CARD_COLOR_MAX == 0 { return PER_CARD_COLOR_MAX } return int(c+3) % PER_CARD_COLOR_MAX } // CmpCard 比逻辑大小 func CmpCard(a, b int32) bool { if Value(a) > Value(b) { return true } else if Value(a) == Value(b) { if Color(a) > Color(b) { return true } } return false } func IsSingle(cards []int32) bool { //单张 if len(cards) == 1 { return true } return false } func IsTwin(cards []int32) bool { //对子 if len(cards) == 2 { if Value(cards[0]) == Value(cards[1]) { return true } } return false } // IsStraight 顺子 // 至少3张,且不带2 func IsStraight(cards []int32) bool { //顺子,至少3张 if len(cards) < 3 || len(cards) > 12 { return false } tmpCards := []int{} for _, card := range cards { if Value(card) == Card_Value_2 { return false } tmpCards = append(tmpCards, Value(card)) } sort.Ints(tmpCards) for i := 0; i < len(tmpCards)-1; i++ { card := tmpCards[i] nextCard := tmpCards[i+1] if nextCard-card != 1 { //不相邻 return false } } //fmt.Println("顺子排序:", tmpCards) return true } // IsColorStraight 同花顺 // 是顺子又是同花 func IsColorStraight(cards []int32) bool { // 先是顺子 if !IsStraight(cards) { return false } c := Color(cards[0]) for _, card := range cards { if c != Color(card) { return false } } return true } // IsStraightTwin 双顺 // 最少两连,且不带2 func IsStraightTwin(cards []int32) bool { if len(cards) < 4 || len(cards)%2 != 0 { return false } tmpCards := []int{} for _, card := range cards { if Value(card) == Card_Value_2 { return false } tmpCards = append(tmpCards, Value(card)) } sort.Ints(tmpCards) for i := 0; i < len(tmpCards); i += 2 { card := tmpCards[i] nextCard := tmpCards[i+1] if card != nextCard { return false } if i < len(cards)-2 { if tmpCards[i+2]-card != 1 { return false } if card == Card_Value_2 || nextCard == Card_Value_2 { //2不能加入顺子中 return false } } } return true } // IsTriple 三张 func IsTriple(cards []int32) bool { if len(cards)%3 != 0 { return false } if Value(cards[0]) != Value(cards[1]) { return false } if Value(cards[1]) != Value(cards[2]) { return false } return true } // IsFourBomb 炸弹 // 4张相同点数的牌 func IsFourBomb(cards []int32) bool { if len(cards) != 4 { return false } if Value(cards[0]) != Value(cards[1]) { return false } if Value(cards[1]) != Value(cards[2]) { return false } if Value(cards[2]) != Value(cards[3]) { return false } return true } // IsStraightTriple 三顺 // 至少两连,顺子不带2 func IsStraightTriple(cards []int32) bool { //三顺 if len(cards) == 0 { return false } if len(cards)%3 != 0 { return false } mapSTriple := make(map[int32]int32) for _, card := range cards { if Value(card) == Card_Value_2 { return false } mapSTriple[int32(Value(card))]++ } if len(mapSTriple) > 0 { valueSTriple := []int32{} for card, num := range mapSTriple { if num == 3 { valueSTriple = append(valueSTriple, card) } } if len(valueSTriple) != len(cards)/3 { return false } if len(valueSTriple) > 0 { sort.Slice(valueSTriple, func(i, j int) bool { if valueSTriple[i] > valueSTriple[j] { return false } return true }) tmpPairs := FindOneStraightWithWidth(len(valueSTriple), valueSTriple) if len(tmpPairs) > 0 { return true } } } return false } // IsPlaneSingle 飞机带单包括三带一(只能最后一手出牌) func IsPlaneSingle(cards []int32) bool { if len(cards) < 4 { return false } mapSTriple := make(map[int32]int32) if len(cards) == 4 { for _, card := range cards { mapSTriple[int32(Value(card))]++ } } else { for _, card := range cards { if Value(card) != Card_Value_2 { mapSTriple[int32(Value(card))]++ } } } if len(mapSTriple) > 0 { valueSTriple := []int32{} for card, num := range mapSTriple { if num == 3 { valueSTriple = append(valueSTriple, card) } if num == 4 { //有炸弹不让出 return false } } if len(valueSTriple) > 0 { sort.Slice(valueSTriple, func(i, j int) bool { if valueSTriple[i] > valueSTriple[j] { return false } return true }) for i := len(valueSTriple); i > 0; i-- { tmpPairs := FindOneStraightWithWidth(i, valueSTriple) if len(tmpPairs) > 0 && len(tmpPairs)*5 > len(cards) { return true } } } } return false } func IsPlaneTwin(cards []int32) bool { //飞机带双包括三带二 if len(cards) == 0 { return false } if len(cards)%5 != 0 { return false } mapSTriple := make(map[int32]int32) if len(cards) == 5 { for _, card := range cards { mapSTriple[int32(Value(card))]++ } } else { for _, card := range cards { if Value(card) != Card_Value_2 { mapSTriple[int32(Value(card))]++ } } } if len(mapSTriple) > 0 { valueSTriple := []int32{} for card, num := range mapSTriple { if num == 3 { valueSTriple = append(valueSTriple, card) } if num == 4 { //有炸弹不让出 return false } } if len(valueSTriple) > 0 { sort.Slice(valueSTriple, func(i, j int) bool { if valueSTriple[i] > valueSTriple[j] { return false } return true }) for i := len(valueSTriple); i > 0; i-- { tmpPairs := FindOneStraightWithWidth(i, valueSTriple) if len(tmpPairs) > 0 && len(tmpPairs)*5 == len(cards) { return true } } } } return false } // 飞机带双 找头 长度 func FindPlaneTwinHead(cards []int32) (int32, int) { if len(cards) == 0 { return InvalideCard, 0 } if len(cards)%5 != 0 { return InvalideCard, 0 } mapSTriple := make(map[int32]int32) for _, card := range cards { mapSTriple[int32(Value(card))]++ } if len(mapSTriple) > 0 { valueSTriple := []int32{} for card, num := range mapSTriple { if num == 3 { valueSTriple = append(valueSTriple, card) } if num == 4 { //有炸弹不让出 return InvalideCard, 0 } } if len(valueSTriple) > 0 { sort.Slice(valueSTriple, func(i, j int) bool { if valueSTriple[i] > valueSTriple[j] { return false } return true }) for i := len(valueSTriple); i > 0; i-- { tmpPairs := FindOneStraightWithWidth(i, valueSTriple) if len(tmpPairs) > 0 && len(tmpPairs)*5 == len(cards) { return tmpPairs[len(tmpPairs)-1], len(tmpPairs) } } } } return InvalideCard, 0 } // 飞机带单 找头 长度 func FindPlaneSingleHead(cards []int32) (int32, int) { if len(cards) == 0 { return InvalideCard, 0 } mapSTriple := make(map[int32]int32) for _, card := range cards { mapSTriple[int32(Value(card))]++ } if len(mapSTriple) > 0 { valueSTriple := []int32{} for card, num := range mapSTriple { if num == 3 { valueSTriple = append(valueSTriple, card) } if num == 4 { //有炸弹不让出 return InvalideCard, 0 } } if len(valueSTriple) > 0 { sort.Slice(valueSTriple, func(i, j int) bool { if valueSTriple[i] > valueSTriple[j] { return false } return true }) for i := len(valueSTriple); i > 0; i-- { tmpPairs := FindOneStraightWithWidth(i, valueSTriple) if len(tmpPairs) > 0 && len(tmpPairs)*5 > len(cards) { return tmpPairs[len(tmpPairs)-1], len(tmpPairs) } } } } return InvalideCard, 0 } // RulePopEnable 牌型判断 // bool:是否找到牌型 // int:牌型 func RulePopEnable(cards []int32) (bool, int) { isRule := false ruleType := Tienlen_Pass switch len(cards) { case 1: isRule = true ruleType = Single case 2: if IsTwin(cards) { isRule = true ruleType = Twin } case 3: if IsColorStraight(cards) { //同花顺 isRule = true ruleType = ColorStraight } else if IsStraight(cards) { //顺子 isRule = true ruleType = Straight } else if IsTriple(cards) { //三张 isRule = true ruleType = Triple } case 4: if IsColorStraight(cards) { //同花顺 isRule = true ruleType = ColorStraight } else if IsStraight(cards) { //顺子 isRule = true ruleType = Straight } else if IsFourBomb(cards) { //炸弹 isRule = true ruleType = Four_Bomb } else if IsStraightTwin(cards) { //连对(双顺) isRule = true ruleType = Straight_Twin } default: if IsColorStraight(cards) { //同花顺 isRule = true ruleType = ColorStraight } else if IsStraight(cards) { //顺子 isRule = true ruleType = Straight } else if IsStraightTwin(cards) { //连对(双顺) isRule = true ruleType = Straight_Twin } } return isRule, ruleType } // RulePopEnable_yl 娱乐版牌型判断 // 多了三顺,飞机 func RulePopEnable_yl(cards []int32) (bool, int) { //娱乐场 isRule := false ruleType := Tienlen_Pass switch len(cards) { case 1: isRule = true ruleType = Single case 2: if IsTwin(cards) { isRule = true ruleType = Twin } case 3: if IsColorStraight(cards) { //同花顺 isRule = true ruleType = ColorStraight } else if IsStraight(cards) { //顺子 isRule = true ruleType = Straight } else if IsTriple(cards) { //三张 isRule = true ruleType = Triple } case 4: if IsColorStraight(cards) { //同花顺 isRule = true ruleType = ColorStraight } else if IsStraight(cards) { //顺子 isRule = true ruleType = Straight } else if IsFourBomb(cards) { //炸弹 isRule = true ruleType = Four_Bomb } else if IsStraightTwin(cards) { //连对(双顺) isRule = true ruleType = Straight_Twin } else if IsPlaneSingle(cards) { //飞机带单 isRule = true ruleType = Plane_Single } break default: if IsColorStraight(cards) { //同花顺 isRule = true ruleType = ColorStraight } else if IsStraight(cards) { //顺子 isRule = true ruleType = Straight } else if IsStraightTwin(cards) { //连对(双顺) isRule = true ruleType = Straight_Twin } else if IsStraightTriple(cards) { //三顺 isRule = true ruleType = Straight_Triple } else if IsPlaneTwin(cards) { //飞机带双 isRule = true ruleType = Plane_Twin } else if IsPlaneSingle(cards) { //飞机带单 isRule = true ruleType = Plane_Single } break } return isRule, ruleType } // CanDel 跟牌 // lastCards 上家出牌 // cards 当前出牌 // toEnd 打到底 // return :可压住,是否炸,炸多少分 func CanDel(lastCards, cards []int32, toEnd bool) (bool, bool, int32) { isBomb := false bombScore := int32(0) if len(lastCards) == 0 || len(cards) == 0 { return false, isBomb, bombScore } for _, card := range lastCards { if card == InvalideCard { return false, isBomb, bombScore } } for _, card := range cards { if card == InvalideCard { return false, isBomb, bombScore } } sort.Slice(lastCards, func(i, j int) bool { if Value(lastCards[i]) > Value(lastCards[j]) { return false } else if Value(lastCards[i]) == Value(lastCards[j]) { return Color(lastCards[i]) < Color(lastCards[j]) } return true }) sort.Slice(cards, func(i, j int) bool { if Value(cards[i]) > Value(cards[j]) { return false } else if Value(cards[i]) == Value(cards[j]) { return Color(cards[i]) < Color(cards[j]) } return true }) lastIsRule, lastRuleType := RulePopEnable(lastCards) isRule, ruleType := RulePopEnable(cards) //fmt.Println("isRule:", isRule, " ruleType:", ruleType) if isRule && lastIsRule { switch ruleType { case Single: //单张只能压单张 if lastRuleType == Single { lastCard := lastCards[0] card := cards[0] if Value(card) > Value(lastCard) { return true, isBomb, bombScore } else if Value(card) == Value(lastCard) { return Color(card) > Color(lastCard), isBomb, bombScore } } case Twin: //对子只能压对子 if lastRuleType == Twin { lastCard := lastCards[len(lastCards)-1] card := cards[len(cards)-1] if Value(card) > Value(lastCard) { return true, isBomb, bombScore } else if Value(card) == Value(lastCard) { return Color(card) > Color(lastCard), isBomb, bombScore } } case Straight: //非同花顺子只能压非同花顺子 if len(cards) == len(lastCards) && lastRuleType == Straight { lastCard := lastCards[len(lastCards)-1] card := cards[len(cards)-1] if Value(card) > Value(lastCard) { return true, isBomb, bombScore } else if Value(card) == Value(lastCard) { return Color(card) > Color(lastCard), isBomb, bombScore } } case ColorStraight: //同花顺子可压: 同花顺、非同花顺子 if len(cards) == len(lastCards) && (lastRuleType == ColorStraight || lastRuleType == Straight) { lastCard := lastCards[len(lastCards)-1] card := cards[len(cards)-1] if Value(card) > Value(lastCard) { return true, isBomb, bombScore } else if Value(card) == Value(lastCard) { return Color(card) > Color(lastCard), isBomb, bombScore } } case Straight_Twin: //连对特殊处理下!!! twinNum := len(cards) switch twinNum { case 4: //二连对只能压二连对 if len(cards) == len(lastCards) && lastRuleType == Straight_Twin { lastCard := lastCards[len(lastCards)-1] card := cards[len(cards)-1] if Value(card) > Value(lastCard) { return true, isBomb, bombScore } else if Value(card) == Value(lastCard) { return Color(card) > Color(lastCard), isBomb, bombScore } } case 6: //三连对可压:三连对、单2 lastCard := lastCards[len(lastCards)-1] if lastRuleType == Straight_Twin { if len(lastCards) == 6 { //三连对 score := Score15 if toEnd { score = Score2End15 } card := cards[len(cards)-1] if Value(card) > Value(lastCard) { return true, true, score } else if Value(card) == Value(lastCard) { return Color(card) > Color(lastCard), true, score } } } else if lastRuleType == Single && Value(lastCard) == Card_Value_2 { //单2 score := Score10 if lastCard == 51 || lastCard == 38 { //红2 10分 if toEnd { score = Score2End10 } } else if lastCard == 25 || lastCard == 12 { //黑2 5分 score = Score5 if toEnd { score = Score2End5 } } return true, true, score } case 8: //四连对可压:四连对、三连对、对子2、单2 lastCard := lastCards[len(lastCards)-1] if lastRuleType == Straight_Twin { if len(lastCards) == 8 { //四连对 score := Score20 if toEnd { score = Score2End20 } card := cards[len(cards)-1] if Value(card) > Value(lastCard) { return true, true, score } else if Value(card) == Value(lastCard) { return Color(card) > Color(lastCard), true, score } } else if len(lastCards) == 6 { //三连对 score := Score15 if toEnd { score = Score2End15 } return true, true, score } } else if lastRuleType == Twin && Value(lastCard) == Card_Value_2 { //对子2 tmpScore := int32(0) for _, card := range lastCards { if card == 51 || card == 38 { //红2 10分 if toEnd { tmpScore += Score2End10 } else { tmpScore += Score10 } } else if card == 25 || card == 12 { //黑2 5分 if toEnd { tmpScore += Score2End5 } else { tmpScore += Score5 } } } return true, true, tmpScore } else if lastRuleType == Single && Value(lastCard) == Card_Value_2 { //单2 score := Score10 if lastCard == 51 || lastCard == 38 { //红2 10分 if toEnd { score = Score2End10 } return true, true, score } else if lastCard == 25 || lastCard == 12 { //黑2 5分 score = Score5 if toEnd { score = Score2End5 } return true, true, score } } case 10: //五连对可压:五连对、四连对、三连对、对子2、单2 lastCard := lastCards[len(lastCards)-1] if lastRuleType == Straight_Twin { if len(lastCards) == 10 { //五连对 score := Score25 if toEnd { score = Score2End25 } card := cards[len(cards)-1] if Value(card) > Value(lastCard) { return true, true, score } else if Value(card) == Value(lastCard) { return Color(card) > Color(lastCard), true, score } } else if len(lastCards) == 8 { //四连对 score := Score20 if toEnd { score = Score2End20 } return true, true, score } else if len(lastCards) == 6 { //三连对 score := Score15 if toEnd { score = Score2End15 } return true, true, score } } else if lastRuleType == Twin && Value(lastCard) == Card_Value_2 { //对子2 tmpScore := int32(0) for _, card := range lastCards { if card == 51 || card == 38 { //红2 10分 if toEnd { tmpScore += Score2End10 } else { tmpScore += Score10 } } else if card == 25 || card == 12 { //黑2 5分 if toEnd { tmpScore += Score2End5 } else { tmpScore += Score5 } } } return true, true, tmpScore } else if lastRuleType == Single && Value(lastCard) == Card_Value_2 { //单2 score := Score10 if lastCard == 51 || lastCard == 38 { //红2 10分 if toEnd { score = Score2End10 } return true, true, score } else if lastCard == 25 || lastCard == 12 { //黑2 5分 score = Score5 if toEnd { score = Score2End5 } return true, true, score } } } case Triple: //三张只能压三张 if lastRuleType == Triple { lastCard := lastCards[0] card := cards[0] if Value(card) > Value(lastCard) { return true, false, 0 } else if Value(card) == Value(lastCard) { return Color(card) > Color(lastCard), false, 0 } } case Four_Bomb: //炸弹可压:炸弹、三连对、对子2、单2 score := Score2End20 if lastRuleType == Four_Bomb { //炸弹 if !toEnd { score = Score20 } lastCard := lastCards[0] card := cards[0] if Value(card) > Value(lastCard) { return true, true, score } } else if lastRuleType == Straight_Twin { if len(lastCards) == 6 { //三连对 if !toEnd { score = Score15 } return true, true, score } } else if lastRuleType == Twin && Value(lastCards[0]) == Card_Value_2 { if !toEnd { tmpScore := int32(0) for _, card := range lastCards { if card == 51 || card == 38 { //红2 10分 tmpScore += Score10 } else if card == 25 || card == 12 { //黑2 5分 tmpScore += Score5 } } return true, true, tmpScore } return true, true, score } else if lastRuleType == Single && Value(lastCards[0]) == Card_Value_2 { if lastCards[0] == 51 || lastCards[0] == 38 { //红2 10分 if !toEnd { score = Score10 } return true, true, score } else if lastCards[0] == 25 || lastCards[0] == 12 { //黑2 5分 if !toEnd { score = Score5 } return true, true, score } } } } return false, false, 0 } // return :可压住,是否炸,炸多少分 func CanDel_yl(lastCards, cards []int32, toEnd bool) (bool, bool, int32) { isBomb := false bombScore := int32(0) if len(lastCards) == 0 || len(cards) == 0 { return false, isBomb, bombScore } for _, card := range lastCards { if card == InvalideCard { return false, isBomb, bombScore } } for _, card := range cards { if card == InvalideCard { return false, isBomb, bombScore } } sort.Slice(lastCards, func(i, j int) bool { if Value(lastCards[i]) > Value(lastCards[j]) { return false } else if Value(lastCards[i]) == Value(lastCards[j]) { return Color(lastCards[i]) < Color(lastCards[j]) } return true }) sort.Slice(cards, func(i, j int) bool { if Value(cards[i]) > Value(cards[j]) { return false } else if Value(cards[i]) == Value(cards[j]) { return Color(cards[i]) < Color(cards[j]) } return true }) lastIsRule, lastRuleType := RulePopEnable_yl(lastCards) isRule, ruleType := RulePopEnable_yl(cards) //fmt.Println("CanDel_yl: isRule:", isRule, " ruleType:", ruleType) if isRule && lastIsRule { switch ruleType { case Single: //单张只能压单张 if lastRuleType == Single { lastCard := lastCards[0] card := cards[0] if Value(card) > Value(lastCard) { return true, isBomb, bombScore } else if Value(card) == Value(lastCard) { return Color(card) > Color(lastCard), isBomb, bombScore } } case Twin: //对子只能压对子 if lastRuleType == Twin { lastCard := lastCards[len(lastCards)-1] card := cards[len(cards)-1] if Value(card) > Value(lastCard) { return true, isBomb, bombScore } else if Value(card) == Value(lastCard) { return Color(card) > Color(lastCard), isBomb, bombScore } } case Straight: //非同花顺子只能压非同花顺子 if len(cards) == len(lastCards) && lastRuleType == Straight { lastCard := lastCards[len(lastCards)-1] card := cards[len(cards)-1] if Value(card) > Value(lastCard) { return true, isBomb, bombScore } else if Value(card) == Value(lastCard) { return Color(card) > Color(lastCard), isBomb, bombScore } } case ColorStraight: //同花顺子可压: 同花顺、非同花顺子 if len(cards) == len(lastCards) && (lastRuleType == ColorStraight || lastRuleType == Straight) { lastCard := lastCards[len(lastCards)-1] card := cards[len(cards)-1] if Value(card) > Value(lastCard) { return true, isBomb, bombScore } else if Value(card) == Value(lastCard) { return Color(card) > Color(lastCard), isBomb, bombScore } } case Straight_Twin: //连对特殊处理下!!! twinNum := len(cards) switch twinNum { case 4: //二连对只能压二连对 if len(cards) == len(lastCards) && lastRuleType == Straight_Twin { lastCard := lastCards[len(lastCards)-1] card := cards[len(cards)-1] if Value(card) > Value(lastCard) { return true, isBomb, bombScore } else if Value(card) == Value(lastCard) { return Color(card) > Color(lastCard), isBomb, bombScore } } case 6: //三连对可压:三连对、单2 lastCard := lastCards[len(lastCards)-1] if lastRuleType == Straight_Twin { if len(lastCards) == 6 { //三连对 score := Score15 if toEnd { score = Score2End15 } card := cards[len(cards)-1] if Value(card) > Value(lastCard) { return true, true, score } else if Value(card) == Value(lastCard) { return Color(card) > Color(lastCard), true, score } } } else if lastRuleType == Single && Value(lastCard) == Card_Value_2 { //单2 score := Score10 if lastCard == 51 || lastCard == 38 { //红2 10分 if toEnd { score = Score2End10 } return true, true, score } else if lastCard == 25 || lastCard == 12 { //黑2 5分 score = Score5 if toEnd { score = Score2End5 } return true, true, score } } case 8: //四连对可压:四连对、三连对、对子2、单2 lastCard := lastCards[len(lastCards)-1] if lastRuleType == Straight_Twin { if len(lastCards) == 8 { //四连对 score := Score20 if toEnd { score = Score2End20 } card := cards[len(cards)-1] if Value(card) > Value(lastCard) { return true, true, score } else if Value(card) == Value(lastCard) { return Color(card) > Color(lastCard), true, score } } else if len(lastCards) == 6 { //三连对 score := Score15 if toEnd { score = Score2End15 } return true, true, score } } else if lastRuleType == Twin && Value(lastCard) == Card_Value_2 { //对子2 tmpScore := int32(0) for _, card := range lastCards { if card == 51 || card == 38 { //红2 10分 if toEnd { tmpScore += Score2End10 } else { tmpScore += Score10 } } else if card == 25 || card == 12 { //黑2 5分 if toEnd { tmpScore += Score2End5 } else { tmpScore += Score5 } } } return true, true, tmpScore } else if lastRuleType == Single && Value(lastCard) == Card_Value_2 { //单2 score := Score10 if lastCard == 51 || lastCard == 38 { //红2 10分 if toEnd { score = Score2End10 } return true, true, score } else if lastCard == 25 || lastCard == 12 { //黑2 5分 score = Score5 if toEnd { score = Score2End5 } return true, true, score } } case 10: //五连对可压:五连对、四连对、三连对、对子2、单2 lastCard := lastCards[len(lastCards)-1] if lastRuleType == Straight_Twin { if len(lastCards) == 10 { //五连对 score := Score25 if toEnd { score = Score2End25 } card := cards[len(cards)-1] if Value(card) > Value(lastCard) { return true, true, score } else if Value(card) == Value(lastCard) { return Color(card) > Color(lastCard), true, score } } else if len(lastCards) == 8 { //四连对 score := Score20 if toEnd { score = Score2End20 } return true, true, score } else if len(lastCards) == 6 { //三连对 score := Score15 if toEnd { score = Score2End15 } return true, true, score } } else if lastRuleType == Twin && Value(lastCard) == Card_Value_2 { //对子2 tmpScore := int32(0) for _, card := range lastCards { if card == 51 || card == 38 { //红2 10分 if toEnd { tmpScore += Score2End10 } else { tmpScore += Score10 } } else if card == 25 || card == 12 { //黑2 5分 if toEnd { tmpScore += Score2End5 } else { tmpScore += Score5 } } } return true, true, tmpScore } else if lastRuleType == Single && Value(lastCard) == Card_Value_2 { //单2 score := Score10 if lastCard == 51 || lastCard == 38 { //红2 10分 if toEnd { score = Score2End10 } return true, true, score } else if lastCard == 25 || lastCard == 12 { //黑2 5分 score = Score5 if toEnd { score = Score2End5 } return true, true, score } } } case Triple: //三张只能压三张 if lastRuleType == Triple { lastCard := lastCards[0] card := cards[0] if Value(card) > Value(lastCard) { return true, false, 0 } else if Value(card) == Value(lastCard) { return Color(card) > Color(lastCard), false, 0 } } case Straight_Triple: //三顺只能压三顺,或者张数相同的飞机带单飞机带双 if len(lastCards) == len(cards) { if lastRuleType == Straight_Triple { lastCard := lastCards[0] card := cards[0] if Value(card) > Value(lastCard) { return true, false, 0 } else if Value(card) == Value(lastCard) { return Color(card) > Color(lastCard), false, 0 } } else if lastRuleType == Plane_Single || lastRuleType == Plane_Twin { lastCardValue, lastPlaneLen := FindPlaneSingleHead(lastCards) cardValue, planeLen := FindPlaneSingleHead(cards) if lastCardValue != InvalideCard && cardValue != InvalideCard && lastPlaneLen <= planeLen && cardValue > lastCardValue { return true, false, 0 } else { return false, false, 0 } } } case Plane_Twin: //飞机带双只能压飞机带双 if lastRuleType == Plane_Twin || lastRuleType == Plane_Single { lastCardValue, lastPlaneLen := FindPlaneTwinHead(lastCards) cardValue, planeLen := FindPlaneTwinHead(cards) if lastCardValue != InvalideCard && cardValue != InvalideCard && len(lastCards) == len(cards) && lastPlaneLen <= planeLen && cardValue > lastCardValue { return true, false, 0 } else { return false, false, 0 } } case Plane_Single: //飞机带单只能压飞机带单 if lastRuleType == Plane_Single || lastRuleType == Plane_Twin { lastCardValue, lastPlaneLen := FindPlaneSingleHead(lastCards) cardValue, planeLen := FindPlaneSingleHead(cards) if lastCardValue != InvalideCard && cardValue != InvalideCard && len(lastCards) == len(cards) && lastPlaneLen <= planeLen && cardValue > lastCardValue { return true, false, 0 } else { return false, false, 0 } } case Four_Bomb: //炸弹可压:炸弹、飞机带双,飞机带单、三顺、三张、顺子、三连对以下的对子、单张 score := Score20 if toEnd { score = Score2End20 } switch lastRuleType { case Four_Bomb: lastCard := lastCards[0] card := cards[0] if Value(card) > Value(lastCard) { return true, true, score } case Plane_Twin, Plane_Single, Straight_Triple, Triple, Straight, ColorStraight, Twin, Single: return true, true, score case Straight_Twin: if len(lastCards) == 6 || len(lastCards) == 4 { // 三连对、二连对 return true, true, score } } } } return false, false, 0 } func DelSliceInt32(sl []int32, v int32) []int32 { index := -1 for key, value := range sl { if value == v { index = key break } } if index != -1 { sl = append(sl[:index], sl[index+1:]...) } return sl } // 计算输家输分数百分比 func GetLoseScore(cards [HandCardNum]int32, toEnd bool) int32 { loseScore := int32(0) cpCards := []int32{} for _, card := range cards { if card != InvalideCard { cpCards = append(cpCards, card) } } //找单2 find2Num := 0 for i := 0; i < len(cpCards); i++ { card := cpCards[i] switch card { case HongTao2, FangPian2: if toEnd { loseScore += Score2End10 } else { loseScore += Score10 } cpCards = append(cpCards[:i], cpCards[i+1:]...) i-- find2Num++ case MeiHua2, HeiTao2: if toEnd { loseScore += Score2End5 } else { loseScore += Score5 } cpCards = append(cpCards[:i], cpCards[i+1:]...) i-- find2Num++ } } if find2Num >= 4 { //找到4个2?? return 0 } // 找炸弹 mapBomb := make(map[int32]int) for _, card := range cpCards { mapBomb[int32(Value(card))]++ } bombValue := []int32{} for card, num := range mapBomb { if num == 4 { bombValue = append(bombValue, card) } } if len(bombValue) > 0 { score := Score20 if toEnd { score = Score2End20 } for _, card := range bombValue { for i := int32(0); i < 4; i++ { cpCards = DelSliceInt32(cpCards, card+(i*PER_CARD_COLOR_MAX)) } } loseScore += int32(len(bombValue)) * score } //找五连 if len(cpCards) >= 10 { sort.Slice(cpCards, func(i, j int) bool { if cpCards[i] > cpCards[j] { return false } return true }) map5STwin := make(map[int32]int32) for _, card := range cpCards { map5STwin[int32(Value(card))]++ } Value5STwin := []int32{} for card, num := range map5STwin { if num >= 2 { Value5STwin = append(Value5STwin, card) } } sort.Slice(Value5STwin, func(i, j int) bool { if Value5STwin[i] > Value5STwin[j] { return false } return true }) if len(Value5STwin) > 0 { tmpPairs := FindOneStraightWithWidth(5, Value5STwin) if len(tmpPairs) > 0 { for _, card := range tmpPairs { delC := 0 for i := 0; i < len(cpCards); i++ { if cpCards[i] == InvalideCard { continue } if int32(Value(cpCards[i])) == card && (delC < 2) { //删除2次 delC++ cpCards = append(cpCards[:i], cpCards[i+1:]...) i-- continue } } } score := Score25 if toEnd { score = Score2End25 } loseScore += score } } } //找四连 if len(cpCards) >= 8 { sort.Slice(cpCards, func(i, j int) bool { if cpCards[i] > cpCards[j] { return false } return true }) map4STwin := make(map[int32]int32) for _, card := range cpCards { map4STwin[int32(Value(card))]++ } Value4STwin := []int32{} for card, num := range map4STwin { if num >= 2 { Value4STwin = append(Value4STwin, card) } } sort.Slice(Value4STwin, func(i, j int) bool { if Value4STwin[i] > Value4STwin[j] { return false } return true }) if len(Value4STwin) > 0 { tmpPairs := FindOneStraightWithWidth(4, Value4STwin) if len(tmpPairs) > 0 { for _, card := range tmpPairs { delC := 0 for i := 0; i < len(cpCards); i++ { if cpCards[i] != InvalideCard { if int32(Value(cpCards[i])) == card && (delC < 2) { //删除2次 delC++ cpCards = append(cpCards[:i], cpCards[i+1:]...) i-- continue } } } } score := Score20 if toEnd { score = Score2End20 } loseScore += score } } } //找三连 if len(cpCards) >= 6 { sort.Slice(cpCards, func(i, j int) bool { if cpCards[i] > cpCards[j] { return false } return true }) map3STwin := make(map[int32]int32) for _, card := range cpCards { map3STwin[int32(Value(card))]++ } Value3STwin := []int32{} for card, num := range map3STwin { if num >= 2 { Value3STwin = append(Value3STwin, card) } } sort.Slice(Value3STwin, func(i, j int) bool { if Value3STwin[i] > Value3STwin[j] { return false } return true }) if len(Value3STwin) > 0 { tmpPairs := FindOneStraightWithWidth(3, Value3STwin) if len(tmpPairs) > 0 { for _, card := range tmpPairs { delC := 0 for i := 0; i < len(cpCards); i++ { if cpCards[i] == InvalideCard { continue } if int32(Value(cpCards[i])) == card && (delC < 2) { //删除2次 delC++ cpCards = append(cpCards[:i], cpCards[i+1:]...) i-- continue } } } score := Score15 if toEnd { score = Score2End15 } loseScore += score } } } //再找三连 if len(cpCards) >= 6 { sort.Slice(cpCards, func(i, j int) bool { if cpCards[i] > cpCards[j] { return false } return true }) map3STwin := make(map[int32]int32) for _, card := range cpCards { map3STwin[int32(Value(card))]++ } Value3STwin := []int32{} for card, num := range map3STwin { if num >= 2 { Value3STwin = append(Value3STwin, card) } } sort.Slice(Value3STwin, func(i, j int) bool { if Value3STwin[i] > Value3STwin[j] { return false } return true }) if len(Value3STwin) > 0 { tmpPairs := FindOneStraightWithWidth(3, Value3STwin) if len(tmpPairs) > 0 { for _, card := range tmpPairs { delC := 0 for i := 0; i < len(cpCards); i++ { if cpCards[i] == InvalideCard { continue } if int32(Value(cpCards[i])) == card && (delC < 2) { //删除2次 delC++ cpCards = append(cpCards[:i], cpCards[i+1:]...) i-- continue } } } score := Score15 if toEnd { score = Score2End15 } loseScore += score } } } if !toEnd { //找单张 for _, card := range cpCards { if card != InvalideCard { loseScore++ } } } return loseScore } // 找一个固定长度的顺子 (2,3,4,5,6) 3-> [2,3,4] func FindOneStraightWithWidth(n int, pairs []int32) []int32 { if len(pairs) == 0 { return nil } lastKey := pairs[0] tempPair := []int32{lastKey} if n == 1 { return tempPair } for i := 1; i < len(pairs); i++ { if pairs[i]-lastKey == 1 { tempPair = append(tempPair, pairs[i]) } else { tempPair = []int32{pairs[i]} } if len(tempPair) == n { break } lastKey = pairs[i] } if len(tempPair) == n { return tempPair } return nil } // 找多个固定长度的顺子(2,3,4,5,6) 3-> [[2,3,4][3,4,5][4,5,6]] func FindStraightWithWidth(n int, pairs []int32) [][]int32 { if len(pairs) == 0 || n < 2 { return nil } var tempPairs [][]int32 lastKey := pairs[0] tempPair := []int32{lastKey} for i := 1; i < len(pairs); i++ { if pairs[i]-lastKey == 1 { tempPair = append(tempPair, pairs[i]) } else { tempPair = []int32{pairs[i]} } if len(tempPair) == n { tempPairs = append(tempPairs, tempPair) tempPair = []int32{} for j := n - 1; j > 0; j-- { tempPair = append(tempPair, pairs[i-j+1]) } } lastKey = pairs[i] } return tempPairs } func FindCardsFromCardsValue(cards, valueCards []int32, count int) []int32 { var ret []int32 for _, card := range valueCards { delC := 0 for i := 0; i < len(cards); i++ { if int32(Value(cards[i])) == card { //删除count次 delC++ ret = append(ret, cards[i]) } if delC >= count { break } } } return ret } // ///////////////////////////(天胡牌型)/////////////////////// // 判断13张牌里面是否有4个2炸弹 func Have2FourBomb(cards []int32) bool { if len(cards) == Hand_CardNum { for i := 0; i < len(cards); i++ { if Value(cards[i]) == Card_Value_2 { tmpInt := 0 for j := 0; j < len(cards); j++ { if Value(cards[i]) == Value(cards[j]) { tmpInt++ } } if tmpInt == 4 { return true } } } } return false } // 判断13张牌里面是否有6连对(单牌2不能带到连牌里) func Have6StraightTwin(cards []int32) bool { cpCards := []int32{} for _, card := range cards { if int32(Value(card)) != InvalideCard { cpCards = append(cpCards, card) } } if len(cpCards) == Hand_CardNum { sort.Slice(cpCards, func(i, j int) bool { if cpCards[i] > cpCards[j] { return false } return true }) map6STwin := make(map[int32]int32) for _, card := range cpCards { if Value(card) != Card_Value_2 { map6STwin[int32(Value(card))]++ } } if len(map6STwin) > 0 { Value6STwin := []int32{} for card, num := range map6STwin { if num >= 2 { Value6STwin = append(Value6STwin, card) } } if len(Value6STwin) > 0 { sort.Slice(Value6STwin, func(i, j int) bool { if Value6STwin[i] > Value6STwin[j] { return false } return true }) tmpPairs := FindOneStraightWithWidth(6, Value6STwin) if len(tmpPairs) == 6 { return true } } } } return false } // 判断13张牌里面是否有12顺(单牌2不能带到连牌里) func Have12Straight(cards []int32) bool { if len(cards) == Hand_CardNum { mapCard := make(map[int32]int) for _, card := range cards { if Value(card) != Card_Value_2 { mapCard[int32(Value(card))]++ } } if len(mapCard) == 12 { return true } } return false } // 随机获取一个天胡牌型 func GetTianHu() ([]int32, int) { var ret []int32 n := rand.Intn(3) switch n { case 0: // 4个2炸弹 ret = append(ret, []int32{51, 38, 25, 12}...) for i := 0; i < Hand_CardNum-4; i++ { for j := 0; j < 52; j++ { if !slices.Contains(ret, int32(j)) { ret = append(ret, int32(i)) break } } } case 1: // 6连对 i := rand.Int31n(7) n := i + 6 for ; i < n; i++ { cs := rand.Perm(4) ret = append(ret, []int32{int32(cs[0])*13 + i, int32(cs[1])*13 + i}...) } for i := 0; i < 52; i++ { if !slices.Contains(ret, int32(i)) { ret = append(ret, int32(i)) break } } case 2: // 12顺 for i := 0; i < 12; i++ { color := rand.Int31n(4) ret = append(ret, color*13+int32(i)) } for i := 0; i < 52; i++ { if !slices.Contains(ret, int32(i)) { ret = append(ret, int32(i)) break } } } return ret, n } // 根据最小牌值去推荐出牌 /*func RecommendCardsWithMinCard(cards []int32) []int32 { recmCards := []int32{} //排序 sort.Slice(cards, func(i, j int) bool { v_i := Value(cards[i]) v_j := Value(cards[j]) c_i := Color(cards[i]) c_j := Color(cards[j]) if v_i > v_j { return false } else if v_i == v_j { return c_i < c_j } return true }) //取手牌 cpCards := []int32{} for _, card := range cards { if card != InvalideCard { cpCards = append(cpCards, card) } } //取最小牌值 minCard := cpCards[0] for _, card := range cpCards { minCard = card break } //找顺子 recmCards = []int32{} findNum := 0 for _, card := range cpCards { if Value(card) == Value(minCard)+findNum && Value(card) != Card_Value_2 { recmCards = append(recmCards, card) findNum++ } else { break } } if len(recmCards) < 3 { //找二连对 recmCards = []int32{} find1 := 0 find2 := 0 for _, card := range cpCards { if Value(card) == Value(minCard) && Value(card) != Card_Value_2 && find1 < 2 { recmCards = append(recmCards, card) find1++ } if Value(card) == Value(minCard)+1 && Value(card) != Card_Value_2 && find2 < 2 { recmCards = append(recmCards, card) find2++ } } if len(recmCards) != 4 { //找三张 recmCards = []int32{} find3 := 0 for _, card := range cpCards { if Value(card) == Value(minCard) && Value(card) != Card_Value_2 && find3 < 3 { recmCards = append(recmCards, card) find3++ } } if len(recmCards) != 3 { //找对子 recmCards = []int32{} find4 := 0 for _, card := range cpCards { if Value(card) == Value(minCard) && Value(card) != Card_Value_2 && find4 < 2 { recmCards = append(recmCards, card) find4++ } } if len(recmCards) != 2 { // 找单张 recmCards = []int32{} recmCards = append(recmCards, minCard) } } } } if len(recmCards) == 0 { recmCards = append(recmCards, minCard) } return recmCards }*/ // 根据牌型牌数量最多去推荐出牌 /*func RecommendCardsWithCards(cards []int32) []int32 { recmCards := []int32{} //排序 sort.Slice(cards, func(i, j int) bool { v_i := Value(cards[i]) v_j := Value(cards[j]) c_i := Color(cards[i]) c_j := Color(cards[j]) if v_i > v_j { return false } else if v_i == v_j { return c_i < c_j } return true }) //取手牌 cpCards := []int32{} for _, card := range cards { if card != InvalideCard { cpCards = append(cpCards, card) } } //取最小牌值 minCard := cpCards[0] for _, card := range cpCards { minCard = card break } if IsStraight(cpCards) { //5顺直接返回 for _, card := range cpCards { recmCards = append(recmCards, card) } } else { if len(cpCards) >= 4 { //找4顺 map4Straight := make(map[int32]int32) for _, card := range cpCards { if Value(card) == Card_Value_2 { continue } map4Straight[int32(Value(card))]++ } if len(map4Straight) > 0 { Value4Straight := []int32{} for cardV, num := range map4Straight { if num >= 1 { Value4Straight = append(Value4Straight, cardV) } } sort.Slice(Value4Straight, func(i, j int) bool { if Value4Straight[i] > Value4Straight[j] { return false } return true }) if len(Value4Straight) > 0 { tmpPairs := FindOneStraightWithWidth(4, Value4Straight) if len(tmpPairs) > 0 { for _, cardV := range tmpPairs { delC := 0 for i := 0; i < len(cpCards); i++ { if int32(Value(cpCards[i])) == cardV && (delC < 1) { //找1次 delC++ recmCards = append(recmCards, cpCards[i]) cpCards = append(cpCards[:i], cpCards[i+1:]...) i-- continue } } } } } } } if len(cpCards) >= 4 { //找炸弹 mapBomb := make(map[int32]int) for _, card := range cpCards { mapBomb[int32(Value(card))]++ } if len(mapBomb) > 0 { bombValue := []int32{} for card, num := range mapBomb { if num == 4 { bombValue = append(bombValue, card) break //找一个炸弹就行 } } if len(bombValue) > 0 { for _, card := range bombValue { for i := 0; i < len(cpCards); i++ { cpCard := cpCards[i] if int32(Value(cpCard)) == card { recmCards = append(recmCards, cpCard) cpCards = append(cpCards[:i], cpCards[i+1:]...) i-- } } } } } } if len(cpCards) >= 4 { //找二连对 map2STwin := make(map[int32]int32) for _, card := range cpCards { if Value(card) == Card_Value_2 { continue } map2STwin[int32(Value(card))]++ } if len(map2STwin) > 0 { Value2STwin := []int32{} for card, num := range map2STwin { if num >= 2 { Value2STwin = append(Value2STwin, card) } } if len(Value2STwin) > 0 { sort.Slice(Value2STwin, func(i, j int) bool { if Value2STwin[i] > Value2STwin[j] { return false } return true }) tmpPairs := FindOneStraightWithWidth(2, Value2STwin) if len(tmpPairs) > 0 { for _, card := range tmpPairs { delC := 0 for i := 0; i < len(cpCards); i++ { if int32(Value(cpCards[i])) == card && (delC < 2) { //找2次 delC++ recmCards = append(recmCards, cpCards[i]) cpCards = append(cpCards[:i], cpCards[i+1:]...) i-- continue } } } } } } } if len(cpCards) >= 3 { //找3顺 map3Straight := make(map[int32]int32) for _, card := range cpCards { if Value(card) == Card_Value_2 { continue } map3Straight[int32(Value(card))]++ } if len(map3Straight) > 0 { Value3Straight := []int32{} for cardV, num := range map3Straight { if num >= 1 { Value3Straight = append(Value3Straight, cardV) } } sort.Slice(Value3Straight, func(i, j int) bool { if Value3Straight[i] > Value3Straight[j] { return false } return true }) if len(Value3Straight) > 0 { tmpPairs := FindOneStraightWithWidth(3, Value3Straight) if len(tmpPairs) > 0 { for _, cardV := range tmpPairs { delC := 0 for i := 0; i < len(cpCards); i++ { if int32(Value(cpCards[i])) == cardV && (delC < 1) { //找1次 delC++ recmCards = append(recmCards, cpCards[i]) cpCards = append(cpCards[:i], cpCards[i+1:]...) i-- continue } } } } } } } if len(cpCards) >= 3 { //找3张 mapTriple := make(map[int32]int32) for _, card := range cpCards { mapTriple[int32(Value(card))]++ } if len(mapTriple) > 0 { valueTriple := []int32{} for cardV, num := range mapTriple { if num >= 3 { valueTriple = append(valueTriple, cardV) } } if len(valueTriple) > 0 { tripleValue := valueTriple[0] delC := 0 for i := 0; i < len(cpCards); i++ { if int32(Value(cpCards[i])) == tripleValue && (delC < 3) { //找3次 delC++ recmCards = append(recmCards, cpCards[i]) cpCards = append(cpCards[:i], cpCards[i+1:]...) i-- continue } } } } } if len(cpCards) >= 2 { //找对子 mapTwin := make(map[int32]int32) for _, card := range cpCards { if Value(card) == Card_Value_2 { continue } mapTwin[int32(Value(card))]++ } if len(mapTwin) > 0 { ValueTwin := []int32{} for card, num := range mapTwin { if num >= 2 { ValueTwin = append(ValueTwin, card) } } if len(ValueTwin) > 0 { sort.Slice(ValueTwin, func(i, j int) bool { if ValueTwin[i] > ValueTwin[j] { return false } return true }) vTwin := ValueTwin[0] recmCount := 0 for i := 0; i < len(cpCards); i++ { card := cpCards[i] if vTwin == int32(Value(card)) && recmCount < 2 { recmCards = append(recmCards, card) recmCount++ cpCards = append(cpCards[:i], cpCards[i+1:]...) i-- } } } } } } if len(recmCards) == 0 { recmCards = append(recmCards, minCard) } return recmCards }*/ /*// 根据牌型牌数量最多去推荐出牌 func RecommendCardsWithCards_yl(cards []int32) []int32 { recmCards := []int32{} allTypeCards := map[int][]int32{} maxType := 0 maxNum := 0 //排序 sort.Slice(cards, func(i, j int) bool { v_i := Value(cards[i]) v_j := Value(cards[j]) c_i := Color(cards[i]) c_j := Color(cards[j]) if v_i > v_j { return false } else if v_i == v_j { return c_i < c_j } return true }) //取手牌 cpCards := []int32{} for _, card := range cards { if card != InvalideCard { cpCards = append(cpCards, card) } } //取最小牌值 minCard := cpCards[0] for _, card := range cpCards { minCard = card break } if IsStraight(cpCards) { //顺直接返回 for _, card := range cpCards { recmCards = append(recmCards, card) } maxType = Straight maxNum = len(recmCards) allTypeCards[maxType] = recmCards } else { isHave := true var tCards []int32 isHave, tCards = needMaxStraightTripleRandom(cpCards) if isHave { if len(tCards) > maxNum { maxNum = len(tCards) maxType = Straight_Triple } allTypeCards[Straight_Triple] = tCards } isHave, tCards = needMaxPlaneSingleRandom(cpCards) if isHave { //只有最后一手牌才能出 if len(tCards) == len(cpCards) { if len(tCards) > maxNum { maxNum = len(tCards) maxType = Plane_Single } allTypeCards[Plane_Single] = tCards } } isHave, tCards = needMaxPlaneTwinRandom(cpCards) if isHave { if len(tCards) > maxNum { maxNum = len(tCards) maxType = Plane_Twin } allTypeCards[Plane_Twin] = tCards } isHave, tCards = needMaxStraightTwinRandom(cpCards) if isHave { if len(tCards) > maxNum { maxNum = len(tCards) maxType = Straight_Twin } allTypeCards[Straight_Twin] = tCards } isHave, tCards = needMaxBoomRandom(cpCards) if isHave { if len(tCards) > maxNum { maxNum = len(tCards) maxType = Four_Bomb } allTypeCards[Four_Bomb] = tCards } isHave, tCards = needMaxTripleRandom(cpCards) if isHave { if len(tCards) > maxNum { maxNum = len(tCards) maxType = Triple } allTypeCards[Triple] = tCards } isHave, tCards = needMaxStraightRandom(cpCards) if isHave { if len(tCards) > maxNum { maxNum = len(tCards) maxType = Straight } allTypeCards[Straight] = tCards } isHave, tCards = needMaxTwinRandom(cpCards) if isHave { if len(tCards) > maxNum { maxNum = len(tCards) maxType = Twin } allTypeCards[Twin] = tCards } } if maxType == 0 { recmCards = append(recmCards, minCard) } else { recmCards = allTypeCards[maxType] } return recmCards }*/ // 根据上家牌去推荐出牌 压牌 func RecommendCardsWithLastCards(lastCards, cards []int32) []int32 { recmCards := []int32{} isHave := false isRule, ruleType := RulePopEnable(lastCards) cpCards := []int32{} for _, card := range cards { if card != InvalideCard { cpCards = append(cpCards, card) } } if isRule { switch ruleType { case Single: isHave, recmCards = needSingle(lastCards, cpCards) if !isHave { } case Twin: isHave, recmCards = needTwin(lastCards, cpCards) if !isHave { } case Straight: isHave, recmCards = needStraight(lastCards, cpCards) if !isHave { } case ColorStraight: isHave, recmCards = needColorStraight(lastCards, cpCards) if !isHave { } case Straight_Twin: isHave, recmCards = needStraightTwin(lastCards, cpCards) if !isHave { } case Triple: isHave, recmCards = needTriple(lastCards, cpCards) if !isHave { } case Four_Bomb: isHave, recmCards = needFourBomb(lastCards, cpCards) if !isHave { } } } return recmCards } // 根据上家牌去推荐出牌 func RecommendCardsWithLastCards_yl(lastCards, cards []int32) []int32 { recmCards := []int32{} isHave := false isRule, ruleType := RulePopEnable_yl(lastCards) cpCards := []int32{} for _, card := range cards { if card != InvalideCard { cpCards = append(cpCards, card) } } if isRule { switch ruleType { case Single: isHave, recmCards = needSingle(lastCards, cpCards) if !isHave { } case Twin: isHave, recmCards = needTwin(lastCards, cpCards) if !isHave { } case Straight: isHave, recmCards = needStraight(lastCards, cpCards) if !isHave { } case ColorStraight: isHave, recmCards = needColorStraight(lastCards, cpCards) if !isHave { } case Straight_Twin: isHave, recmCards = needStraightTwin(lastCards, cpCards) if !isHave { } case Triple: isHave, recmCards = needTriple(lastCards, cpCards) if !isHave { } case Four_Bomb: isHave, recmCards = needFourBomb(lastCards, cpCards) if !isHave { } case Straight_Triple: isHave, recmCards = needStraightTriple(lastCards, cpCards) if !isHave { } case Plane_Single: case Plane_Twin: } } return recmCards } // 需要单张 func needSingle(lastCards, cards []int32) (bool, []int32) { haveNeed := false needCards := []int32{} if len(cards) != 0 && IsSingle(lastCards) { sort.Slice(cards, func(i, j int) bool { if Value(cards[i]) > Value(cards[j]) { return false } return true }) for _, card := range cards { if card != InvalideCard { if Value(card) < Value(lastCards[0]) { continue } else { if Value(card) == Value(lastCards[0]) { if Color(card) > Color(lastCards[0]) { haveNeed = true needCards = append(needCards, card) break } } else if Value(card) > Value(lastCards[0]) { haveNeed = true needCards = append(needCards, card) break } } } } } return haveNeed, needCards } // 需要对子 func needTwin(lastCards, cards []int32) (bool, []int32) { haveNeed := false needCards := []int32{} if len(cards) != 0 && IsTwin(lastCards) { mapTwin := make(map[int32]int32) for _, card := range cards { if card != InvalideCard { mapTwin[int32(Value(card))]++ } } if len(mapTwin) > 0 { ValueTwin := []int32{} for card, num := range mapTwin { if num >= 2 { ValueTwin = append(ValueTwin, card) } } if len(ValueTwin) > 0 { sort.Slice(ValueTwin, func(i, j int) bool { if ValueTwin[i] > ValueTwin[j] { return false } return true }) sort.Slice(lastCards, func(i, j int) bool { if lastCards[i] > lastCards[j] { return false } return true }) needValue := -1 for _, card := range ValueTwin { if int(card) < Value(lastCards[1]) { continue } else { if int(card) == Value(lastCards[1]) { if Color(card) > Color(lastCards[1]) { haveNeed = true needValue = int(card) break } } else if int(card) > Value(lastCards[1]) { haveNeed = true needValue = int(card) break } } } if needValue != -1 { sort.Slice(cards, func(i, j int) bool { if cards[i] > cards[j] { return false } return true }) needNum := 0 for i := len(cards) - 1; i >= 0; i-- { if Value(cards[i]) == needValue && needNum < 2 { needNum++ needCards = append(needCards, cards[i]) } } } } } } return haveNeed, needCards } // 需要顺子 func needStraight(lastCards, cards []int32) (bool, []int32) { haveNeed := false needCards := []int32{} if len(cards) != 0 && IsStraight(lastCards) { sort.Slice(lastCards, func(i, j int) bool { if lastCards[i] > lastCards[j] { return false } return true }) sort.Slice(cards, func(i, j int) bool { if Value(cards[i]) > Value(cards[j]) { return false } return true }) mapS := make(map[int]int32) for _, card := range cards { if card != InvalideCard && Value(card) != Card_Value_2 { mapS[Value(card)]++ } } if len(mapS) > 0 { ValueS := []int32{} for card, num := range mapS { if num >= 1 { ValueS = append(ValueS, int32(card)) } } idx := len(lastCards) if len(ValueS) > 0 { sort.Slice(ValueS, func(i, j int) bool { if Value(ValueS[i]) > Value(ValueS[j]) { return false } return true }) tmpSMap := FindStraightWithWidth(idx, ValueS) if len(tmpSMap) != 0 { needCard := int32(-1) for _, sCards := range tmpSMap { maxSCard := sCards[len(sCards)-1] for i := len(cards) - 1; i >= 0; i-- { if int32(Value(cards[i])) == maxSCard { card := cards[i] lastCard := lastCards[len(lastCards)-1] if Value(card) < Value(lastCard) { continue } else { if Value(card) == Value(lastCard) { if Color(card) > Color(lastCard) { haveNeed = true needCard = cards[i] } } else if Value(card) > Value(lastCards[1]) { haveNeed = true needCard = cards[i] } } } if haveNeed && needCard != -1 { break } } if haveNeed && needCard != -1 { break } } if haveNeed && needCard != -1 { needValue := Value(needCard) need := 0 for j := len(cards) - 1; j >= 0; j-- { if needValue >= 0 && Value(cards[j]) == needValue && need < idx { needCards = append(needCards, cards[j]) needValue-- need++ } } } } } } } return haveNeed, needCards } func needColorStraight(lastCards, cards []int32) (bool, []int32) { haveNeed := false needCards := []int32{} if len(cards) != 0 && IsColorStraight(lastCards) { sliceCS := [4][]int32{} //color-card for _, card := range cards { if card != InvalideCard && Value(card) != Card_Value_2 { sliceCS[Color(card)] = append(sliceCS[Color(card)], card) } } for _, colorCards := range sliceCS { if len(colorCards) > 0 && len(colorCards) >= len(lastCards) { sort.Slice(colorCards, func(i, j int) bool { if Value(colorCards[i]) > Value(colorCards[j]) { return false } return true }) tmpS := FindOneStraightWithWidth(len(lastCards), colorCards) if len(tmpS) > 0 { card := tmpS[len(tmpS)-1] lastCard := lastCards[len(lastCards)-1] if Value(card) > Value(lastCard) { haveNeed = true copy(needCards, tmpS) } else if Value(card) == Value(lastCard) { if Color(card) > Color(lastCard) { haveNeed = true copy(needCards, tmpS) } } } } } } return haveNeed, needCards } func needStraightTwin(lastCards, cards []int32) (bool, []int32) { haveNeed := false needCards := []int32{} if len(cards) != 0 && IsStraightTwin(lastCards) { sort.Slice(cards, func(i, j int) bool { if cards[i] > cards[j] { return false } return true }) mapSTwin := make(map[int32]int32) for _, card := range cards { if card != InvalideCard && Value(card) != Card_Value_2 { mapSTwin[int32(Value(card))]++ } } if len(mapSTwin) > 0 { valueSTwin := []int32{} for card, num := range mapSTwin { if num >= 2 { valueSTwin = append(valueSTwin, card) } } if len(valueSTwin) > 0 { sort.Slice(valueSTwin, func(i, j int) bool { if valueSTwin[i] > valueSTwin[j] { return false } return true }) tmpPairs := FindOneStraightWithWidth(len(lastCards)/2, valueSTwin) if len(tmpPairs) > 0 { for _, card := range tmpPairs { delC := 0 for i := 0; i < len(cards); i++ { if int32(Value(cards[i])) == card && (delC < 2) { //删除2次 delC++ haveNeed = true needCards = append(needCards, cards[i]) continue } } } } } } } return haveNeed, needCards } func needTriple(lastCards, cards []int32) (bool, []int32) { haveNeed := false needCards := []int32{} if len(cards) != 0 && IsTriple(lastCards) { mapTriple := make(map[int32]int32) for _, card := range cards { if card != InvalideCard { mapTriple[int32(Value(card))]++ } } if len(mapTriple) > 0 { ValueTriple := []int32{} for card, num := range mapTriple { if num >= 3 { ValueTriple = append(ValueTriple, card) } } if len(ValueTriple) > 0 { lastCard := lastCards[0] for _, triple := range ValueTriple { if triple > lastCard { for _, card := range cards { if int32(Value(card)) == triple { haveNeed = true needCards = append(needCards, card) } } } } } } } return haveNeed, needCards } func needStraightTriple(lastCards, cards []int32) (bool, []int32) { haveNeed := false needCards := []int32{} if len(cards) != 0 && IsStraightTriple(lastCards) { sort.Slice(cards, func(i, j int) bool { if cards[i] > cards[j] { return false } return true }) mapTriple := make(map[int32]int32) for _, card := range cards { if card != InvalideCard && Value(card) != Card_Value_2 { mapTriple[int32(Value(card))]++ } } if len(mapTriple) > 0 { ValueTriple := []int32{} for card, num := range mapTriple { if num >= 3 { ValueTriple = append(ValueTriple, card) } } if len(ValueTriple) > 0 { sort.Slice(ValueTriple, func(i, j int) bool { if ValueTriple[i] > ValueTriple[j] { return false } return true }) tmpPairs := FindOneStraightWithWidth(len(lastCards)/3, ValueTriple) if len(tmpPairs) > 0 { for _, card := range tmpPairs { delC := 0 for i := 0; i < len(cards); i++ { if int32(Value(cards[i])) == card && (delC < 3) { //删除3次 delC++ haveNeed = true needCards = append(needCards, cards[i]) continue } } } } } } } return haveNeed, needCards } func needFourBomb(lastCards, cards []int32) (bool, []int32) { haveNeed := false needCards := []int32{} if len(cards) != 0 && IsFourBomb(lastCards) { mapBomb := make(map[int32]int32) for _, card := range cards { if card != InvalideCard { mapBomb[int32(Value(card))]++ } } if len(mapBomb) > 0 { ValueBomb := []int32{} for card, num := range mapBomb { if num >= 4 { ValueBomb = append(ValueBomb, card) } } if len(ValueBomb) > 0 { lastCard := lastCards[0] for _, bomb := range ValueBomb { if bomb > lastCard { for _, card := range cards { if int32(Value(card)) == bomb { haveNeed = true needCards = append(needCards, card) } } } } } } } return haveNeed, needCards } func needMaxPlaneSingleRandom(cards []int32) (bool, []int32) { haveNeed := false needCards := []int32{} if len(cards) != 0 { sort.Slice(cards, func(i, j int) bool { if cards[i] > cards[j] { return false } return true }) mapTriple := make(map[int32]int32) for _, card := range cards { if card != InvalideCard && Value(card) != Card_Value_2 { mapTriple[int32(Value(card))]++ } } if len(mapTriple) > 0 { ValueTriple := []int32{} for card, num := range mapTriple { if num >= 3 { ValueTriple = append(ValueTriple, card) } } if len(ValueTriple) > 0 { sort.Slice(ValueTriple, func(i, j int) bool { if ValueTriple[i] > ValueTriple[j] { return false } return true }) for start := len(ValueTriple) - 1; start >= 1; start-- { tmpPairs := FindOneStraightWithWidth(start, ValueTriple) if len(tmpPairs) > 0 { haveNeed = true needCards = FindCardsFromCardsValue(cards, tmpPairs, 3) break } } //找到3顺后,寻找配牌. 3-1可以是3-x,不匹配3-2 if haveNeed { maxSLen := len(needCards)*2/3 - 1 tCards := GetASliceInt32NotInB(cards, needCards) for i := 0; i < len(tCards) && i < maxSLen; i++ { needCards = append(needCards, tCards[i]) } } } } } return haveNeed, needCards } func needMaxPlaneTwinRandom(cards []int32) (bool, []int32) { haveNeed := false needCards := []int32{} if len(cards) != 0 { sort.Slice(cards, func(i, j int) bool { if cards[i] > cards[j] { return false } return true }) mapTriple := make(map[int32]int32) for _, card := range cards { if card != InvalideCard && Value(card) != Card_Value_2 { mapTriple[int32(Value(card))]++ } } if len(mapTriple) > 0 { ValueTriple := []int32{} for card, num := range mapTriple { if num >= 3 { ValueTriple = append(ValueTriple, card) } } if len(ValueTriple) > 0 { sort.Slice(ValueTriple, func(i, j int) bool { if ValueTriple[i] > ValueTriple[j] { return false } return true }) for start := len(ValueTriple) - 1; start >= 1; start-- { tmpPairs := FindOneStraightWithWidth(start, ValueTriple) if len(tmpPairs) > 0 { //需要判断剩余牌张数 if len(cards)-len(tmpPairs)*3 < len(tmpPairs)*2 { continue } haveNeed = true needCards = FindCardsFromCardsValue(cards, tmpPairs, 3) //找到3顺后,寻找配牌. if haveNeed { maxSLen := len(needCards) * 2 / 3 tCards := GetASliceInt32NotInB(cards, needCards) for i := 0; i < len(tCards) && i < maxSLen; i++ { needCards = append(needCards, tCards[i]) } } break } } } } } return haveNeed, needCards } func needMaxStraightTripleRandom(cards []int32) (bool, []int32) { haveNeed := false needCards := []int32{} if len(cards) != 0 { sort.Slice(cards, func(i, j int) bool { if cards[i] > cards[j] { return false } return true }) mapTriple := make(map[int32]int32) for _, card := range cards { if card != InvalideCard && Value(card) != Card_Value_2 { mapTriple[int32(Value(card))]++ } } if len(mapTriple) > 0 { ValueTriple := []int32{} for card, num := range mapTriple { if num >= 3 { ValueTriple = append(ValueTriple, card) } } if len(ValueTriple) > 0 { sort.Slice(ValueTriple, func(i, j int) bool { if ValueTriple[i] > ValueTriple[j] { return false } return true }) for start := len(ValueTriple) - 1; start >= 2; start-- { tmpPairs := FindOneStraightWithWidth(start, ValueTriple) if len(tmpPairs) > 0 { haveNeed = true needCards = FindCardsFromCardsValue(cards, tmpPairs, 3) break } } } } } return haveNeed, needCards } func needMaxStraightTwinRandom(cards []int32) (bool, []int32) { haveNeed := false needCards := []int32{} if len(cards) != 0 { sort.Slice(cards, func(i, j int) bool { if cards[i] > cards[j] { return false } return true }) mapTriple := make(map[int32]int32) for _, card := range cards { if card != InvalideCard && Value(card) != Card_Value_2 { mapTriple[int32(Value(card))]++ } } if len(mapTriple) > 0 { ValueTriple := []int32{} for card, num := range mapTriple { if num >= 2 { ValueTriple = append(ValueTriple, card) } } if len(ValueTriple) > 0 { sort.Slice(ValueTriple, func(i, j int) bool { if ValueTriple[i] > ValueTriple[j] { return false } return true }) for start := len(ValueTriple) - 1; start >= 2; start-- { tmpPairs := FindOneStraightWithWidth(start, ValueTriple) if len(tmpPairs) > 0 { haveNeed = true needCards = FindCardsFromCardsValue(cards, tmpPairs, 2) break } } } } } return haveNeed, needCards } func needMaxStraightRandom(cards []int32) (bool, []int32) { haveNeed := false needCards := []int32{} if len(cards) != 0 { sort.Slice(cards, func(i, j int) bool { if cards[i] > cards[j] { return false } return true }) mapTriple := make(map[int32]int32) for _, card := range cards { if card != InvalideCard && Value(card) != Card_Value_2 { mapTriple[int32(Value(card))]++ } } if len(mapTriple) > 0 { ValueTriple := []int32{} for card, num := range mapTriple { if num >= 1 { ValueTriple = append(ValueTriple, card) } } if len(ValueTriple) > 0 { sort.Slice(ValueTriple, func(i, j int) bool { if ValueTriple[i] > ValueTriple[j] { return false } return true }) for start := len(ValueTriple) - 1; start >= 3; start-- { tmpPairs := FindOneStraightWithWidth(start, ValueTriple) if len(tmpPairs) > 0 { haveNeed = true needCards = FindCardsFromCardsValue(cards, tmpPairs, 1) break } } } } } return haveNeed, needCards } func needMaxTwinRandom(cards []int32) (bool, []int32) { haveNeed := false needCards := []int32{} if len(cards) != 0 { sort.Slice(cards, func(i, j int) bool { if cards[i] > cards[j] { return false } return true }) mapTriple := make(map[int32]int32) for _, card := range cards { if card != InvalideCard { mapTriple[int32(Value(card))]++ } } if len(mapTriple) > 0 { ValueTriple := []int32{} for card, num := range mapTriple { if num >= 2 { ValueTriple = append(ValueTriple, card) } } if len(ValueTriple) > 0 { card := ValueTriple[0] haveNeed = true needCards = FindCardsFromCardsValue(cards, []int32{card}, 2) } } } return haveNeed, needCards } func needMaxBoomRandom(cards []int32) (bool, []int32) { haveNeed := false needCards := []int32{} if len(cards) != 0 { sort.Slice(cards, func(i, j int) bool { if cards[i] > cards[j] { return false } return true }) mapTriple := make(map[int32]int32) for _, card := range cards { if card != InvalideCard { mapTriple[int32(Value(card))]++ } } if len(mapTriple) > 0 { ValueTriple := []int32{} for card, num := range mapTriple { if num >= 4 { ValueTriple = append(ValueTriple, card) } } if len(ValueTriple) > 0 { card := ValueTriple[0] haveNeed = true needCards = FindCardsFromCardsValue(cards, []int32{card}, 4) } } } return haveNeed, needCards } func needMaxTripleRandom(cards []int32) (bool, []int32) { haveNeed := false needCards := []int32{} if len(cards) != 0 { sort.Slice(cards, func(i, j int) bool { if cards[i] > cards[j] { return false } return true }) mapTriple := make(map[int32]int32) for _, card := range cards { if card != InvalideCard { mapTriple[int32(Value(card))]++ } } if len(mapTriple) > 0 { ValueTriple := []int32{} for card, num := range mapTriple { if num >= 3 { ValueTriple = append(ValueTriple, card) } } if len(ValueTriple) > 0 { card := ValueTriple[0] haveNeed = true needCards = FindCardsFromCardsValue(cards, []int32{card}, 3) } } } return haveNeed, needCards } // 根据上家牌型是否需要额外延迟出牌时间(s) func NeedExDelay(lastCards []int32) bool { if IsStraightTwin(lastCards) && len(lastCards) >= 6 { //三连对、四连对、五连对 return true } if IsFourBomb(lastCards) { //炸弹 return true } //if IsStraight(lastCards) { //5张以上的顺子 // return true //} if IsPlaneTwin(lastCards) && len(lastCards) >= 10 { //飞机 return true } return false } func GetASliceInt32NotInB(a []int32, b []int32) []int32 { var c []int32 temp := map[int32]struct{}{} for _, val := range b { if _, ok := temp[val]; !ok { temp[val] = struct{}{} // 空struct 不占内存空间 } } for _, val := range a { if _, ok := temp[val]; !ok { c = append(c, val) } } return c } func IsTwo(a []int32) bool { if len(a) != 1 { return false } return Value(a[0]) == 12 // 2 } // IsBomb 是否炸弹 // isClass 是否经典版 func IsBomb(a []int32, isClass bool) bool { var n int var has bool if isClass { has, n = RulePopEnable(a) } else { has, n = RulePopEnable_yl(a) } if !has { return false } switch n { case Straight_Twin, Four_Bomb: return true } return false }