2990 lines
70 KiB
Go
2990 lines
70 KiB
Go
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
|
||
}
|