| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506 |
- 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
- }
|