package gamelogic import ( "encoding/json" "fmt" "math/rand" "runtime/debug" "sort" "bet24.com/log" "bet24.com/servers/games/masharie_table/common" ) var type_desc = []string{"♦", "♣", "♥", "♠", ""} var value_desc = []string{"7", "8", "9", "10", "J", "Q", "K", "A"} var type_html_desc = []string{"d", "c", "h", "s", ""} // var type_html_desc = []string{"♦", "♣", "♥", "♠", ""} // 非主花色排序从大到小 A 10 K Q J 9 8 7 var score_regular = []int{0, 0, 0, 10, 2, 3, 4, 11} // 主花色排序从大到小 J 9 A 10 K Q 8 7 var score_trump = []int{0, 0, 18, 10, 20, 3, 4, 11} //9的牌值跟baloot游戏的不同,这里为了排序方便,牌值从14为28 const ( CARD_COUNT = 32 // 牌数量 HAND_CARD_COUNT = 5 // 手牌数量 CARD_DECK_COUNT = 5 // 牌组数量 ) /* 牌的排列顺序为 方块 梅花 红心 黑桃 */ const ( CardType_Diamond = iota CardType_Club CardType_Heart CardType_Spade CardType_Invalid ) const ( CardValue7 = iota CardValue8 CardValue9 CardValue10 CardValueJ CardValueQ CardValueK CardValueA ) type RankingMode int const ( Max RankingMode = iota Min Random ) func getCardHex(card int, isHtml bool) string { if !isValidCard(card) { return "n/a" } if isHtml { return fmt.Sprintf("%s%s", type_html_desc[GetCardType(card)], value_desc[GetCardValue(card)]) } return fmt.Sprintf("%s%s", type_desc[GetCardType(card)], value_desc[GetCardValue(card)]) } func getCardsHex(cards []int, isHtml bool) string { ret := "[" for _, v := range cards { ret += " " ret += getCardHex(v, isHtml) ret += " " } ret += "]" return ret } func isValidCard(card int) bool { return card >= 0 && card < CARD_COUNT } func GetCardType(card int) int { if !isValidCard(card) { log.Debug("getCardType invalid Card %d", card) log.Debug("%s", debug.Stack()) return CardType_Invalid } return card / 8 } func GetCardValue(card int) int { if !isValidCard(card) { log.Debug("getCardValue invalid Card %d", card) log.Debug("%s", debug.Stack()) return -1 } return card % 8 } // 是否为主花色牌 func IsTrump(card, trumpType int) bool { return CardType_Invalid != trumpType && GetCardType(card) == trumpType } // 按牌分值排序 func SortCardsByScore(cards []int, trumpType int) { sort.Slice(cards, func(i, j int) bool { //主花色 比其他的花色大 就算分值低也比其他花色大 if IsTrump(cards[i], trumpType) != IsTrump(cards[j], trumpType) { return !IsTrump(cards[i], trumpType) } return calculateCardScore(cards[i], trumpType) < calculateCardScore(cards[j], trumpType) }) } // 计算花色权重 为了花色逆时针排序 func getCardTypeWeight(cardTypeOrder []int, card int) int { weight := 0 // 初始化为-1,表示没有找到 cardType := GetCardType(card) for i := 0; i < len(cardTypeOrder); i++ { if cardTypeOrder[i] == cardType { weight = i break } } return weight * 100 } // 按花色加分值排序 func SortCardsByType(cards, cardTypeOrder []int, trumpType int) { sort.Slice(cards, func(i, j int) bool { return getCardTypeWeight(cardTypeOrder, cards[i])+calculateCardScore(cards[i], trumpType) < getCardTypeWeight(cardTypeOrder, cards[j])+calculateCardScore(cards[j], trumpType) }) } // 计算卡片牌值 func calculateCardScore(card, trumpType int) int { value := GetCardValue(card) t := GetCardType(card) if trumpType != CardType_Invalid && t == trumpType { return (value + score_trump[value]) } return (value + score_regular[value]) } // 比较两张牌的大小 func calculateRankings(card1, card2 int, trumpType int) int { //如果是主花色则更大,都是主花色 或者都不是时才比较牌值 if IsTrump(card1, trumpType) != IsTrump(card2, trumpType) { //有一组是主花色的牌 if IsTrump(card1, trumpType) { return 1 } else { return 2 } } score1 := calculateCardScore(card1, trumpType) score2 := calculateCardScore(card2, trumpType) if score1 > score2 { return 1 } else if score1 < score2 { return 2 } else { return 0 } } func getCopy(cards []int) []int { var ret []int d, _ := json.Marshal(cards) json.Unmarshal(d, &ret) return ret } // 计算卡牌分数 func calculateCardsScore(cards1, cards2 []int, trumpType int) int { cards1Copy := getCopy(cards1) cards2Copy := getCopy(cards2) SortCardsByScore(cards1Copy, trumpType) //排序 SortCardsByScore(cards2Copy, trumpType) //排序 for i := len(cards1Copy) - 1; i >= 0; i-- { ranking := calculateRankings(cards1Copy[i], cards2Copy[i], trumpType) if ranking == 1 { return 1 } else if ranking == 2 { return 2 } } return 0 } // 计算项目分数(有项目需要特殊处理) func calculateProjectScore(cards1, cards2 []int) int { lastCards1 := cards1[len(cards1)-1] lastCards2 := cards2[len(cards2)-1] trumpType := CardType_Invalid //只比较最后一张牌 ranking := calculateRankings(lastCards1, lastCards2, trumpType) if ranking == 1 { return 1 } else if ranking == 2 { return 2 } return 0 } // 排序卡牌 func SortHandCards(cards []int, trumpType int) ([]int, common.CardProject, int, int) { project := common.Project_Base projectLength := 0 maxCard := CARD_COUNT //最大牌 // 剩余项目牌 var mainCards []int // 项目牌 var projectCards []int mainCardType := trumpType //主要卡牌花色用于排序 默认为主花色 haveProject := false //是否有项目 haveStraightFlush := false haveFourOfAKind := false fourOfAKindValue := -1 haveFifty := false var fiftyCard []int haveBaloot := false haveSira := false var siraCard []int //先初步排序便于检查同花顺 sort.Slice(cards, func(i, j int) bool { if GetCardType(cards[i]) != GetCardType(cards[j]) { return GetCardType(cards[i]) < GetCardType(cards[j]) } return GetCardValue(cards[i]) < GetCardValue(cards[j]) }) if !haveProject { haveStraightFlush, _ = isStraightFlush(cards, HAND_CARD_COUNT) if haveStraightFlush { haveProject = haveStraightFlush project = common.Project_StraightFlush projectLength = 5 } } if !haveProject { fourOfAKindValue = getFourOfAKind(cards) haveFourOfAKind = fourOfAKindValue != -1 if haveFourOfAKind { haveProject = haveFourOfAKind project = common.Project_Hundred projectLength = 4 mainCardType = CardType_Spade } } if !haveProject { fiftyCard = isFifty(cards) haveFifty = len(fiftyCard) > 0 if haveFifty { haveProject = haveFifty project = common.Project_Fifty projectLength = len(fiftyCard) mainCardType = GetCardType(fiftyCard[0]) } } if !haveProject { haveBaloot = isBaloot(cards, trumpType) if haveBaloot { haveProject = haveBaloot project = common.Project_Baloot projectLength = 2 } } if !haveProject { siraCard = isSira(cards) haveSira = len(siraCard) > 0 if haveSira { haveProject = haveSira project = common.Project_Sira projectLength = len(siraCard) mainCardType = GetCardType(siraCard[0]) } } // log.Release("是否有项目%v ,同花顺%v,炸弹[%v:%v] 4同花顺[%v:%v] Baloot[%v] Sira[%v:%v]", haveProject, haveStraightFlush, // haveFourOfAKind, fourOfAKindValue, // haveFifty, fiftyCard, // haveBaloot, // haveSira, siraCard) if haveProject { for _, card := range cards { if haveStraightFlush { projectCards = append(projectCards, card) continue } else if haveFourOfAKind && GetCardValue(card) == fourOfAKindValue { projectCards = append(projectCards, card) continue } else if haveFifty && IsContainInt(fiftyCard, card) { projectCards = append(projectCards, card) continue } else if haveBaloot && (GetCardValue(card) == 5 || GetCardValue(card) == 6) && IsTrump(card, trumpType) { //检查是否有主花色的Baloot projectCards = append(projectCards, card) continue } else if haveSira && IsContainInt(siraCard, card) { projectCards = append(projectCards, card) continue } mainCards = append(mainCards, card) } //有项目的情况下其他牌按大小排序 // sort.Slice(mainCards, func(i, j int) bool { // if IsTrump(mainCards[i], trumpType) != IsTrump(mainCards[j], trumpType) { // return !IsTrump(mainCards[i], trumpType) // } // if GetCardType(mainCards[i]) != GetCardType(mainCards[j]) { // return GetCardType(mainCards[i]) < GetCardType(mainCards[j]) // } // return GetCardValue(mainCards[i]) < GetCardValue(mainCards[j]) // }) // sort.Slice(projectCards, func(i, j int) bool { // if IsTrump(projectCards[i], trumpType) != IsTrump(projectCards[j], trumpType) { // return !IsTrump(projectCards[i], trumpType) // } // if GetCardType(projectCards[i]) != GetCardType(projectCards[j]) { // return GetCardType(projectCards[i]) < GetCardType(projectCards[j]) // } // return GetCardValue(projectCards[i]) < GetCardValue(projectCards[j]) // }) //cardTypeOrder := sortCardType(mainCardType) //SortCardsByType(mainCards, cardTypeOrder, trumpType) //SortCardsByType(projectCards, cardTypeOrder, trumpType) } else { mainCards = append(mainCards, cards...) //没有项目的情况 和主牌一个花色的牌按照value_trump牌值排序 其他花色的牌按照value_regular牌值排序 SortCardsByScore(mainCards, trumpType) maxCard = mainCards[len(mainCards)-1] } cardTypeOrder := sortCardType(mainCardType) SortCardsByType(mainCards, cardTypeOrder, trumpType) if haveProject { SortCardsByType(projectCards, cardTypeOrder, trumpType) mainCards = append(mainCards, projectCards...) } return mainCards, project, projectLength, maxCard } // 是否为Baloot func isBaloot(cards []int, trumpType int) bool { haveTrumpQ := false haveTrumpK := false for i := 0; i < len(cards); i++ { if cards[i] == trumpType*8+CardValueQ { haveTrumpQ = true } if cards[i] == trumpType*8+CardValueK { haveTrumpK = true } } return haveTrumpQ && haveTrumpK } // 得到炸弹牌值,如果为-1则表示没有炸弹 7,8,9不算炸弹 func getFourOfAKind(cards []int) int { counts := make(map[int]int) for _, card := range cards { value := GetCardValue(card) if value != CardValue7 && value != CardValue8 && value != CardValue9 { counts[value]++ } } for v, count := range counts { if count == 4 { return v } } return -1 } // 检查是否为同花顺 func isStraightFlush(cards []int, minLength int) (bool, []int) { if len(cards) < minLength { return false, nil } // sort.Ints(cards) for i := 0; i <= len(cards)-minLength; i++ { cardType := GetCardType(cards[i]) isStraightFlush := true for j := i + 1; j < i+minLength; j++ { if GetCardType(cards[j]) != cardType || GetCardValue(cards[j])-GetCardValue(cards[j-1]) != 1 { isStraightFlush = false break } } if isStraightFlush { return true, cards[i : i+minLength] } } return false, nil } // 检查是否有4张同花顺 func isFifty(cards []int) []int { if len(cards) != 5 { return nil } _, result := isStraightFlush(cards, 4) return result } // 检查是否有3张同花顺 func isSira(cards []int) []int { if len(cards) != 5 { return nil } _, result := isStraightFlush(cards, 3) return result } func IsContainInt(items []int, item int) bool { for _, eachItem := range items { if eachItem == item { return true } } return false } func getRanking(ranking []int, rankingMode RankingMode) (int, []int) { if len(ranking) == 0 { return -1, ranking } if len(ranking) == 1 { return ranking[0], []int{} } var randomRank int if rankingMode == Random { randomIndex := rand.Intn(len(ranking)) randomRank = ranking[randomIndex] } else { maxRanking := ranking[0] minRanking := ranking[0] for _, f := range ranking { if f < maxRanking { maxRanking = f } if f > minRanking { minRanking = f } } if rankingMode == Max { randomRank = maxRanking } else if rankingMode == Min { randomRank = minRanking } } newRanking := make([]int, 0) removed := false for _, f := range ranking { if f == randomRank && !removed { removed = true continue } newRanking = append(newRanking, f) } return randomRank, newRanking } // 根据类型排序卡牌花色顺序 主花色在最后 其他花色逆时针排序 func sortCardType(cardType int) []int { if cardType < CardType_Diamond || cardType > CardType_Spade { return []int{} } order := make([]int, 4) for i := 0; i < 4; i++ { offset := (i - (cardType + 1) + 4) % 4 // 加4避免越界 order[offset] = i } return order }