github.com/lianghucheng/zrddz@v0.0.0-20200923083010-c71f680932e2/src/game/poker/landlordanalyzer.go (about) 1 package poker 2 3 import ( 4 "common" 5 "sort" 6 7 "github.com/name5566/leaf/log" 8 ) 9 10 type LandlordAnalyzer struct { 11 cardValueMarker map[int]int // 记牌器(Key 牌值、Value 牌的数量) 12 cards []int 13 14 hasKingBomb bool 15 hasBomb bool 16 hasTrio bool 17 hasPair bool 18 hasAirplaneChain bool 19 hasPairSisters bool 20 hasSoloChain bool 21 22 kingBomb []int 23 bombs [][]int 24 trios [][]int 25 pairs [][]int 26 airplaneChains [][]int 27 pairSisterss [][]int 28 soloChains [][]int 29 30 unrelated []int 31 } 32 33 func (analyzer *LandlordAnalyzer) init() { 34 analyzer.cardValueMarker = make(map[int]int) 35 analyzer.cards = []int{} 36 37 analyzer.hasKingBomb = false 38 analyzer.hasBomb = false 39 analyzer.hasTrio = false 40 analyzer.hasPair = false 41 analyzer.hasAirplaneChain = false 42 analyzer.hasPairSisters = false 43 analyzer.hasSoloChain = false 44 45 analyzer.kingBomb = []int{} 46 analyzer.bombs = [][]int{} 47 analyzer.trios = [][]int{} 48 analyzer.pairs = [][]int{} 49 analyzer.airplaneChains = [][]int{} 50 analyzer.pairSisterss = [][]int{} 51 analyzer.soloChains = [][]int{} 52 53 analyzer.unrelated = []int{} 54 } 55 56 func (analyzer *LandlordAnalyzer) setCardValueMarker() { 57 for i := 3; i < 18; i++ { // 3、4、5、6、7、8、9、10、J、Q、K、A、2、小王、大王 58 analyzer.cardValueMarker[i] = 0 59 } 60 for _, card := range analyzer.cards { 61 analyzer.cardValueMarker[CardValue(card)]++ 62 } 63 } 64 65 // 传入的牌必须降序排列 66 func (analyzer *LandlordAnalyzer) Analyze(cards []int) { 67 analyzer.init() 68 analyzer.cards = append([]int{}, cards...) 69 analyzer.setCardValueMarker() 70 analyzer.analyzeKingBomb() 71 analyzer.analyzeBomb() 72 analyzer.analyzeTrio() 73 if analyzer.hasTrio { 74 analyzer.analyzeAirplaneChains(unite(analyzer.trios)) 75 } 76 analyzer.analyzePair() 77 if analyzer.hasPair { 78 analyzer.analyzePairSisters(unite(analyzer.pairs)) 79 } 80 analyzer.analyzeSoloChain(exclude(analyzer.cards)) 81 analyzer.analyzeUnrelated() 82 } 83 84 func (analyzer *LandlordAnalyzer) analyzeKingBomb() { 85 if len(analyzer.cards) > 1 && analyzer.cards[0] == 53 && analyzer.cards[1] == 52 { 86 analyzer.hasKingBomb = true 87 analyzer.kingBomb = []int{53, 52} 88 } else { 89 analyzer.hasKingBomb = false 90 } 91 } 92 93 func (analyzer *LandlordAnalyzer) analyzeBomb() { 94 for cardValue := 15; cardValue > 2; cardValue-- { 95 if analyzer.cardValueMarker[cardValue] == 4 { 96 bomb := []int{4*cardValue - 12, 4*cardValue - 11, 4*cardValue - 10, 4*cardValue - 9} 97 analyzer.bombs = append(analyzer.bombs, bomb) 98 } 99 } 100 if len(analyzer.bombs) == 0 { 101 analyzer.hasBomb = false 102 } else { 103 analyzer.hasBomb = true 104 } 105 } 106 107 func (analyzer *LandlordAnalyzer) analyzeTrio() { 108 for value := 15; value > 2; value-- { 109 if analyzer.cardValueMarker[value] > 2 { 110 temp := GetCardsByValue(analyzer.cards, value) 111 analyzer.trios = append(analyzer.trios, temp[:3]) 112 } 113 } 114 if len(analyzer.trios) == 0 { 115 analyzer.hasTrio = false 116 } else { 117 analyzer.hasTrio = true 118 } 119 } 120 121 func (analyzer *LandlordAnalyzer) analyzePair() { 122 for value := 15; value > 2; value-- { 123 countCardValue := analyzer.cardValueMarker[value] 124 switch countCardValue { 125 case 2, 3: 126 temp := GetCardsByValue(analyzer.cards, value) 127 analyzer.pairs = append(analyzer.pairs, temp[:2]) 128 case 4: 129 temp := GetCardsByValue(analyzer.cards, value) 130 analyzer.pairs = append(analyzer.pairs, temp[:2]) 131 analyzer.pairs = append(analyzer.pairs, temp[2:]) 132 } 133 } 134 if len(analyzer.pairs) == 0 { 135 analyzer.hasPair = false 136 } else { 137 analyzer.hasPair = true 138 } 139 } 140 141 func (analyzer *LandlordAnalyzer) analyzeAirplaneChains(cards []int) { 142 airplaneChains := GetLandlordAirplaneChains(cards) 143 if len(airplaneChains) == 0 { 144 analyzer.hasAirplaneChain = false 145 } else { 146 analyzer.hasAirplaneChain = true 147 for _, airplaneChain := range airplaneChains { 148 analyzer.airplaneChains = append(analyzer.airplaneChains, airplaneChain) 149 } 150 } 151 } 152 153 func (analyzer *LandlordAnalyzer) analyzePairSisters(cards []int) { 154 remain := append([]int{}, cards...) 155 pairSisterss := GetLandlordPairSisters(remain) 156 if len(pairSisterss) == 0 { 157 if len(analyzer.pairSisterss) == 0 { 158 analyzer.hasPairSisters = false 159 } 160 } else { 161 analyzer.hasPairSisters = true 162 for _, pairSisters := range pairSisterss { 163 analyzer.pairSisterss = append(analyzer.pairSisterss, pairSisters) 164 remain = common.Remove(remain, pairSisters) 165 } 166 analyzer.analyzePairSisters(remain) 167 } 168 } 169 170 func (analyzer *LandlordAnalyzer) analyzeSoloChain(cards []int) { 171 remain := append([]int{}, cards...) 172 soloChains := GetLandlordSoloChains(remain) 173 if len(soloChains) == 0 { 174 if len(analyzer.soloChains) == 0 { 175 analyzer.hasSoloChain = false 176 } 177 } else { 178 analyzer.hasSoloChain = true 179 for _, soloChain := range soloChains { 180 analyzer.soloChains = append(analyzer.soloChains, soloChain) 181 remain = common.Remove(remain, soloChain) 182 } 183 analyzer.analyzeSoloChain(remain) 184 } 185 } 186 187 func (analyzer *LandlordAnalyzer) analyzeUnrelated() { 188 cardMarker := make(map[int]bool) 189 cardMarker = GetCardsMap(analyzer.kingBomb, cardMarker) 190 cardMarker = GetMeldsCardsMap(analyzer.bombs, cardMarker) 191 cardMarker = GetMeldsCardsMap(analyzer.trios, cardMarker) 192 cardMarker = GetMeldsCardsMap(analyzer.pairs, cardMarker) 193 cardMarker = GetMeldsCardsMap(analyzer.airplaneChains, cardMarker) 194 cardMarker = GetMeldsCardsMap(analyzer.pairSisterss, cardMarker) 195 cardMarker = GetMeldsCardsMap(analyzer.soloChains, cardMarker) 196 for _, card := range analyzer.cards { 197 if !cardMarker[card] { 198 analyzer.unrelated = append(analyzer.unrelated, card) 199 cardMarker[card] = true 200 } 201 } 202 sort.Ints(analyzer.unrelated) 203 } 204 205 func (analyzer *LandlordAnalyzer) Print() { 206 melds := [][]int{} 207 if analyzer.hasKingBomb { 208 melds = append(melds, analyzer.kingBomb) 209 } 210 melds = append(melds, analyzer.bombs...) 211 melds = append(melds, analyzer.airplaneChains...) 212 melds = append(melds, analyzer.trios...) 213 melds = append(melds, analyzer.pairSisterss...) 214 melds = append(melds, analyzer.pairs...) 215 melds = append(melds, analyzer.soloChains...) 216 if len(analyzer.unrelated) > 0 { 217 melds = append(melds, analyzer.unrelated) 218 } 219 log.Debug("%v", ToMeldsString(melds)) 220 } 221 222 func unite(melds [][]int) []int { 223 temp := []int{} 224 for _, meld := range melds { 225 if CardValue(meld[0]) < 15 { 226 temp = append(temp, meld...) 227 } 228 } 229 return temp 230 } 231 232 // 把大于A的牌排除 233 func exclude(cards []int) []int { 234 temp := []int{} 235 for _, card := range cards { 236 if CardValue(card) < 15 { 237 temp = append(temp, card) 238 } 239 } 240 return temp 241 } 242 243 // 排除顺子、对子 244 func (analyzer *LandlordAnalyzer) analyze2(cards []int) { 245 analyzer.init() 246 analyzer.cards = append([]int{}, cards...) 247 analyzer.setCardValueMarker() 248 //analyzer.analyzeKingBomb() 249 //if analyzer.hasKingBomb { 250 // analyzer.cards = common.Remove(analyzer.cards, []int{53, 52}) 251 // analyzer.setCardValueMarker() 252 //} 253 //analyzer.analyzeBomb() 254 //if analyzer.hasBomb { 255 // for _, bomb := range analyzer.bombs { 256 // analyzer.cards = common.Remove(analyzer.cards, bomb) 257 // } 258 // analyzer.setCardValueMarker() 259 //} 260 analyzer.analyzeSoloChain(exclude(analyzer.cards)) 261 if analyzer.hasSoloChain { 262 for _, soloChain := range analyzer.soloChains { 263 analyzer.cards = common.Remove(analyzer.cards, soloChain) 264 } 265 analyzer.setCardValueMarker() 266 } 267 analyzer.analyzeTrio() 268 if analyzer.hasTrio { 269 for _, trio := range analyzer.trios { 270 analyzer.cards = common.Remove(analyzer.cards, trio) 271 } 272 analyzer.setCardValueMarker() 273 // analyzer.analyzeAirplaneChains(unite(analyzer.trios)) 274 } 275 analyzer.analyzePair() 276 if analyzer.hasPair { 277 for _, pair := range analyzer.pairs { 278 analyzer.cards = common.Remove(analyzer.cards, pair) 279 } 280 analyzer.setCardValueMarker() 281 // analyzer.analyzePairSisters(unite(analyzer.pairs)) 282 } 283 analyzer.unrelated = append([]int{}, analyzer.cards...) 284 sort.Ints(analyzer.unrelated) 285 } 286 287 func (analyzer *LandlordAnalyzer) GetMinDiscards(cards []int) []int { 288 analyzer.init() 289 analyzer.cards = append([]int{}, cards...) 290 analyzer.setCardValueMarker() 291 292 analyzer.analyzeKingBomb() 293 if analyzer.hasKingBomb { 294 analyzer.cards = common.Remove(analyzer.cards, analyzer.kingBomb) 295 analyzer.setCardValueMarker() 296 if len(analyzer.cards) == 0 { 297 return []int{analyzer.kingBomb[1]} 298 } 299 } 300 analyzer.analyzeBomb() 301 if analyzer.hasBomb { 302 for _, bomb := range analyzer.bombs { 303 analyzer.cards = common.Remove(analyzer.cards, bomb) 304 } 305 analyzer.setCardValueMarker() 306 if len(analyzer.cards) == 0 { 307 return analyzer.bombs[len(analyzer.bombs)-1] 308 } 309 } 310 analyzer.analyzeTrio() 311 if analyzer.hasTrio { 312 analyzer.analyzeAirplaneChains(unite(analyzer.trios)) 313 } 314 analyzer.analyzePair() 315 if analyzer.hasPair { 316 analyzer.analyzePairSisters(unite(analyzer.pairs)) 317 } 318 analyzer.analyzeSoloChain(exclude(analyzer.cards)) 319 analyzer.analyzeUnrelated() 320 analyzer.Print() 321 322 minCard := analyzer.cards[len(analyzer.cards)-1] 323 if analyzer.hasAirplaneChain { 324 meld := analyzer.airplaneChains[len(analyzer.airplaneChains)-1] 325 if common.InArray(meld, minCard) { 326 remain := RemoveCardByValue(analyzer.cards, GetCardValueMap(meld)) 327 return mixAirplane(meld, exclude(remain)) 328 } 329 } 330 if analyzer.hasTrio { 331 meld := analyzer.trios[len(analyzer.trios)-1] 332 if common.InArray(meld, minCard) { 333 remain := RemoveCardByValue(analyzer.cards, GetCardValueMap(meld)) 334 return mixTrio(meld, exclude(remain)) 335 } 336 } 337 if analyzer.hasPairSisters { 338 meld := analyzer.pairSisterss[len(analyzer.pairSisterss)-1] 339 if common.InArray(meld, minCard) { 340 return meld 341 } 342 } 343 if analyzer.hasSoloChain { 344 meld := analyzer.soloChains[len(analyzer.soloChains)-1] 345 if common.InArray(meld, minCard) { 346 return meld 347 } 348 } 349 if analyzer.hasPair { 350 meld := analyzer.pairs[len(analyzer.pairs)-1] 351 if common.InArray(meld, minCard) { 352 remain := RemoveCardByValue(analyzer.cards, GetCardValueMap(meld)) 353 return mixPair(meld, exclude(remain)) 354 } 355 } 356 meld := []int{minCard} 357 remain := RemoveCardByValue(analyzer.cards, GetCardValueMap(meld)) 358 return mixSolo(meld, exclude(remain)) 359 } 360 361 func mixAirplane(meld []int, cards []int) []int { 362 kickerLen := len(meld) / 3 363 if kickerLen > len(cards) { 364 return meld 365 } 366 analyzer := new(LandlordAnalyzer) 367 analyzer.analyze2(cards) 368 if len(analyzer.unrelated) >= kickerLen { 369 newMeld := append([]int{}, meld...) 370 newMeld = append(newMeld, analyzer.unrelated[:kickerLen]...) 371 return newMeld 372 } 373 if len(analyzer.pairs) >= kickerLen { 374 newMeld := append([]int{}, meld...) 375 newMeld = append(newMeld, unite(analyzer.pairs[len(analyzer.pairs)-kickerLen:])...) 376 return newMeld 377 } 378 return meld 379 } 380 381 func mixTrio(meld []int, cards []int) []int { 382 if len(cards) == 0 { 383 return meld 384 } 385 analyzer := new(LandlordAnalyzer) 386 analyzer.analyze2(cards) 387 if len(analyzer.unrelated) > 0 { 388 newMeld := append([]int{}, meld...) 389 newMeld = append(newMeld, analyzer.unrelated[0]) 390 return newMeld 391 } 392 if len(analyzer.pairs) > 0 { 393 newMeld := append([]int{}, meld...) 394 newMeld = append(newMeld, analyzer.pairs[len(analyzer.pairs)-1]...) 395 return newMeld 396 } 397 return meld 398 } 399 400 func mixPair(meld []int, cards []int) []int { 401 if len(cards) == 0 { 402 return meld 403 } 404 analyzer := new(LandlordAnalyzer) 405 analyzer.Analyze(cards) 406 if len(analyzer.airplaneChains) > 0 { 407 airplaneChain := analyzer.airplaneChains[len(analyzer.airplaneChains)-1] 408 newCards := append([]int{}, cards...) 409 newCards = append(newCards, meld...) 410 sort.Sort(sort.Reverse(sort.IntSlice(newCards))) 411 remain := common.Remove(newCards, airplaneChain) 412 return mixAirplane(airplaneChain, remain) 413 } 414 if len(analyzer.trios) > 0 { 415 newMeld := append([]int{}, analyzer.trios[len(analyzer.trios)-1]...) 416 newMeld = append(newMeld, meld...) 417 return newMeld 418 } 419 return meld 420 } 421 422 func mixSolo(meld []int, cards []int) []int { 423 return mixPair(meld, cards) 424 }