package tala import ( "sort" "strconv" ) //牌序- K, Q, J, 10, 9, 8, 7, 6, 5, 4, 3, 2, A //方片- 51,50,49,48,47,46,45,44,43,42,41,40,39 //红桃- 38,37,36,35,34,33,32,31,30,29,28,27,26 //梅花- 25,24,23,22,21,20,19,18,17,16,15,14,13 //黑桃- 12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 const ( TaLaNil int = iota //nil ColorStraight //1 同花顺 Triple //2 三张 ) // Color 黑桃0 梅花1 紅桃2 方片3 func Color(c int32) int { return int(c) / PER_CARD_COLOR_MAX } func Value(c int32) int { value := int(c+1) % PER_CARD_COLOR_MAX if value == 0 { value = PER_CARD_COLOR_MAX } return value } func ValueStr(c int32) string { if c == InvalideCard { return "" } str := "" value := strconv.Itoa(Value(c)) switch Color(c) { case 0: str = "黑桃" case 1: str = "梅花" case 2: str = "紅桃" case 3: str = "方片" } return str + value } func IsStraight(cards []int32) bool { //顺子 if len(cards) < 3 || len(cards) > HandCardNum { return false } tmpCards := []int{} for _, card := range cards { 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 } } return true } 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 } func IsTriple(cards []int32) bool { //三张 if len(cards) < 3 || len(cards) > 4 { // 3张或者4张 return false } switch len(cards) { case 3: if Value(cards[0]) != Value(cards[1]) { return false } if Value(cards[1]) != Value(cards[2]) { return false } return true case 4: 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 } return false } func CanChi(cards []int32, chiCard int32, excludeCards []int32) (bool, []int32) { //可吃 chi2pPhom := []int32{chiCard} if chiCard == InvalideCard { return false, chi2pPhom } cpCards := []int32{} for _, card := range cards { if card != InvalideCard { cpCards = append(cpCards, card) } } if len(cpCards) == 0 { return false, chi2pPhom } n := 0 tmp := []int32{} for _, card := range cpCards { if Value(chiCard) == Value(card) && !InSliceInt32(excludeCards, card) { n++ tmp = append(tmp, card) } } if n >= 2 { //找到两张以上牌值相同的,可以吃 for _, card := range tmp { chi2pPhom = append(chi2pPhom, card) } return true, chi2pPhom } chi2pPhom = []int32{chiCard} min1 := false min2 := false minPhom := []int32{} mid1 := false mid2 := false midPhom := []int32{} max1 := false max2 := false maxPhom := []int32{} for _, card := range cpCards { if Color(chiCard) == Color(card) && !InSliceInt32(excludeCards, card) { //最小 if chiCard+1 == card { minPhom = append(minPhom, card) min1 = true } if chiCard+2 == card { minPhom = append(minPhom, card) min2 = true } if min1 && min2 { for _, c := range minPhom { chi2pPhom = append(chi2pPhom, c) } return true, chi2pPhom } //中间 if chiCard+1 == card { midPhom = append(midPhom, card) mid1 = true } if chiCard-1 == card { midPhom = append(midPhom, card) mid2 = true } if mid1 && mid2 { for _, c := range midPhom { chi2pPhom = append(chi2pPhom, c) } return true, chi2pPhom } //最大 if chiCard-1 == card { maxPhom = append(maxPhom, card) max1 = true } if chiCard-2 == card { maxPhom = append(maxPhom, card) max2 = true } if max1 && max2 { for _, c := range maxPhom { chi2pPhom = append(chi2pPhom, c) } return true, chi2pPhom } } } return false, chi2pPhom } func GetCardsValue(cards []int32) int { cardValue := 0 for _, card := range cards { if card != InvalideCard { cardValue += Value(card) } } return cardValue } // 尝试组合phom func TryPhom(cards, chiCards []int32) ([]int32, [][]int32) { //胡 cpCards := []int32{} phomCards := [][]int32{} for _, card := range cards { if card != InvalideCard { cpCards = append(cpCards, card) } } if len(cpCards) == 0 { return cpCards, phomCards } cardValue := GetCardsValue(cards) tmpPhoms := [][]int32{} var TryOpPhom func([]int32) TryOpPhom = func(cs []int32) { if len(cs) == 0 { return } cp := []int32{} for _, i2 := range cs { if i2 != InvalideCard { cp = append(cp, i2) } } //fmt.Println("===2===", cp) phoms := needPhom(cp) if len(phoms) != 0 { //fmt.Println("===4===", phoms) for _, phom := range phoms { for _, card := range phom { for i := 0; i < len(cp); i++ { if cp[i] == card { cp = append(cp[:i], cp[i+1:]...) i-- } } } tmpCp := []int32{} for _, tmp := range cp { tmpCp = append(tmpCp, tmp) } tmpPhoms = append(tmpPhoms, phom) TryOpPhom(tmpCp) //fmt.Println("===3===", tmpCp, tmpPhoms) if GetCardsValue(tmpCp) < cardValue && !InSliceASliceB(tmpCp, chiCards) { //是不是最优解 //吃过的牌不能留在手牌里 cardValue = GetCardsValue(cp) phomCards = [][]int32{} for _, tmpPhom := range tmpPhoms { if len(tmpPhom) > 0 { tmp := []int32{} for _, c := range tmpPhom { tmp = append(tmp, c) } phomCards = append(phomCards, tmp) } } } cp = []int32{} //回退下 next for _, card := range cs { cp = append(cp, card) } tmpPhoms = append(tmpPhoms[:len(tmpPhoms)-1]) } } return } TryOpPhom(cpCards) //fmt.Println("===1===", phomCards) for _, phom := range phomCards { for _, card := range phom { for i, cpcard := range cpCards { if card == cpcard { cpCards = append(cpCards[:i], cpCards[i+1:]...) i-- break } } } } return cpCards, phomCards } // b中元素是否在a里面 func InSliceASliceB(a, b []int32) bool { for _, bi := range b { if InSliceInt32(a, bi) { return true } } return false } // 有所有的同花顺组合 或者 有所有的点数相同的组合 func needPhom(cards []int32) [][]int32 { //胡 tmps := [][]int32{} haveColorStraights, colorStraights := needColorStraight(cards) haveTriples, triples := needTriple(cards) if haveColorStraights || haveTriples { //有所有的同花顺组合 或者 有所有的点数相同的组合 if haveColorStraights { for _, straight := range colorStraights { tmps = append(tmps, straight) } } if haveTriples { for _, triple := range triples { tmps = append(tmps, triple) } } } return tmps } // 找所有相同点数的三张 func needTriple(cards []int32) (bool, [][]int32) { haveNeed := false needCards := [][]int32{} if len(cards) != 0 { mapTriple := make(map[int32][]int32) for _, card := range cards { if card != InvalideCard { mapTriple[int32(Value(card))] = append(mapTriple[int32(Value(card))], card) } } if len(mapTriple) > 0 { for _, tripleCards := range mapTriple { if len(tripleCards) == 3 { haveNeed = true needCards = append(needCards, tripleCards) } if len(tripleCards) == 4 { haveNeed = true needCards = append(needCards, tripleCards) for _, card := range tripleCards { tmps := []int32{} for _, tmp := range tripleCards { if card != tmp { tmps = append(tmps, tmp) } } if len(tmps) > 0 { needCards = append(needCards, tmps) } } } } } } return haveNeed, needCards } // 所有的同花顺 func needColorStraight(cards []int32) (bool, [][]int32) { haveNeed := false needCards := [][]int32{} if len(cards) != 0 { sliceCS := [4][]int32{} //color-card for _, card := range cards { if card != InvalideCard { sliceCS[Color(card)] = append(sliceCS[Color(card)], card) } } for _, colorCards := range sliceCS { if len(colorCards) > 0 { sort.Slice(colorCards, func(i, j int) bool { if Value(colorCards[i]) > Value(colorCards[j]) { return false } return true }) for i := len(colorCards); i > 2; i-- { tmps := FindStraightWithWidth(i, colorCards) if len(tmps) > 0 { haveNeed = true for _, tmp := range tmps { needCards = append(needCards, tmp) } } } } } } return haveNeed, needCards } // 找一个固定长度的顺子 (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 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 InSliceInt32(sl []int32, v int32) bool { for _, vv := range sl { if vv == v { return true } } return false }