3061 lines
92 KiB
Go
3061 lines
92 KiB
Go
package tienlen
|
||
|
||
import (
|
||
"math"
|
||
tienlenApi "mongo.games.com/game/api3th/smart/tienlen"
|
||
"mongo.games.com/goserver/core/logger"
|
||
"sort"
|
||
)
|
||
|
||
// 新tienlenAI 获取牌型
|
||
func GetCardsType(myCards []int32, isYuLe bool) map[int]map[int32][]int32 {
|
||
cards := make([]int32, len(myCards))
|
||
copy(cards, myCards)
|
||
cardsTypeMap := make(map[int]map[int32][]int32)
|
||
//先找炸弹
|
||
bombMap := GetBomb(cards)
|
||
if len(bombMap) > 0 {
|
||
cardsTypeMap[Four_Bomb] = bombMap
|
||
}
|
||
cards = DelCards(cards, bombMap)
|
||
//找连对(5连对>4连对>3连队>2连队)
|
||
pair, pairMap := GetPair(cards)
|
||
//再找连对
|
||
pairStraightMap := GetConsecutivePairs(cards, pair)
|
||
if len(pairStraightMap) > 0 {
|
||
cardsTypeMap[Straight_Twin] = pairStraightMap
|
||
}
|
||
for i, pairStraight := range pairStraightMap {
|
||
if len(pairStraight)/2 <= 2 {
|
||
//先删除2连对 去找顺子和三条
|
||
delete(cardsTypeMap[Straight_Twin], i)
|
||
}
|
||
}
|
||
//先排除2连对
|
||
//排除3连对以上的连对
|
||
for _, pairStraight := range pairStraightMap {
|
||
if isYuLe {
|
||
//娱乐模式 如果3连对以上,则删除3连对以上的连对
|
||
if len(pairStraight)/2 >= 3 {
|
||
delMap := make(map[int32][]int32)
|
||
delMap[int32(len(delMap)+1)] = pairStraight
|
||
cards = DelCards(cards, delMap)
|
||
}
|
||
} else {
|
||
delMap := make(map[int32][]int32)
|
||
delMap[int32(len(delMap)+1)] = pairStraight
|
||
cards = DelCards(cards, delMap)
|
||
}
|
||
}
|
||
//娱乐模式先找三张
|
||
//连队和三条有冲突 既能组成连对 也是三条 这个时候要判断是不是娱乐模式 娱乐模式保留三条拆连对,不是娱乐模式保留连对 拆三条
|
||
if isYuLe {
|
||
threeMap := GetThreeOfkind(cards)
|
||
if len(threeMap) > 0 {
|
||
cardsTypeMap[Triple] = threeMap
|
||
}
|
||
//娱乐模式三张不拆 删除掉三张的牌找顺子
|
||
cards = DelCards(cards, threeMap)
|
||
//判断获取到的三条在不在连对中
|
||
for _, three := range threeMap {
|
||
for i, pairStraight := range pairStraightMap {
|
||
if len(pairStraight)/2 >= 3 {
|
||
continue
|
||
}
|
||
for _, data := range pairStraight {
|
||
if Value(data) == Value(three[0]) {
|
||
//删除连对
|
||
delete(cardsTypeMap[Straight_Twin], i)
|
||
break
|
||
}
|
||
}
|
||
|
||
}
|
||
}
|
||
cards = DelCards(cards, threeMap)
|
||
}
|
||
//找顺子(同花顺>杂色顺子)
|
||
straightMap := findStraights(cards)
|
||
if len(straightMap) > 0 {
|
||
cardsTypeMap[Straight] = straightMap
|
||
cards = DelCards(cards, straightMap)
|
||
}
|
||
//找三张
|
||
if !isYuLe {
|
||
threeMap := GetThreeOfkind(cards)
|
||
if len(threeMap) > 0 {
|
||
cardsTypeMap[Triple] = threeMap
|
||
}
|
||
//不是娱乐模式删除三条
|
||
for i, three := range threeMap {
|
||
for _, pairStraight := range pairStraightMap {
|
||
if len(pairStraight)/2 >= 3 {
|
||
continue
|
||
}
|
||
for _, data := range pairStraight {
|
||
if Value(data) == Value(three[0]) {
|
||
//删除连对
|
||
delete(cardsTypeMap[Triple], i)
|
||
break
|
||
}
|
||
}
|
||
|
||
}
|
||
}
|
||
cards = DelCards(cards, threeMap)
|
||
}
|
||
|
||
//找三顺
|
||
var arr []int32
|
||
for _, three := range cardsTypeMap[Triple] {
|
||
for _, value := range three {
|
||
arr = append(arr, value)
|
||
}
|
||
}
|
||
StraightTripleMap := GetStraightTriple(arr)
|
||
if len(StraightTripleMap) > 0 {
|
||
cardsTypeMap[Straight_Triple] = StraightTripleMap
|
||
}
|
||
//剩余的牌再找对子
|
||
pair, pairMap = GetPair(cards)
|
||
//再找连队
|
||
pairStraightMap = GetConsecutivePairs(cards, pair)
|
||
for _, pairStraight := range pairStraightMap {
|
||
cardsTypeMap[Straight_Twin][int32(len(cardsTypeMap[Straight_Twin])+1)] = pairStraight
|
||
|
||
}
|
||
cards = DelCards(cards, pairStraightMap)
|
||
pair, pairMap = GetPair(cards)
|
||
if len(pairMap) > 0 {
|
||
cardsTypeMap[Twin] = pairMap
|
||
}
|
||
//找单张 移除上面所有牌型的牌,剩余的牌就是单张
|
||
cards = DelCards(cards, pairMap)
|
||
if len(cards) > 0 {
|
||
cardsTypeMap[Single] = make(map[int32][]int32)
|
||
for i := 0; i < len(cards); i++ {
|
||
cardsTypeMap[Single][int32(i)] = []int32{cards[i]}
|
||
}
|
||
}
|
||
return cardsTypeMap
|
||
}
|
||
|
||
// 找炸弹
|
||
func GetBomb(cards []int32) map[int32][]int32 {
|
||
cardCount := make(map[int32]int)
|
||
cardMap := make(map[int32][]int32)
|
||
// 统计每张牌的数量
|
||
|
||
for _, card := range cards {
|
||
cardCount[int32(Value(card))]++
|
||
cardMap[int32(Value(card))] = append(cardMap[int32(Value(card))], card)
|
||
|
||
}
|
||
|
||
// 查找炸弹组合
|
||
bombMap := make(map[int32][]int32)
|
||
for card, count := range cardCount {
|
||
if count == 4 {
|
||
bombMap[card] = cardMap[card]
|
||
}
|
||
}
|
||
return bombMap
|
||
}
|
||
|
||
// 找连对
|
||
func GetConsecutivePairs(cards, pair []int32) map[int32][]int32 {
|
||
// 对切片进行排序
|
||
sort.Slice(pair, func(i, j int) bool {
|
||
return pair[i] < pair[j]
|
||
})
|
||
|
||
// 存储顺子的 map
|
||
straightMap := make(map[int32][]int32)
|
||
for i := 0; i < len(pair); i++ {
|
||
// 如果当前数字与前一个数字相同,则跳过
|
||
if i > 0 && pair[i] == pair[i-1] {
|
||
continue
|
||
}
|
||
|
||
// 初始值为当前数字
|
||
current := pair[i]
|
||
straight := []int32{current}
|
||
|
||
// 检查是否连续递增
|
||
num := i
|
||
for j := i + 1; j < len(pair); j++ {
|
||
if pair[j] == current+1 && pair[j] < 12 {
|
||
straight = append(straight, pair[j])
|
||
current = pair[j]
|
||
num = j
|
||
}
|
||
}
|
||
i = num
|
||
if len(straight) >= 2 {
|
||
straightMap[int32(len(straightMap)+1)] = straight
|
||
}
|
||
}
|
||
//找原牌
|
||
cardsMap := make(map[int32][]int32)
|
||
for i, v := range straightMap {
|
||
for _, v1 := range v {
|
||
num := 0
|
||
for _, v2 := range cards {
|
||
if v1 == int32(Value(v2)) {
|
||
num += 1
|
||
cardsMap[i] = append(cardsMap[i], v2)
|
||
if num == 2 {
|
||
break
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return cardsMap
|
||
|
||
}
|
||
|
||
// 找顺子
|
||
func GetAllStraight(cards []int32, length int) map[int32][]int32 {
|
||
// 对切片进行排序
|
||
sort.Slice(cards, func(i, j int) bool {
|
||
return cards[i] < cards[j]
|
||
})
|
||
|
||
// 存储顺子的 map
|
||
straightMap := make(map[int32][]int32)
|
||
for i := 0; i < len(cards); i++ {
|
||
// 如果当前数字与前一个数字相同,则跳过
|
||
if i > 0 && Value(cards[i]) == Value(cards[i-1]) {
|
||
continue
|
||
}
|
||
|
||
// 初始值为当前数字
|
||
current := cards[i]
|
||
straight := []int32{current}
|
||
|
||
// 检查是否连续递增
|
||
for j := i + 1; j < len(cards); j++ {
|
||
if Value(cards[j]) == Value(current)+1 && Value(cards[j]) < 12 {
|
||
straight = append(straight, cards[j])
|
||
current = cards[j]
|
||
if len(straight) >= length {
|
||
straightMap[int32(len(straightMap)+1)] = straight
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return straightMap
|
||
}
|
||
|
||
// 1.先找到所有长度为3的顺子
|
||
// 2.剩余的牌再和已经取出来的顺子组合,知道组合成更大的牌,
|
||
// 3.合并顺子
|
||
// 4.最后再确定单顺,剩余的牌和三条连对进行组合 看看能不能组成新的顺子(娱乐版不拆三条)拆连队只能拆长度等于2的连对
|
||
// 找出所有长度为3的顺子
|
||
func findStraights(cards []int32) map[int32][]int32 {
|
||
straights := [][]int32{}
|
||
length := len(cards)
|
||
if length < 3 {
|
||
return make(map[int32][]int32)
|
||
}
|
||
|
||
sort.Slice(cards, func(i, j int) bool {
|
||
return Value(cards[i]) < Value(cards[j])
|
||
})
|
||
|
||
for i := 0; i <= length-3; {
|
||
if Value(cards[i]) == Value(cards[i+1]) || Value(cards[i]) >= 10 {
|
||
i++
|
||
continue
|
||
}
|
||
if i+2 < length {
|
||
arr := []int32{}
|
||
value := cards[i]
|
||
arr = append(arr, cards[i])
|
||
for j := i + 1; j <= length-1; j++ {
|
||
if Value(cards[j]) == Value(value) || Value(cards[j]) >= 12 {
|
||
continue
|
||
}
|
||
arr = append(arr, cards[j])
|
||
value = cards[j]
|
||
if len(arr) == 3 {
|
||
break
|
||
}
|
||
}
|
||
if isStraight(arr) {
|
||
straights = append(straights, arr)
|
||
// 从牌组中移除当前顺子的牌
|
||
cards = removeCards(cards, arr)
|
||
length = len(cards) // 更新牌组长度
|
||
} else {
|
||
i++
|
||
}
|
||
} else {
|
||
break
|
||
}
|
||
}
|
||
sort.Slice(straights, func(i, j int) bool {
|
||
return Value(straights[i][0]) < Value(straights[j][0])
|
||
})
|
||
//2.剩余的牌再和已经取出来的顺子组合,知道组合成更大的牌,
|
||
removeCard := []int32{}
|
||
for _, card := range cards {
|
||
for i, straight := range straights {
|
||
if Value(card) == Value(straight[len(straight)-1]+1) && Value(card) < 12 {
|
||
straight = append(straight, card)
|
||
removeCard = append(removeCard, card)
|
||
straights[i] = straight
|
||
break
|
||
}
|
||
}
|
||
}
|
||
cards = removeCards(cards, removeCard)
|
||
//3.合并顺子
|
||
for i := 0; i < len(straights)-1; i++ {
|
||
if Value(straights[i][len(straights[i])-1]) == Value(straights[i+1][0])-1 {
|
||
straights[i] = append(straights[i], straights[i+1]...)
|
||
straights = append(straights[:i+1], straights[i+2:]...)
|
||
i -= 1
|
||
}
|
||
}
|
||
//转正map
|
||
straightsMap := make(map[int32][]int32)
|
||
for i, straight := range straights {
|
||
straightsMap[int32(i)] = straight
|
||
}
|
||
return straightsMap
|
||
}
|
||
|
||
// 暂时不做 现在的找牌顺序可以兼容这种 拆三条 二连对组顺子
|
||
func TwoFindStraights(cards []int32, isYuLe bool, cardsType map[int]map[int32][]int32, straights [][]int32) {
|
||
//4.剩余的牌和三条连对进行组合 看看能不能组成新的顺子(娱乐版不拆三条)拆连队只能拆长度等于2的连对
|
||
//找相邻的两张牌
|
||
twoCards := [][]int32{}
|
||
for i := 0; i < len(cards)-1; i++ {
|
||
if cards[i] == cards[i+1]-1 || cards[i] == cards[i+1]-2 {
|
||
twoCards = append(twoCards, []int32{cards[i], cards[i+1]})
|
||
i += 1
|
||
}
|
||
}
|
||
if len(twoCards) > 0 {
|
||
indexesToRemove := []int{}
|
||
for _, twoCard := range twoCards {
|
||
value := twoCard
|
||
//添加三条 和连对的牌进去再找顺子
|
||
if !isYuLe {
|
||
threeCards := cardsType[Triple]
|
||
for i, three := range threeCards {
|
||
//logger.Logger.Tracef("开始拆三条组顺子 three = %d \n", three)
|
||
value = append(value, three[0])
|
||
sort.Slice(value, func(i, j int) bool {
|
||
return value[i] < value[j]
|
||
})
|
||
//判断是不是顺子
|
||
if isStraight(value) {
|
||
//找到顺子了 移除三张
|
||
cards = removeCards(cards, value)
|
||
delete(cardsType[Triple], i)
|
||
straights = append(straights, value)
|
||
indexesToRemove = append(indexesToRemove, int(i))
|
||
cards = append(cards, three[1], three[2])
|
||
break
|
||
}
|
||
}
|
||
}
|
||
|
||
}
|
||
// 根据索引从切片中删除元素
|
||
for i := len(indexesToRemove) - 1; i >= 0; i-- {
|
||
twoCards = append(twoCards[:indexesToRemove[i]], twoCards[indexesToRemove[i]+1:]...)
|
||
}
|
||
//添加二连对组顺子
|
||
|
||
//最后在合并一下顺子
|
||
for i := 0; i < len(straights)-1; i++ {
|
||
if straights[i][len(straights[i])-1] == straights[i+1][0]-1 {
|
||
straights[i] = append(straights[i], straights[i+1]...)
|
||
straights = append(straights[:i+1], straights[i+2:]...)
|
||
i -= 1
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
func removeCards(cards []int32, toRemove []int32) []int32 {
|
||
newCards := []int32{}
|
||
removed := make([]bool, len(cards))
|
||
|
||
for _, card := range toRemove {
|
||
for i, c := range cards {
|
||
if c == card && !removed[i] {
|
||
removed[i] = true
|
||
break
|
||
}
|
||
}
|
||
}
|
||
|
||
for i, card := range cards {
|
||
if !removed[i] {
|
||
newCards = append(newCards, card)
|
||
}
|
||
}
|
||
|
||
return newCards
|
||
}
|
||
|
||
func isStraight(cards []int32) bool {
|
||
if len(cards) < 3 {
|
||
return false
|
||
}
|
||
return Value(cards[1])-Value(cards[0]) == 1 && Value(cards[2])-Value(cards[1]) == 1
|
||
}
|
||
|
||
// 找三张
|
||
func GetThreeOfkind(cards []int32) map[int32][]int32 {
|
||
cardCount := make(map[int32]int)
|
||
var three []int32
|
||
cardMap := make(map[int32][]int32)
|
||
// 统计每张牌的数量
|
||
for _, card := range cards {
|
||
cardCount[int32(Value(card))]++
|
||
cardMap[int32(Value(card))] = append(cardMap[int32(Value(card))], card)
|
||
}
|
||
// 查找炸弹组合
|
||
threeMap := make(map[int32][]int32)
|
||
for card, count := range cardCount {
|
||
if count >= 3 {
|
||
three = append(three, card)
|
||
threeMap[card] = cardMap[card]
|
||
}
|
||
}
|
||
return threeMap
|
||
}
|
||
|
||
// 找三顺
|
||
func GetStraightTriple(cards []int32) map[int32][]int32 {
|
||
sort.Slice(cards, func(i, j int) bool {
|
||
if Value(cards[i]) == Value(cards[j]) {
|
||
return cards[i] < cards[j]
|
||
}
|
||
return Value(cards[i]) < Value(cards[j])
|
||
})
|
||
result := make(map[int32][]int32)
|
||
for i := 0; i < len(cards)-3; {
|
||
num := 1
|
||
for j := i + 3; j < len(cards); {
|
||
if Value(cards[i]) == Value(cards[j])-num && Value(cards[j]) < 12 {
|
||
num += 1
|
||
}
|
||
j += 3
|
||
}
|
||
if num >= 2 {
|
||
arr := cards[i : i+num*3]
|
||
result[int32(Value(arr[len(arr)-1]))] = arr
|
||
}
|
||
i += 3
|
||
|
||
}
|
||
return result
|
||
}
|
||
|
||
// 找对子
|
||
func GetPair(cards []int32) ([]int32, map[int32][]int32) {
|
||
cardCount := make(map[int32]int)
|
||
cardMap := make(map[int32][]int32)
|
||
// 统计每张牌的数量
|
||
for _, card := range cards {
|
||
cardCount[int32(Value(card))]++
|
||
cardMap[int32(Value(card))] = append(cardMap[int32(Value(card))], card)
|
||
}
|
||
// 查找对子组合
|
||
pairMap := make(map[int32][]int32)
|
||
var pair []int32
|
||
for card, count := range cardCount {
|
||
if count >= 2 {
|
||
//logger.Logger.Tracef("\n找到所有的对子:%d \n", card)
|
||
pair = append(pair, card)
|
||
pairMap[card] = cardMap[card]
|
||
}
|
||
}
|
||
return pair, pairMap
|
||
}
|
||
|
||
// 牌型转换
|
||
func CardsChange(cards []int32) []int {
|
||
//map key-相同牌数量 value-key:
|
||
var cardChange []int
|
||
for _, card := range cards {
|
||
cardChange = append(cardChange, Value(card))
|
||
}
|
||
sort.Ints(cardChange)
|
||
return cardChange
|
||
}
|
||
|
||
// 删除牌
|
||
func DelCards(cards []int32, delCards map[int32][]int32) []int32 {
|
||
// 创建一个新的切片,用于存储不需要删除的元素
|
||
newCards := make([]int32, 0, len(cards))
|
||
|
||
// 遍历 cards 中的元素
|
||
for _, card := range cards {
|
||
// 检查当前元素是否需要删除
|
||
shouldDelete := false
|
||
for _, delCard := range delCards {
|
||
for _, del := range delCard {
|
||
if card == del {
|
||
shouldDelete = true
|
||
break
|
||
}
|
||
}
|
||
}
|
||
|
||
// 如果不需要删除,则将元素添加到新的切片中
|
||
if !shouldDelete {
|
||
newCards = append(newCards, card)
|
||
}
|
||
}
|
||
|
||
return newCards
|
||
}
|
||
|
||
// 获取牌型分计算
|
||
func GetCardTypeScore(cardsType map[int]map[int32][]int32, isYuLe bool, cards []int32) (int, int) {
|
||
//计算每张牌的牌值
|
||
cardValues := []int{
|
||
-0, -100, -80, -60, -40, -20, 0, 20, 50, 90, 140, 200, 300,
|
||
-115, -95, -75, -55, -35, -15, 5, 25, 55, 95, 145, 205, 325,
|
||
-110, -90, -70, -50, -30, -10, 10, 30, 60, 100, 150, 210, 350,
|
||
-105, -85, -65, -45, -25, -5, 15, 35, 65, 105, 155, 215, 400,
|
||
}
|
||
//logger.Logger.Trace("计算牌型分 cardsType = ", cardsType)
|
||
//计算牌型分值
|
||
var score int
|
||
//炸弹
|
||
if len(cardsType[Four_Bomb]) > 0 {
|
||
if isYuLe {
|
||
score += len(cardsType[Four_Bomb]) * 1000
|
||
} else {
|
||
score += len(cardsType[Four_Bomb]) * 700
|
||
}
|
||
}
|
||
//连队
|
||
if len(cardsType[Straight_Twin]) > 0 {
|
||
for _, twin := range cardsType[Straight_Twin] {
|
||
switch len(twin) / 2 {
|
||
case 5:
|
||
score += 500
|
||
case 4:
|
||
score += 400
|
||
case 3:
|
||
score += 300
|
||
case 2:
|
||
score += 200
|
||
}
|
||
}
|
||
}
|
||
//顺子
|
||
if len(cardsType[Straight]) > 0 {
|
||
for _, straight := range cardsType[Straight] {
|
||
score += len(straight)*100 + (len(straight)-3)*(cardValues[straight[len(straight)-1]]/3)
|
||
}
|
||
|
||
}
|
||
//三张
|
||
if len(cardsType[Triple]) > 0 {
|
||
for _, triples := range cardsType[Triple] {
|
||
if Value(triples[0]) < 7 {
|
||
score += int(math.Abs(float64(250 + cardValues[triples[2]])))
|
||
} else {
|
||
score += cardValues[triples[0]] + cardValues[triples[1]] + cardValues[triples[2]]
|
||
}
|
||
}
|
||
if isYuLe {
|
||
score += len(cardsType[Triple]) * 300
|
||
}
|
||
}
|
||
//两对
|
||
if len(cardsType[Twin]) > 0 {
|
||
for _, twins := range cardsType[Twin] {
|
||
if Value(twins[0]) < 7 {
|
||
score += cardValues[twins[1]] / 2
|
||
} else {
|
||
score += cardValues[twins[0]] + cardValues[twins[1]]
|
||
}
|
||
}
|
||
}
|
||
|
||
//删除三连对以上且三连对小于10的牌
|
||
copyCards := make([]int32, len(cards))
|
||
copy(copyCards, cards)
|
||
copyCards = DelCards(copyCards, cardsType[Four_Bomb])
|
||
for _, straightTwin := range cardsType[Straight_Twin] {
|
||
delMap := make(map[int32][]int32)
|
||
if len(straightTwin)/2 >= 3 && Value(straightTwin[len(straightTwin)-1]) < 10 {
|
||
delMap[int32(len(delMap)+1)] = straightTwin
|
||
copyCards = DelCards(copyCards, delMap)
|
||
}
|
||
}
|
||
|
||
for _, card := range copyCards {
|
||
score += cardValues[card]
|
||
}
|
||
handCardnum := len(cardsType[Four_Bomb]) + len(cardsType[Straight_Twin]) + len(cardsType[Straight]) + len(cardsType[Triple]) + len(cardsType[Twin]) + len(cardsType[Single])
|
||
if isYuLe {
|
||
handCardnum -= (len(cardsType[Triple]) * 2)
|
||
}
|
||
if handCardnum <= 1 {
|
||
handCardnum = 1
|
||
if isYuLe && handCardnum == 1 {
|
||
if len(cardsType[Triple]) > 0 {
|
||
if len(cards) > 5 {
|
||
handCardnum = 2
|
||
}
|
||
}
|
||
}
|
||
}
|
||
if Have6StraightTwin(cards) ||
|
||
Have12Straight(cards) ||
|
||
Have2FourBomb(cards) {
|
||
return 9999, 1
|
||
}
|
||
return score - (handCardnum-5)*150, handCardnum
|
||
}
|
||
|
||
// 压牌 isWin-是否胜利
|
||
func GetPressCards(cards, lastCards []int32, data *tienlenApi.PredictRequest, pos int32) []int32 {
|
||
logger.Logger.Tracef("---------------压牌开始-------------------")
|
||
sort.Slice(cards, func(i, j int) bool {
|
||
if Value(cards[i]) == Value(cards[j]) {
|
||
return cards[i] < cards[j]
|
||
}
|
||
return Value(cards[i]) < Value(cards[j])
|
||
})
|
||
isWin := data.IsWin
|
||
//测试代码
|
||
isWin = true
|
||
logger.Logger.Trace("压牌 调控输赢 isWin = ", isWin)
|
||
outCards := []int32{}
|
||
//压牌测试代码
|
||
// cards = []int32{6, 19, 2, 28, 41, 43, 12, 25}
|
||
// lastCards = []int32{14, 27}
|
||
// pos = 0
|
||
// data.Cards_left_2 = []int32{45, 32}
|
||
// data.Cards_left_3 = nil
|
||
// data.Cards_left_1 = nil
|
||
// data.Last_pos = 2
|
||
|
||
lastPos := data.Last_pos //上家出牌人的位置
|
||
logger.Logger.Tracef(" 上家出牌人的位置%d,出的牌:%v\n", lastPos, lastCards)
|
||
isYuLe := data.IsTienLenYule
|
||
isEnd := data.IsEnd
|
||
winSnids := data.WinSnids
|
||
logger.Logger.Trace("当前模式是否是打到底%v\n,当前获胜玩家:%v\n", isEnd, winSnids)
|
||
//获取牌型
|
||
cardsTypeMap := GetCardsType(cards, isYuLe)
|
||
score, handCardnum := GetCardTypeScore(cardsTypeMap, isYuLe, cards)
|
||
logger.Logger.Tracef("压牌 获取牌型:%v\n,分值:%d\n手牌:%d、n,我的位置:%d\n", cardsTypeMap, score, handCardnum, pos)
|
||
//获取出牌人的 手数
|
||
otherCards := getOtherPlayerCards(pos, lastPos, data)
|
||
otherCardsTypeMap := GetCardsType(otherCards, isYuLe)
|
||
lastScore, lastHandCardnum := GetCardTypeScore(otherCardsTypeMap, isYuLe, otherCards)
|
||
logger.Logger.Tracef("压牌,获取出牌玩家的剩余牌的牌型:", otherCardsTypeMap, "分值:", lastScore, "手牌:", lastHandCardnum, "\n")
|
||
//获取下一家的位置和剩余的牌
|
||
nextPos, nextCards := GetNextPos(pos, data)
|
||
logger.Logger.Tracef("我的位置:%d\n,获取下家牌和位置:nextPos = %d\n,nextCards := %v\n", pos, nextPos, nextCards)
|
||
isRule, ruleType := RulePopEnable_yl(lastCards)
|
||
if isRule {
|
||
switch ruleType {
|
||
case Single:
|
||
//单张
|
||
cardsMap := cardsTypeMap[Single]
|
||
//转成数组
|
||
singleArr := []int32{}
|
||
for _, single := range cardsMap {
|
||
singleArr = append(singleArr, single[0])
|
||
}
|
||
if isEnd && !isYuLe {
|
||
sort.Slice(singleArr, func(i, j int) bool {
|
||
if Value(singleArr[i]) == Value(singleArr[j]) {
|
||
return singleArr[i] < singleArr[j]
|
||
}
|
||
return Value(singleArr[i]) < Value(singleArr[j])
|
||
})
|
||
}
|
||
//如果我的下一家剩余一张牌 出比他大的牌
|
||
if len(singleArr) > 0 {
|
||
if len(singleArr) == 2 && len(cards) == 2 {
|
||
for _, mycard := range singleArr {
|
||
if getMaxCardTypeNum(Single, []int32{mycard}, pos, data) {
|
||
outCards = []int32{mycard}
|
||
}
|
||
}
|
||
} else {
|
||
for _, card := range singleArr {
|
||
if Value(card) >= Value(lastCards[0]) {
|
||
if Value(card) == Value(lastCards[0]) {
|
||
if Color(card) < Color(lastCards[0]) {
|
||
continue
|
||
}
|
||
}
|
||
|
||
if len(nextCards) == 1 {
|
||
if Value(card) >= Value(nextCards[0]) {
|
||
if Value(card) == Value(nextCards[0]) {
|
||
if Color(card) > Color(nextCards[0]) {
|
||
outCards = []int32{card}
|
||
break
|
||
}
|
||
} else {
|
||
outCards = []int32{card}
|
||
break
|
||
}
|
||
}
|
||
} else {
|
||
outCards = []int32{card}
|
||
break
|
||
}
|
||
}
|
||
}
|
||
}
|
||
} else {
|
||
//找顺子交集 返回值[][]int32
|
||
result := FindIntersection(cardsTypeMap[Straight])
|
||
if len(result) > 0 {
|
||
sort.Slice(cards, func(i, j int) bool {
|
||
if Value(cards[i]) == Value(cards[j]) {
|
||
return cards[i] < cards[j]
|
||
}
|
||
return Value(cards[i]) < Value(cards[j])
|
||
})
|
||
for _, arr := range result {
|
||
for _, card := range arr {
|
||
if Value(card) >= Value(lastCards[0]) {
|
||
if Value(card) == Value(lastCards[0]) {
|
||
if Color(card) < Color(lastCards[0]) {
|
||
continue
|
||
}
|
||
}
|
||
if len(nextCards) == 1 {
|
||
if Value(card) >= Value(nextCards[0]) {
|
||
if Value(card) == Value(nextCards[0]) {
|
||
if Color(card) > Color(nextCards[0]) {
|
||
outCards = []int32{card}
|
||
break
|
||
//return card
|
||
}
|
||
} else {
|
||
outCards = []int32{card}
|
||
break
|
||
}
|
||
}
|
||
} else {
|
||
outCards = []int32{card}
|
||
break
|
||
}
|
||
}
|
||
}
|
||
if len(outCards) > 0 {
|
||
break
|
||
}
|
||
}
|
||
}
|
||
}
|
||
if isWin {
|
||
//拆牌 先找顺子的交集 拆对子 拆2 拆长度大于3的顺子 最后找大于这张出牌的牌除了炸弹 出牌这家只剩一首牌了
|
||
if len(outCards) == 0 && len(cardsTypeMap[Twin]) > 0 {
|
||
logger.Logger.Trace("拆对子")
|
||
twinMap := cardsTypeMap[Twin]
|
||
//拆小于2的对子
|
||
for _, card := range twinMap {
|
||
if Value(card[0]) == 12 {
|
||
//排除掉对2
|
||
continue
|
||
}
|
||
//先拆小于2的对子
|
||
if Value(card[0]) >= Value(lastCards[0]) {
|
||
if Value(card[0]) == Value(lastCards[0]) {
|
||
if Color(card[0]) < Color(lastCards[0]) {
|
||
continue
|
||
}
|
||
}
|
||
if len(nextCards) == 1 {
|
||
if Value(card[0]) >= Value(nextCards[0]) {
|
||
if Value(card[0]) == Value(nextCards[0]) {
|
||
if Color(card[0]) > Color(nextCards[0]) {
|
||
outCards = []int32{card[0]}
|
||
break
|
||
}
|
||
} else {
|
||
outCards = []int32{card[0]}
|
||
break
|
||
}
|
||
}
|
||
} else {
|
||
//玩家出完这张牌 还剩一张 剩余的牌比我现在出的牌大
|
||
if len(otherCards) == 1 && Value(otherCards[0]) >= Value(card[0]) {
|
||
continue
|
||
}
|
||
outCards = []int32{card[0]}
|
||
break
|
||
}
|
||
}
|
||
}
|
||
//判断一下下一家剩1张牌比我的大的情况
|
||
if len(outCards) > 0 {
|
||
break
|
||
}
|
||
}
|
||
//直接拆2上
|
||
if len(outCards) == 0 &&
|
||
(lastHandCardnum <= 4 || handCardnum <= 3 ||
|
||
(len(nextCards) == 1 && Value(nextCards[0]) >= Value(lastCards[0]))) {
|
||
for _, card := range cards {
|
||
if Value(card) == 12 && Value(card) >= Value(lastCards[0]) {
|
||
if Value(card) == Value(lastCards[0]) {
|
||
if Color(card) > Color(lastCards[0]) {
|
||
outCards = []int32{card}
|
||
break
|
||
} else {
|
||
continue
|
||
}
|
||
} else {
|
||
outCards = []int32{card}
|
||
break
|
||
}
|
||
|
||
}
|
||
}
|
||
if len(outCards) > 0 && len(otherCards) == 1 && Value(otherCards[0]) >= Value(outCards[0]) {
|
||
if Value(outCards[0]) == Value(otherCards[0]) {
|
||
if Color(outCards[0]) < Color(otherCards[0]) {
|
||
if Value(cards[len(cards)-1]) >= Value(lastCards[0]) {
|
||
outCards = []int32{cards[len(cards)-1]}
|
||
}
|
||
}
|
||
} else {
|
||
if Value(cards[len(cards)-1]) >= Value(lastCards[0]) {
|
||
outCards = []int32{cards[len(cards)-1]}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
//拆连对 map[int32][]int32
|
||
if len(outCards) == 0 && len(cardsTypeMap[Straight_Twin]) > 0 {
|
||
for _, straightTwin := range cardsTypeMap[Straight_Twin] {
|
||
if len(straightTwin)/2 == 2 || lastHandCardnum == 1 {
|
||
for _, twin := range straightTwin {
|
||
if Value(twin) > Value(lastCards[0]) {
|
||
outCards = []int32{twin}
|
||
break
|
||
}
|
||
}
|
||
if len(outCards) > 0 {
|
||
break
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
if !isYuLe {
|
||
//拆三条
|
||
if len(outCards) == 0 && len(cardsTypeMap[Triple]) > 0 {
|
||
tripleMap := cardsTypeMap[Triple]
|
||
for _, card := range tripleMap {
|
||
if Value(card[0]) >= Value(lastCards[0]) {
|
||
if Value(card[0]) == Value(lastCards[0]) {
|
||
if Color(card[0]) < Color(lastCards[0]) {
|
||
continue
|
||
}
|
||
}
|
||
if len(nextCards) == 1 {
|
||
if Value(card[0]) >= Value(nextCards[0]) {
|
||
if Value(card[0]) == Value(nextCards[0]) {
|
||
if Color(card[0]) > Color(nextCards[0]) {
|
||
outCards = []int32{card[0]}
|
||
break
|
||
}
|
||
} else {
|
||
outCards = []int32{card[0]}
|
||
break
|
||
}
|
||
}
|
||
} else {
|
||
outCards = []int32{card[0]}
|
||
break
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
//拆长度>3的顺子
|
||
if len(outCards) == 0 && len(cardsTypeMap[Straight]) > 0 {
|
||
straightMap := cardsTypeMap[Straight]
|
||
for _, card := range straightMap {
|
||
if len(card) <= 3 && lastHandCardnum != 1 {
|
||
continue
|
||
}
|
||
if Value(card[len(card)-1]) >= Value(lastCards[0]) {
|
||
if Value(card[0]) == Value(lastCards[0]) {
|
||
if Color(card[0]) < Color(lastCards[0]) {
|
||
continue
|
||
}
|
||
}
|
||
if len(nextCards) == 1 {
|
||
if Value(card[0]) >= Value(nextCards[0]) {
|
||
if Value(card[0]) == Value(nextCards[0]) {
|
||
if Color(card[0]) > Color(nextCards[0]) {
|
||
outCards = []int32{card[len(card)-1]}
|
||
break
|
||
}
|
||
} else {
|
||
outCards = []int32{card[len(card)-1]}
|
||
break
|
||
}
|
||
}
|
||
} else {
|
||
outCards = []int32{card[len(card)-1]}
|
||
break
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
if len(outCards) == 0 && Value(lastCards[0]) == 12 {
|
||
//找三连对 >四连对 >五连对 > 炸弹
|
||
straightTwinMap := cardsTypeMap[Straight_Twin]
|
||
//找最小长度的key
|
||
if len(straightTwinMap) > 0 {
|
||
for _, straightTwin := range straightTwinMap {
|
||
if len(straightTwin)/2 >= 3 {
|
||
outCards = straightTwin
|
||
logger.Logger.Trace("-----------------单张压牌 找到连对!", outCards)
|
||
break
|
||
//return straightTwin
|
||
}
|
||
}
|
||
}
|
||
//找炸弹
|
||
if !isYuLe {
|
||
if len(outCards) == 0 && len(cardsTypeMap[Four_Bomb]) > 0 && Value(lastCards[0]) == 12 {
|
||
minKey := findMinKey(cardsTypeMap[Four_Bomb])
|
||
outCards = cardsTypeMap[Four_Bomb][minKey]
|
||
}
|
||
}
|
||
|
||
}
|
||
if isYuLe {
|
||
//找炸弹
|
||
if len(outCards) == 0 && len(cardsTypeMap[Four_Bomb]) > 0 && (lastHandCardnum <= 2 || handCardnum <= 2) {
|
||
minKey := findMinKey(cardsTypeMap[Four_Bomb])
|
||
outCards = cardsTypeMap[Four_Bomb][minKey]
|
||
}
|
||
}
|
||
if len(outCards) > 0 {
|
||
if Value(lastCards[0]) == 12 && Value(outCards[0]) == 12 && lastHandCardnum != 1 {
|
||
//如果出牌玩家剩余手数大于2 或者我的剩余手数小于等于3
|
||
//存在一种情况 上家剩余1张牌 其他人出单张 上家不要 这个时候我执行了这个判断 没有出2去接牌 && 我的上家单张数量>=2 ||上家剩余1张牌了 我要跑牌了
|
||
_, myLastCards := GetLastPos(pos, data)
|
||
if ((lastHandCardnum > 2 && len(otherCardsTypeMap[Single]) > 2) || (handCardnum > 3 && len(cardsTypeMap[Single]) >= 2)) && len(myLastCards) >= 2 {
|
||
if lastHandCardnum > 3 {
|
||
logger.Logger.Tracef("上家出2剩余的手数:%d,我的手数:%d\n,让一手", lastHandCardnum, handCardnum)
|
||
outCards = []int32{}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
if len(outCards) == 0 {
|
||
if len(nextCards) == 1 && Value(lastCards[0]) < Value(nextCards[0]) {
|
||
if Value(cards[len(cards)-1]) >= Value(nextCards[0]) {
|
||
outCards = []int32{cards[len(cards)-1]}
|
||
}
|
||
}
|
||
}
|
||
//强压
|
||
if len(outCards) == 0 && (len(lastCards) == 1 || len(nextCards) == 1) {
|
||
if Value(cards[len(cards)-1]) >= Value(lastCards[0]) {
|
||
outCards = []int32{cards[len(cards)-1]}
|
||
}
|
||
|
||
}
|
||
//打到底 最后一首牌判断
|
||
if len(otherCards) == 1 && (!isYuLe && isEnd) && (winSnids == nil || len(winSnids) == 0) && len(outCards) != 0 && nextPos != lastPos {
|
||
if Value(outCards[0]) == Value(cards[len(cards)-1]) && handCardnum > 2 {
|
||
if Value(outCards[0]) <= Value(otherCards[0]) {
|
||
if Value(outCards[0]) == Value(otherCards[0]) {
|
||
if Color(outCards[0]) < Color(otherCards[0]) {
|
||
logger.Logger.Tracef("判断我的最大牌小于上家剩余的牌,不出!")
|
||
outCards = []int32{}
|
||
}
|
||
} else {
|
||
logger.Logger.Trace("打到底最后一手牌牌,让一手!")
|
||
outCards = []int32{}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
if isEnd && len(otherCards) == 0 && len(outCards) > 0 {
|
||
if len(nextCards) == 1 {
|
||
//在这加一道防线
|
||
if Value(outCards[0]) < Value(nextCards[0]) {
|
||
//出最大牌
|
||
if Value(cards[len(cards)-1]) >= Value(lastCards[0]) && Value(cards[len(cards)-1]) >= Value(nextCards[0]) {
|
||
outCards = []int32{cards[len(cards)-1]}
|
||
}
|
||
|
||
}
|
||
}
|
||
}
|
||
if len(outCards) == 0 && len(lastCards) == 1 && nextPos == lastPos {
|
||
//出最大的牌
|
||
if Value(cards[len(cards)-1]) >= Value(lastCards[0]) {
|
||
outCards = []int32{cards[len(cards)-1]}
|
||
}
|
||
}
|
||
//打到底 出牌人打完了
|
||
if !IsPressed(isYuLe, isEnd, otherCards, lastCards, data, pos, lastPos, nextPos, handCardnum, Single) {
|
||
logger.Logger.Trace("出牌人打完牌了,我过一手!!!!", lastCards)
|
||
outCards = []int32{}
|
||
}
|
||
logger.Logger.Tracef("--------------单张压牌完毕,出的牌:", outCards)
|
||
return outCards
|
||
case Twin:
|
||
//对子
|
||
cardsMap := cardsTypeMap[Twin]
|
||
if len(cardsMap) > 0 {
|
||
for _, card := range cardsMap {
|
||
if lastHandCardnum == 1 && len(otherCards) == 2 && Value(otherCards[len(otherCards)-1]) >= Value(card[1]) {
|
||
if Value(otherCards[len(otherCards)-1]) == Value(card[1]) {
|
||
if Color(otherCards[len(otherCards)-1]) > Color(card[1]) {
|
||
continue
|
||
}
|
||
} else {
|
||
continue
|
||
}
|
||
}
|
||
if Value(card[1]) >= Value(lastCards[1]) {
|
||
if Value(card[1]) == 12 {
|
||
//判断能不能直接出对2
|
||
if handCardnum > 3 && lastHandCardnum > 3 {
|
||
continue
|
||
}
|
||
}
|
||
if Value(card[1]) == Value(lastCards[1]) {
|
||
//判断花色
|
||
if Color(card[1]) > Color(lastCards[1]) {
|
||
outCards = card
|
||
break
|
||
}
|
||
} else {
|
||
outCards = card
|
||
break
|
||
}
|
||
}
|
||
}
|
||
//再找一遍
|
||
if len(outCards) == 0 {
|
||
for _, card := range cardsMap {
|
||
if Value(card[1]) >= Value(lastCards[1]) {
|
||
if Value(card[1]) == 12 {
|
||
//判断能不能直接出对2
|
||
if handCardnum > 3 && lastHandCardnum > 3 {
|
||
continue
|
||
}
|
||
}
|
||
if Value(card[1]) == Value(lastCards[1]) {
|
||
//判断花色
|
||
if Color(card[1]) > Color(lastCards[1]) {
|
||
outCards = card
|
||
break
|
||
}
|
||
} else {
|
||
outCards = card
|
||
break
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
logger.Logger.Trace("找到对子-------------------outCards =", outCards)
|
||
//拆连对
|
||
if isWin {
|
||
straightTwinMap := cardsTypeMap[Straight_Twin]
|
||
if len(outCards) == 0 {
|
||
if Value(lastCards[0]) == 12 {
|
||
if len(straightTwinMap) > 0 {
|
||
for _, straightTwin := range straightTwinMap {
|
||
if len(straightTwin)/2 >= 4 {
|
||
outCards = straightTwin
|
||
break
|
||
}
|
||
}
|
||
}
|
||
} else {
|
||
//拆连对
|
||
if len(straightTwinMap) > 0 {
|
||
for _, straightTwin := range straightTwinMap {
|
||
if len(straightTwin)/2 >= 2 {
|
||
//判断第一个和最后一位
|
||
if Value(straightTwin[0]) >= Value(lastCards[0]) {
|
||
if Color(straightTwin[1]) > Color(lastCards[1]) {
|
||
outCards = []int32{straightTwin[0], straightTwin[1]}
|
||
break
|
||
}
|
||
} else {
|
||
//判断最后一位
|
||
if Value(straightTwin[3]) >= Value(lastCards[0]) {
|
||
if Color(straightTwin[3]) > Color(lastCards[1]) {
|
||
outCards = []int32{straightTwin[2], straightTwin[3]}
|
||
break
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
//拆三条
|
||
//找最大的三条拆
|
||
if !isYuLe {
|
||
if len(outCards) == 0 && len(cardsTypeMap[Triple]) > 0 {
|
||
for _, triple := range cardsTypeMap[Triple] {
|
||
if Value(triple[0]) > Value(lastCards[0]) {
|
||
outCards = []int32{triple[0], triple[1]}
|
||
logger.Logger.Trace("拆三条压对子 outCards = ", outCards)
|
||
break
|
||
|
||
}
|
||
}
|
||
|
||
}
|
||
} else {
|
||
if len(outCards) == 0 && len(cardsTypeMap[Triple]) > 0 && (lastHandCardnum <= 2 || handCardnum <= 3) {
|
||
for _, triple := range cardsTypeMap[Triple] {
|
||
if Value(triple[0]) > Value(lastCards[0]) {
|
||
outCards = []int32{triple[0], triple[1]}
|
||
logger.Logger.Trace("拆三条压对子 outCards = ", outCards)
|
||
break
|
||
}
|
||
}
|
||
|
||
}
|
||
}
|
||
}
|
||
//找炸弹
|
||
if isYuLe {
|
||
if len(outCards) == 0 && len(cardsTypeMap[Four_Bomb]) > 0 && (lastHandCardnum <= 2 || handCardnum <= 2) {
|
||
minKey := findMinKey(cardsTypeMap[Four_Bomb])
|
||
outCards = cardsTypeMap[Four_Bomb][minKey]
|
||
}
|
||
} else {
|
||
if len(outCards) == 0 && len(cardsTypeMap[Four_Bomb]) > 0 && Value(lastCards[0]) == 12 {
|
||
minKey := findMinKey(cardsTypeMap[Four_Bomb])
|
||
outCards = cardsTypeMap[Four_Bomb][minKey]
|
||
}
|
||
}
|
||
if len(outCards) > 0 {
|
||
if Value(lastCards[0]) == 12 && Value(outCards[0]) == 12 {
|
||
//如果出牌玩家剩余手数大于2 或者我的剩余手数小于等于3
|
||
if lastHandCardnum > 3 && (len(otherCardsTypeMap[Twin]) > 2 || len(otherCardsTypeMap[Single]) > 2) || (handCardnum > 3 && len(cardsTypeMap[Single]) > 2) {
|
||
if lastHandCardnum > 1 {
|
||
logger.Logger.Tracef("上家出2剩余的手数:%d,我的手数:%d\n,让一手", lastHandCardnum, handCardnum)
|
||
outCards = []int32{}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
if len(outCards) == 0 && lastHandCardnum <= 2 {
|
||
//重组对子 找大对子
|
||
_, pairMap := GetPair(cards)
|
||
if len(pairMap) > 0 {
|
||
maxkey := int32(-1)
|
||
for key, pairs := range pairMap {
|
||
if Value(pairs[0]) >= Value(lastCards[0]) {
|
||
if key > maxkey {
|
||
maxkey = key
|
||
}
|
||
}
|
||
}
|
||
if maxkey != -1 {
|
||
outCards = append(outCards, pairMap[maxkey][0], pairMap[maxkey][1])
|
||
}
|
||
}
|
||
}
|
||
if len(otherCards) == 2 && lastHandCardnum == 1 && (!isYuLe && isEnd) && (winSnids == nil || len(winSnids) == 0) && len(outCards) != 0 && nextPos != lastPos {
|
||
if Value(outCards[0]) == Value(cards[len(cards)-1]) && handCardnum > 2 {
|
||
if Value(outCards[0]) <= Value(otherCards[0]) {
|
||
if Value(outCards[0]) == Value(otherCards[0]) {
|
||
if Color(outCards[0]) < Color(otherCards[0]) {
|
||
outCards = []int32{}
|
||
}
|
||
} else {
|
||
outCards = []int32{}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
//打到底 出牌人打完了
|
||
if !IsPressed(isYuLe, isEnd, otherCards, lastCards, data, pos, lastPos, nextPos, handCardnum, Twin) {
|
||
outCards = []int32{}
|
||
}
|
||
logger.Logger.Trace("--------------压牌完毕,出的牌:", outCards)
|
||
return outCards
|
||
case Straight:
|
||
//顺子
|
||
cardsMap := cardsTypeMap[Straight]
|
||
//获取顺子长度
|
||
|
||
for _, card := range cardsMap {
|
||
if len(card) == len(lastCards) {
|
||
if Value(card[len(card)-1]) >= Value(lastCards[len(lastCards)-1]) {
|
||
if Value(card[len(card)-1]) == Value(lastCards[len(lastCards)-1]) {
|
||
//比较花色
|
||
if Color(card[len(card)-1]) > Color(lastCards[len(lastCards)-1]) {
|
||
outCards = card
|
||
break
|
||
//return card
|
||
}
|
||
} else {
|
||
outCards = card
|
||
break
|
||
//return card
|
||
}
|
||
}
|
||
} else if len(card) > len(lastCards) && Value(card[len(card)-1]) >= Value(lastCards[len(lastCards)-1]) && (lastHandCardnum <= 2 || isEnd) {
|
||
//拆顺子
|
||
if Value(card[len(card)-1]) == Value(lastCards[len(lastCards)-1]) {
|
||
//比较花色
|
||
if Color(card[len(card)-1]) < Color(lastCards[len(lastCards)-1]) {
|
||
//截取
|
||
//return []int32{}
|
||
}
|
||
}
|
||
outCards = card[len(card)-len(lastCards):]
|
||
logger.Logger.Tracef("拆顺子 outCards = %d\n,lastCard = %d\n", outCards, lastCards)
|
||
}
|
||
}
|
||
//
|
||
if len(outCards) == 0 && lastHandCardnum <= 2 {
|
||
//找顺子
|
||
allStraight := GetAllStraight(cards, len(lastCards))
|
||
logger.Logger.Trace("allStraight = ", allStraight)
|
||
if len(allStraight) > 0 {
|
||
for _, straight := range allStraight {
|
||
if len(straight) >= len(lastCards) {
|
||
if Value(straight[len(straight)-1]) >= Value(lastCards[len(lastCards)-1]) {
|
||
if Value(straight[len(straight)-1]) == Value(lastCards[len(lastCards)-1]) {
|
||
if Color(straight[len(straight)-1]) > Color(lastCards[len(lastCards)-1]) {
|
||
outCards = straight[len(straight)-len(lastCards):]
|
||
break
|
||
}
|
||
} else {
|
||
outCards = straight[len(straight)-len(lastCards):]
|
||
break
|
||
}
|
||
logger.Logger.Tracef("找所有顺子来压牌 outCards = ", outCards)
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
if isYuLe {
|
||
//找炸弹
|
||
if len(outCards) == 0 && len(cardsTypeMap[Four_Bomb]) > 0 && lastHandCardnum <= 2 {
|
||
minKey := findMinKey(cardsTypeMap[Four_Bomb])
|
||
outCards = cardsTypeMap[Four_Bomb][minKey]
|
||
}
|
||
}
|
||
//打到底 出牌人打完了
|
||
if !IsPressed(isYuLe, isEnd, otherCards, lastCards, data, pos, lastPos, nextPos, handCardnum, Straight) {
|
||
outCards = []int32{}
|
||
}
|
||
logger.Logger.Trace("--------------顺子压牌完毕,出的牌:", outCards)
|
||
return outCards
|
||
case ColorStraight:
|
||
//同花顺
|
||
if len(cardsTypeMap[Straight]) > 0 {
|
||
straightMap := cardsTypeMap[Straight]
|
||
for _, straight := range straightMap {
|
||
if len(straight) >= len(lastCards) {
|
||
//判断是不是同花顺
|
||
if IsColorStraight(straight) {
|
||
if Value(straight[len(straight)-1]) >= Value(lastCards[len(lastCards)-1]) {
|
||
if Value(straight[len(straight)-1]) == Value(lastCards[len(lastCards)-1]) {
|
||
if Color(straight[len(straight)-1]) > Color(lastCards[len(lastCards)-1]) {
|
||
return straight[len(straight)-len(lastCards):]
|
||
}
|
||
} else {
|
||
return straight[len(straight)-len(lastCards):]
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
//找炸弹
|
||
if isYuLe && ((len(cardsTypeMap[Four_Bomb]) > 0 && lastHandCardnum <= 2) || handCardnum <= 2) {
|
||
minKey := findMinKey(cardsTypeMap[Four_Bomb])
|
||
logger.Logger.Trace("--------------同花顺压牌完毕,出的牌:", outCards)
|
||
return cardsTypeMap[Four_Bomb][minKey]
|
||
}
|
||
//打到底 出牌人打完了
|
||
if !IsPressed(isYuLe, isEnd, otherCards, lastCards, data, pos, lastPos, nextPos, handCardnum, ColorStraight) {
|
||
outCards = []int32{}
|
||
}
|
||
case Straight_Twin:
|
||
//连对
|
||
//获取连对长度
|
||
lastCardNum := len(lastCards) / 2
|
||
lastMaxCard := Value(lastCards[len(lastCards)-1])
|
||
cardsMap := cardsTypeMap[Straight_Twin]
|
||
for _, card := range cardsMap {
|
||
if len(card) >= len(lastCards) {
|
||
if len(card) == len(lastCards) {
|
||
if Value(card[len(card)-1]) >= lastMaxCard {
|
||
if Value(card[len(card)-1]) == lastMaxCard {
|
||
//比较花色
|
||
if Color(card[len(card)-1]) > Color(lastCards[len(lastCards)-1]) {
|
||
//截取
|
||
outCards = card
|
||
break
|
||
}
|
||
} else {
|
||
outCards = card
|
||
break
|
||
}
|
||
}
|
||
} else {
|
||
outCards = card
|
||
break
|
||
}
|
||
}
|
||
|
||
}
|
||
if isYuLe {
|
||
//找炸弹
|
||
if len(outCards) == 0 && (len(cardsTypeMap[Four_Bomb]) > 0 && lastHandCardnum <= 2 && lastCardNum <= 3) || handCardnum <= 2 {
|
||
minKey := findMinKey(cardsTypeMap[Four_Bomb])
|
||
outCards = cardsTypeMap[Four_Bomb][minKey]
|
||
}
|
||
} else {
|
||
if lastCardNum == 3 {
|
||
//找炸弹
|
||
if len(outCards) == 0 && len(cardsTypeMap[Four_Bomb]) > 0 {
|
||
minKey := findMinKey(cardsTypeMap[Four_Bomb])
|
||
outCards = cardsTypeMap[Four_Bomb][minKey]
|
||
}
|
||
}
|
||
}
|
||
if !IsPressed(isYuLe, isEnd, otherCards, lastCards, data, pos, lastPos, nextPos, handCardnum, Straight_Twin) {
|
||
outCards = []int32{}
|
||
}
|
||
logger.Logger.Tracef("--------------连对压牌完毕,出的牌:", outCards)
|
||
return outCards
|
||
case Triple:
|
||
//三张
|
||
cardsMap := cardsTypeMap[Triple]
|
||
for _, card := range cardsMap {
|
||
if Value(card[len(card)-1]) > Value(lastCards[len(lastCards)-1]) {
|
||
if Value(card[0]) == 12 && lastHandCardnum > 2 {
|
||
continue
|
||
}
|
||
outCards = card
|
||
break
|
||
//return card
|
||
}
|
||
}
|
||
if isYuLe {
|
||
//找炸弹
|
||
if len(outCards) == 0 && ((len(cardsTypeMap[Four_Bomb]) > 0 && lastHandCardnum <= 2) || handCardnum <= 2) {
|
||
minKey := findMinKey(cardsTypeMap[Four_Bomb])
|
||
outCards = cardsTypeMap[Four_Bomb][minKey]
|
||
}
|
||
}
|
||
if !IsPressed(isYuLe, isEnd, otherCards, lastCards, data, pos, lastPos, nextPos, handCardnum, Triple) {
|
||
outCards = []int32{}
|
||
}
|
||
logger.Logger.Trace("--------------三张压牌完毕,出的牌:", outCards)
|
||
return outCards
|
||
case Four_Bomb:
|
||
//炸弹
|
||
cardsMap := cardsTypeMap[Four_Bomb]
|
||
for _, card := range cardsMap {
|
||
if Value(card[0]) > Value(lastCards[0]) {
|
||
logger.Logger.Trace("--------------炸弹压牌,找到的牌:", outCards)
|
||
if isYuLe && (lastHandCardnum <= 2 || handCardnum <= 2) {
|
||
return card
|
||
}
|
||
if !isYuLe {
|
||
return card
|
||
}
|
||
}
|
||
}
|
||
|
||
if !IsPressed(isYuLe, isEnd, otherCards, lastCards, data, pos, lastPos, nextPos, handCardnum, Four_Bomb) {
|
||
outCards = []int32{}
|
||
}
|
||
case Straight_Triple:
|
||
//三顺
|
||
cardsMap := cardsTypeMap[Straight_Triple]
|
||
if len(cardsMap) > 0 {
|
||
for _, card := range cardsMap {
|
||
if Value(card[0]) > Value(lastCards[0]) && len(card) == len(lastCards) {
|
||
outCards = card
|
||
break
|
||
}
|
||
}
|
||
}
|
||
if isYuLe {
|
||
//找炸弹
|
||
if (len(outCards) == 0 || len(outCards) != len(lastCards)) && len(cardsTypeMap[Four_Bomb]) > 0 {
|
||
minKey := findMinKey(cardsTypeMap[Four_Bomb])
|
||
outCards = cardsTypeMap[Four_Bomb][minKey]
|
||
}
|
||
}
|
||
|
||
if !IsPressed(isYuLe, isEnd, otherCards, lastCards, data, pos, lastPos, nextPos, handCardnum, Straight_Triple) {
|
||
outCards = []int32{}
|
||
}
|
||
logger.Logger.Trace("--------------三顺压牌完毕,出的牌:", outCards)
|
||
return outCards
|
||
case Plane_Single:
|
||
//三代单 --不用考虑 只有最后一首才会出三代单
|
||
singleHand, singleLen := FindPlaneSingleHead(lastCards)
|
||
logger.Logger.Trace("飞机找带双 singleHand = ", singleHand, "singleLen = ", singleLen)
|
||
if singleLen > 1 && len(cards) >= len(lastCards) {
|
||
//333 444 5 6 7 8
|
||
//找相同长度三顺
|
||
straightTripleMap := cardsTypeMap[Straight_Triple]
|
||
if len(straightTripleMap) > 0 {
|
||
for _, straightTriple := range straightTripleMap {
|
||
if len(straightTriple)/3 >= singleLen {
|
||
if Value(straightTriple[len(straightTriple)-1]) > int(singleHand) {
|
||
outCards = straightTriple[len(straightTriple)-singleLen*3:]
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
if len(outCards) != 0 {
|
||
copyCards := make([]int32, len(cards))
|
||
copy(copyCards, cards)
|
||
delCard := make(map[int32][]int32)
|
||
delCard[0] = outCards
|
||
copyCards = DelCards(copyCards, delCard)
|
||
copyCards = DelCards(copyCards, cardsTypeMap[Four_Bomb])
|
||
num := len(cards) - len(lastCards)
|
||
if num == 1 {
|
||
//留最大牌
|
||
outCards = []int32{}
|
||
maxCard := copyCards[len(copyCards)-1:]
|
||
for _, card := range cards {
|
||
if card == maxCard[0] {
|
||
continue
|
||
}
|
||
outCards = append(outCards, card)
|
||
}
|
||
} else if num == 2 {
|
||
//留对子
|
||
_, pairMap := GetPair(copyCards)
|
||
if len(pairMap) > 0 {
|
||
outCards = []int32{}
|
||
maxPair := -1
|
||
maxKey := int32(0)
|
||
for i, pair := range pairMap {
|
||
if Value(pair[0]) > maxPair {
|
||
maxPair = Value(pair[0])
|
||
maxKey = i
|
||
}
|
||
}
|
||
for _, card := range cards {
|
||
if card == pairMap[maxKey][0] || card == pairMap[maxKey][1] {
|
||
continue
|
||
}
|
||
outCards = append(outCards, card)
|
||
}
|
||
} else {
|
||
//留最后两张大牌
|
||
outCards = []int32{}
|
||
maxCard := copyCards[len(copyCards)-2:]
|
||
for _, card := range cards {
|
||
if card == maxCard[0] || card == maxCard[1] {
|
||
continue
|
||
}
|
||
outCards = append(outCards, card)
|
||
}
|
||
|
||
}
|
||
} else if num == 3 {
|
||
//留顺子
|
||
straights := cardsTypeMap[Straight]
|
||
if len(straights) > 0 {
|
||
outCards = []int32{}
|
||
straight := straights[int32(len(straights)-1)]
|
||
saveCards := straight[len(straight)-3:]
|
||
for _, card := range cards {
|
||
if card == saveCards[0] || card == saveCards[1] || card == saveCards[2] {
|
||
continue
|
||
}
|
||
outCards = append(outCards, card)
|
||
}
|
||
|
||
} else {
|
||
//留最后三张大牌
|
||
outCards = []int32{}
|
||
maxCard := copyCards[len(copyCards)-3:]
|
||
for _, card := range cards {
|
||
if card == maxCard[0] || card == maxCard[1] || card == maxCard[2] {
|
||
continue
|
||
}
|
||
outCards = append(outCards, card)
|
||
}
|
||
}
|
||
} else {
|
||
for _, value := range cards {
|
||
status := true
|
||
for _, straight := range outCards {
|
||
if value == straight || Value(value) == Value(straight) {
|
||
status = false
|
||
break
|
||
}
|
||
}
|
||
if status {
|
||
outCards = append(outCards, value)
|
||
}
|
||
if len(outCards) == len(lastCards) {
|
||
break
|
||
}
|
||
}
|
||
}
|
||
}
|
||
if isYuLe {
|
||
//找炸弹
|
||
if (len(outCards) == 0 || len(outCards) != len(lastCards)) && len(cardsTypeMap[Four_Bomb]) > 0 {
|
||
minKey := findMinKey(cardsTypeMap[Four_Bomb])
|
||
return cardsTypeMap[Four_Bomb][minKey]
|
||
}
|
||
}
|
||
|
||
if !IsPressed(isYuLe, isEnd, otherCards, lastCards, data, pos, lastPos, nextPos, handCardnum, Plane_Single) {
|
||
outCards = []int32{}
|
||
}
|
||
logger.Logger.Trace("--------------飞机带单压牌完毕,出的牌:", outCards)
|
||
return outCards
|
||
case Plane_Twin:
|
||
outCards = []int32{}
|
||
twinHand, twinLen := FindPlaneTwinHead(lastCards)
|
||
logger.Logger.Trace("飞机找带双 twinHand = ", twinHand, "twinLen = ", twinLen)
|
||
if twinLen == 1 {
|
||
//三代双
|
||
cardsMap := cardsTypeMap[Triple]
|
||
key := int32(999)
|
||
for i, data1 := range cardsMap {
|
||
if Value(data1[len(data1)-1]) > int(twinHand) {
|
||
if i < key {
|
||
//card = data1
|
||
key = i
|
||
}
|
||
break
|
||
}
|
||
}
|
||
if key != 999 {
|
||
outCards = cardsTypeMap[Triple][key]
|
||
}
|
||
if len(outCards) > 0 {
|
||
minSingleKey := findMinKey(cardsTypeMap[Single])
|
||
minTwinKey := findMinKey(cardsTypeMap[Twin])
|
||
if len(cardsTypeMap[Single]) >= 2 && Value(cardsTypeMap[Single][minSingleKey][0]) < 12 {
|
||
//三代2单
|
||
if len(cardsTypeMap[Single]) >= 2 {
|
||
minValue := FindSmallestTwoValues(cardsTypeMap[Single])
|
||
//logger.Logger.Trace("找出最小两张单排的值:", minValue)
|
||
outCards = append(outCards, minValue[0], minValue[1])
|
||
}
|
||
} else if len(cardsTypeMap[Twin]) >= 1 && Value(cardsTypeMap[Twin][minTwinKey][0]) < 11 {
|
||
//三代一对
|
||
outCards = append(outCards, cardsTypeMap[Twin][minTwinKey][0], cardsTypeMap[Twin][minTwinKey][1])
|
||
//logger.Logger.Trace("压牌,三代一对: ", card)
|
||
} else {
|
||
//直接找最小的两张牌
|
||
if len(cards) >= 5 {
|
||
for _, value := range cards {
|
||
if Value(value) != Value(outCards[0]) {
|
||
outCards = append(outCards, value)
|
||
if len(outCards) == 5 {
|
||
return outCards
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
} else {
|
||
//333 444 555
|
||
//找相同长度三顺
|
||
if len(cards) >= len(lastCards) {
|
||
straightTripleMap := cardsTypeMap[Straight_Triple]
|
||
if len(straightTripleMap) > 0 {
|
||
for _, straightTriple := range straightTripleMap {
|
||
if len(straightTriple)/3 >= twinLen {
|
||
if Value(straightTriple[len(straightTriple)-1]) > int(twinHand) {
|
||
outCards = straightTriple[len(straightTriple)-twinLen*3:]
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
if len(outCards) != 0 {
|
||
copyCards := make([]int32, len(cards))
|
||
copy(copyCards, cards)
|
||
delCard := make(map[int32][]int32)
|
||
delCard[0] = outCards
|
||
copyCards = DelCards(copyCards, delCard)
|
||
copyCards = DelCards(copyCards, cardsTypeMap[Four_Bomb])
|
||
num := len(cards) - len(lastCards)
|
||
if num == 1 {
|
||
//留最大牌
|
||
outCards = []int32{}
|
||
maxCard := copyCards[len(copyCards)-1:]
|
||
for _, card := range cards {
|
||
if card == maxCard[0] {
|
||
continue
|
||
}
|
||
outCards = append(outCards, card)
|
||
}
|
||
} else if num == 2 {
|
||
//留对子
|
||
_, pairMap := GetPair(copyCards)
|
||
if len(pairMap) > 0 {
|
||
maxPair := -1
|
||
maxKey := int32(0)
|
||
for i, pair := range pairMap {
|
||
if Value(pair[0]) > maxPair {
|
||
maxPair = Value(pair[0])
|
||
maxKey = i
|
||
}
|
||
}
|
||
outCards = []int32{}
|
||
for _, card := range cards {
|
||
if card == pairMap[maxKey][0] || card == pairMap[maxKey][1] {
|
||
continue
|
||
}
|
||
outCards = append(outCards, card)
|
||
}
|
||
} else {
|
||
//留最后两张大牌
|
||
maxCard := copyCards[len(copyCards)-2:]
|
||
for _, card := range cards {
|
||
if card == maxCard[0] || card == maxCard[1] {
|
||
continue
|
||
}
|
||
outCards = append(outCards, card)
|
||
}
|
||
|
||
}
|
||
} else if num == 3 {
|
||
//留顺子
|
||
straights := cardsTypeMap[Straight]
|
||
if len(straights) > 0 {
|
||
outCards = []int32{}
|
||
straight := straights[int32(len(straights)-1)]
|
||
saveCards := straight[len(straight)-3:]
|
||
for _, card := range cards {
|
||
if card == saveCards[0] || card == saveCards[1] || card == saveCards[2] {
|
||
continue
|
||
}
|
||
outCards = append(outCards, card)
|
||
}
|
||
|
||
} else {
|
||
//留最后三张大牌
|
||
maxCard := copyCards[len(copyCards)-3:]
|
||
outCards = []int32{}
|
||
for _, card := range cards {
|
||
if card == maxCard[0] || card == maxCard[1] || card == maxCard[2] {
|
||
continue
|
||
}
|
||
outCards = append(outCards, card)
|
||
}
|
||
}
|
||
} else {
|
||
for _, value := range cards {
|
||
status := true
|
||
for _, straight := range outCards {
|
||
if value == straight || Value(value) == Value(straight) {
|
||
status = false
|
||
break
|
||
}
|
||
}
|
||
if status {
|
||
outCards = append(outCards, value)
|
||
}
|
||
if len(outCards) == len(lastCards) {
|
||
break
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
if isYuLe {
|
||
//找炸弹
|
||
if len(outCards) == 0 && len(cardsTypeMap[Four_Bomb]) > 0 && (lastHandCardnum <= 2 || handCardnum <= 2) {
|
||
minKey := findMinKey(cardsTypeMap[Four_Bomb])
|
||
return cardsTypeMap[Four_Bomb][minKey]
|
||
}
|
||
}
|
||
|
||
if !IsPressed(isYuLe, isEnd, otherCards, lastCards, data, pos, lastPos, nextPos, handCardnum, Plane_Twin) {
|
||
outCards = []int32{}
|
||
}
|
||
|
||
logger.Logger.Trace("--------------三代双压牌完毕,出的牌:", outCards)
|
||
return outCards
|
||
default:
|
||
logger.Logger.Trace("--------------default压牌完毕,出的牌:", outCards)
|
||
return outCards
|
||
}
|
||
}
|
||
|
||
logger.Logger.Trace("--------------压牌完毕,出的牌:", outCards)
|
||
return outCards
|
||
}
|
||
|
||
// 出牌 isMin是否先手出最小的牌
|
||
func GetOutCards(cards []int32, data *tienlenApi.PredictRequest, pos int32) []int32 {
|
||
logger.Logger.Trace("---------------出牌开始-------------------")
|
||
sort.Slice(cards, func(i, j int) bool {
|
||
if Value(cards[i]) == Value(cards[j]) {
|
||
return cards[i] < cards[j]
|
||
}
|
||
return Value(cards[i]) < Value(cards[j])
|
||
})
|
||
isWin := data.IsWin
|
||
//测试代码
|
||
isWin = true
|
||
logger.Logger.Trace("出牌 调控输赢 isWin = ", isWin)
|
||
//测试代码
|
||
//cards = []int32{51, 4, 5}
|
||
//pos = 0
|
||
//data.Cards_left_2 = []int32{0, 1, 2, 3}
|
||
//data.Cards_left_3 = nil
|
||
//data.Cards_left_1 = nil
|
||
//data.Last_pos = 2
|
||
|
||
isYuLe := data.IsTienLenYule
|
||
isMin := data.IsFirstHand
|
||
isEnd := data.IsEnd
|
||
winSnids := data.WinSnids
|
||
//获取牌型
|
||
cardsTypeMap := GetCardsType(cards, isYuLe) //map[int]map[int32][]int32
|
||
cardsTypeMap = reloadcardsType(cardsTypeMap, pos, data, isYuLe)
|
||
logger.Logger.Trace("出牌 获取我的牌型:", cardsTypeMap, "\n")
|
||
score, handNum := GetCardTypeScore(cardsTypeMap, isYuLe, cards)
|
||
logger.Logger.Tracef("出牌 获取当前手牌的牌型分数:%v, 手牌数量:%v\n,我的位置:%d \n", score, handNum, pos)
|
||
if handNum <= 1 {
|
||
logger.Logger.Trace("只剩最后一手牌 直接全出了", cards)
|
||
return cards
|
||
}
|
||
//出牌逻辑
|
||
outCards := []int32{}
|
||
cardValue := -1
|
||
if isMin {
|
||
outCards = GetMinCardType(cards[0], cardsTypeMap, isYuLe)
|
||
logger.Logger.Trace("先出第一手,当前出牌只能出最小的牌!", outCards)
|
||
return outCards
|
||
}
|
||
//判断其他玩家剩余的牌的牌型是否能压过当前出牌的牌型
|
||
//出牌顺序
|
||
//出单张 判断下一家剩余1张牌且剩余的牌比我出的牌大 不出
|
||
otherMinHandNum, otherMinCardsNum, otherPos, otherCardsType := getOtherMinCards(pos, data, isYuLe)
|
||
|
||
logger.Logger.Tracef("玩家出牌,获取其他玩家最小剩余手数 和剩余牌数及位置剩余的牌型 otherMinHandNum=%d otherMinCardsNum=%d otherPos=%d cardsType=%d", otherMinHandNum, otherMinCardsNum, otherPos, otherCardsType)
|
||
//优先出三张 如果是娱乐模式 直接带单张 或者最小的对子
|
||
if isYuLe {
|
||
outCards, cardValue = getTriple(cardsTypeMap, cards, isYuLe, otherMinHandNum, pos, int32(otherPos), data)
|
||
logger.Logger.Tracef("出三张 cardValue = %d ,outCards = %d", cardValue, outCards)
|
||
}
|
||
//出单张
|
||
if len(outCards) == 0 && handNum > 2 {
|
||
straightNum := len(cardsTypeMap[Straight])
|
||
//测试一下
|
||
//if isYuLe {
|
||
if len(cardsTypeMap[Straight]) > 0 {
|
||
straightNum = len(cardsTypeMap[Straight])*2 + 1
|
||
}
|
||
//}
|
||
if len(cardsTypeMap[Single]) > straightNum && len(cardsTypeMap[Single]) > (len(cardsTypeMap[Twin])+len(cardsTypeMap[Straight_Twin])) {
|
||
outCards = getSingle(cardsTypeMap, cards, isYuLe)
|
||
if len(outCards) > 0 && isWin {
|
||
if otherMinHandNum == 1 && otherMinCardsNum <= 1 && otherCardsType == Single {
|
||
otherCards := getOtherPlayerCards(pos, int32(otherPos), data)
|
||
if Value(cards[0]) < Value(otherCards[0]) {
|
||
logger.Logger.Trace("出单张,其他玩家只剩一首牌 且剩余的牌比我出的牌大 不出!outCards = ", outCards)
|
||
outCards = []int32{}
|
||
} else if Value(cards[0]) == Value(otherCards[0]) {
|
||
//判断花色
|
||
if Color(cards[0]) < Color(otherCards[0]) {
|
||
logger.Logger.Trace("出单张,牌值相同,花色小,不出!outCards = ", outCards)
|
||
outCards = []int32{}
|
||
}
|
||
}
|
||
|
||
otherCardsMap := getOtherCards(pos, data)
|
||
|
||
for _, single := range cardsTypeMap[Single] {
|
||
status := true
|
||
for _, other := range otherCardsMap {
|
||
if len(other) == 1 {
|
||
if Value(single[0]) <= Value(other[0]) {
|
||
if Value(single[0]) == Value(other[0]) && Color(single[0]) > Color(other[0]) {
|
||
continue
|
||
}
|
||
status = false
|
||
}
|
||
}
|
||
}
|
||
if status {
|
||
outCards = single
|
||
break
|
||
}
|
||
}
|
||
}
|
||
//如果是全场最大的单张 不出
|
||
if len(outCards) > 0 && (otherMinCardsNum != 1) {
|
||
if Value(outCards[0]) == 12 && handNum > 2 {
|
||
outCards = []int32{}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
//出对子 判断下一家剩余2张牌且剩余的牌比我出的牌大 不出
|
||
if len(outCards) == 0 {
|
||
straightNum := len(cardsTypeMap[Straight])
|
||
if isYuLe {
|
||
//straightNum = len(cardsTypeMap[Straight])
|
||
if len(cardsTypeMap[Straight]) > 0 {
|
||
straightNum = len(cardsTypeMap[Straight])*2 + 1
|
||
}
|
||
}
|
||
if len(cardsTypeMap[Twin]) > straightNum {
|
||
outCards = getTwin(cardsTypeMap, cards, isYuLe)
|
||
if len(outCards) > 0 && isWin {
|
||
logger.Logger.Tracef("------首牌出对子 outcards = %d\n,所有的对子:%d\n", outCards, cardsTypeMap[Twin])
|
||
otherCards := getOtherPlayerCards(pos, int32(otherPos), data)
|
||
if otherMinHandNum == 1 && otherMinCardsNum == 2 && otherCardsType == Twin {
|
||
|
||
if Value(outCards[1]) < Value(otherCards[1]) {
|
||
logger.Logger.Trace("出对子,其他玩家只剩一首牌 且剩余的牌比我出的牌大 不出!outCards = ", outCards)
|
||
outCards = []int32{}
|
||
} else if Value(outCards[1]) == Value(otherCards[1]) {
|
||
//判断花色
|
||
if Color(outCards[1]) < Color(otherCards[1]) {
|
||
logger.Logger.Trace("出对子,牌值相同,花色小,不出!outCards = ", outCards)
|
||
outCards = []int32{}
|
||
}
|
||
}
|
||
}
|
||
|
||
otherCardsMap := getOtherCards(pos, data)
|
||
|
||
for _, twin := range cardsTypeMap[Twin] {
|
||
if Value(twin[0]) == 12 && handNum > 2 {
|
||
continue
|
||
}
|
||
for _, other := range otherCardsMap {
|
||
_, otherRuleType := RulePopEnable(other)
|
||
if len(other) == 2 && otherRuleType == Twin {
|
||
if Value(twin[1]) >= Value(other[1]) {
|
||
if Value(twin[1]) == Value(other[1]) {
|
||
if Color(twin[0]) > Color(other[0]) {
|
||
outCards = twin
|
||
break
|
||
} else {
|
||
continue
|
||
}
|
||
}
|
||
outCards = twin
|
||
break
|
||
|
||
}
|
||
}
|
||
}
|
||
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
//出三张
|
||
if isYuLe {
|
||
if len(outCards) == 0 {
|
||
outCards, cardValue = getTriple(cardsTypeMap, cards, isYuLe, otherMinHandNum, pos, int32(otherPos), data)
|
||
if len(outCards) > 0 {
|
||
if otherMinHandNum == 1 && otherMinCardsNum >= 3 && otherCardsType == Triple {
|
||
otherCards := getOtherPlayerCards(pos, int32(otherPos), data)
|
||
//获取牌型
|
||
otherCardsTypeMap := GetCardsType(otherCards, isYuLe)
|
||
otherTriple := otherCardsTypeMap[Triple]
|
||
//找最小key
|
||
if len(otherTriple) > 0 {
|
||
otherMinKey := findMinKey(otherTriple)
|
||
if cardValue < Value(otherTriple[otherMinKey][0]) {
|
||
logger.Logger.Trace("出三张,其他玩家只剩一首牌 且剩余的牌比我出的牌大 不出!outCards = ", outCards)
|
||
outCards = []int32{}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
//顺子
|
||
if len(outCards) == 0 {
|
||
outCards = getStraight(cardsTypeMap, cards, isYuLe)
|
||
if len(outCards) > 0 && isWin {
|
||
if otherMinHandNum == 1 && otherMinCardsNum == len(outCards) && otherCardsType == Straight {
|
||
otherCards := getOtherPlayerCards(pos, int32(otherPos), data)
|
||
|
||
if Value(outCards[len(outCards)-1]) < Value(otherCards[len(otherCards)-1]) {
|
||
logger.Logger.Trace("出顺子,其他玩家只剩一首牌 且剩余的牌比我出的牌大 不出!outCards = ", outCards)
|
||
outCards = []int32{}
|
||
} else if Value(outCards[len(outCards)-1]) == Value(otherCards[len(otherCards)-1]) {
|
||
//判断花色
|
||
if Color(outCards[len(outCards)-1]) < Color(otherCards[len(otherCards)-1]) {
|
||
logger.Logger.Trace("出顺子,牌值相同,花色小,不出!outCards = ", outCards)
|
||
outCards = []int32{}
|
||
}
|
||
}
|
||
}
|
||
//如果其他玩家剩余牌全是顺子 并且比我的大 我不出顺子了 (后续没牌型可出了!!!!
|
||
}
|
||
}
|
||
if !isYuLe {
|
||
if len(outCards) == 0 {
|
||
outCards, cardValue = getTriple(cardsTypeMap, cards, isYuLe, otherMinHandNum, pos, int32(otherPos), data)
|
||
if len(outCards) > 0 && isWin {
|
||
if otherMinHandNum == 1 && otherMinCardsNum >= 3 && otherCardsType == Triple {
|
||
otherCards := getOtherPlayerCards(pos, int32(otherPos), data)
|
||
//获取牌型
|
||
otherCardsTypeMap := GetCardsType(otherCards, isYuLe)
|
||
otherTriple := otherCardsTypeMap[Triple]
|
||
//找最小key
|
||
if len(otherTriple) > 0 {
|
||
otherMinKey := findMinKey(otherTriple)
|
||
if cardValue < Value(otherTriple[otherMinKey][0]) {
|
||
logger.Logger.Trace("出三张,其他玩家只剩一首牌 且剩余的牌比我出的牌大 不出!outCards = ", outCards)
|
||
outCards = []int32{}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
//连对
|
||
if len(outCards) == 0 {
|
||
outCards = getStraightTwin(cardsTypeMap, cards, isYuLe)
|
||
if len(outCards) > 0 && isWin {
|
||
if otherMinHandNum == 1 && otherMinCardsNum == len(outCards) && otherCardsType == Straight_Twin {
|
||
otherCards := getOtherPlayerCards(pos, int32(otherPos), data)
|
||
if Value(outCards[len(outCards)-1]) < Value(otherCards[len(otherCards)-1]) {
|
||
logger.Logger.Trace("出连对,其他玩家只剩一首牌 且剩余的牌比我出的牌大 不出!outCards = ", outCards)
|
||
outCards = []int32{}
|
||
} else if Value(outCards[len(outCards)-1]) == Value(otherCards[len(otherCards)-1]) {
|
||
//判断花色
|
||
if Color(outCards[len(outCards)-1]) < Color(otherCards[len(otherCards)-1]) {
|
||
logger.Logger.Trace("出连队,牌值相同,花色小,不出!outCards = ", outCards)
|
||
outCards = []int32{}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
if len(outCards)/2 >= 3 && handNum > 2 {
|
||
outCards = []int32{}
|
||
}
|
||
}
|
||
//炸弹 这个就不用检查了
|
||
if len(outCards) == 0 && handNum <= 2 {
|
||
if isYuLe {
|
||
if len(cardsTypeMap[Triple]) < 2 && len(cards) < 13 {
|
||
outCards = getBomb(cardsTypeMap, cards, isYuLe)
|
||
}
|
||
} else {
|
||
//出炸弹
|
||
outCards = getBomb(cardsTypeMap, cards, isYuLe)
|
||
}
|
||
}
|
||
//额外判断
|
||
//获取下一家的位置和剩余的牌
|
||
if isWin {
|
||
if handNum <= 2 {
|
||
//判断我的剩余牌型中有没有全场最大的牌型
|
||
for cardType, myCards := range cardsTypeMap { //map[int]map[int32][]int32
|
||
for _, mycard := range myCards {
|
||
if getMaxCardTypeNum(cardType, mycard, pos, data) {
|
||
logger.Logger.Trace("最后两手牌,找到最大牌型,mycard:", mycard)
|
||
if cardType == Triple {
|
||
//出三代二
|
||
outCards, cardValue = getTriple(cardsTypeMap, cards, isYuLe, otherMinHandNum, pos, int32(otherPos), data)
|
||
if len(outCards) > 0 {
|
||
return outCards
|
||
} else {
|
||
continue
|
||
}
|
||
}
|
||
return mycard
|
||
}
|
||
}
|
||
}
|
||
}
|
||
if (handNum <= 3 && isYuLe && len(cardsTypeMap[Triple]) == 0) || (handNum <= 3 && !isYuLe) {
|
||
myMaxCardStatus, maxCardNum, maxCardsArr := getMaxCards(cards, data, pos)
|
||
if len(outCards) == 1 {
|
||
//判断当前最大牌在不在我手
|
||
if !myMaxCardStatus {
|
||
//找最长的牌
|
||
for cardType, myCards := range cardsTypeMap { //map[int]map[int32][]int32
|
||
for _, mycard := range myCards {
|
||
if (cardType == Straight_Twin && len(mycard)/2 >= 3) || cardType == Four_Bomb {
|
||
//手里有连炸
|
||
continue
|
||
}
|
||
if len(mycard) > len(outCards) {
|
||
if cardType == Triple {
|
||
//出三代二
|
||
outCards, cardValue = getTriple(cardsTypeMap, cards, isYuLe, otherMinHandNum, pos, int32(otherPos), data)
|
||
if len(outCards) > 0 {
|
||
return outCards
|
||
} else {
|
||
break
|
||
}
|
||
}
|
||
if cardType != Single && cardType != Twin {
|
||
outCards = mycard
|
||
} else {
|
||
if Value(mycard[0]) != Value(cards[len(cards)-1]) {
|
||
outCards = mycard
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
//获取我最大牌的
|
||
if myMaxCardStatus {
|
||
if otherMinCardsNum > 1 {
|
||
//这个时候我应该出单牌
|
||
//找单张 - 对子- 和最大牌数量相等的顺子长度+1的顺子
|
||
status := false
|
||
if len(cardsTypeMap[Single]) > 0 {
|
||
card := getSingle(cardsTypeMap, cards, isYuLe)
|
||
if card[0] != maxCardsArr[len(maxCardsArr)-1] {
|
||
status = true
|
||
}
|
||
}
|
||
if len(cardsTypeMap[Single]) > 0 && status {
|
||
card := getSingle(cardsTypeMap, cards, isYuLe)
|
||
if len(card) > 0 {
|
||
outCards = card
|
||
}
|
||
} else if len(cardsTypeMap[Twin]) > 0 {
|
||
minKey := findMinKey(cardsTypeMap[Twin])
|
||
//map[int]map[int32][]int32
|
||
if cardsTypeMap[Twin][minKey] != nil {
|
||
outCards = []int32{cardsTypeMap[Twin][minKey][0]}
|
||
}
|
||
logger.Logger.Trace("对子拆单张出!")
|
||
} else {
|
||
if maxCardNum > 1 {
|
||
//先找顺子的交集
|
||
result := FindIntersection(cardsTypeMap[Straight])
|
||
if len(result) > 0 {
|
||
sort.Slice(cards, func(i, j int) bool {
|
||
if Value(cards[i]) == Value(cards[j]) {
|
||
return cards[i] < cards[j]
|
||
}
|
||
return Value(cards[i]) < Value(cards[j])
|
||
})
|
||
if len(result) > 0 {
|
||
for _, arr := range result {
|
||
outCards = arr
|
||
break
|
||
}
|
||
}
|
||
} else if len(cardsTypeMap[Straight]) > 0 {
|
||
minLength := 13
|
||
minKey := int32(0)
|
||
for i, straight := range cardsTypeMap[Straight] {
|
||
if len(straight) < minLength {
|
||
minKey = i
|
||
}
|
||
}
|
||
if len(cardsTypeMap[Straight][minKey]) <= maxCardNum+1 {
|
||
outCards = []int32{cardsTypeMap[Straight][minKey][0]}
|
||
logger.Logger.Trace("拆顺子,出单张!outCards = ", outCards)
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
//最后直接出最小牌型的牌
|
||
if len(outCards) == 0 {
|
||
//直接出最大的单牌
|
||
if otherMinHandNum == 1 {
|
||
//先找其他牌型
|
||
for cardType, card := range cardsTypeMap {
|
||
if len(card) > 0 {
|
||
if cardType != Single {
|
||
minKey := findMinKey(card)
|
||
outCards = card[minKey]
|
||
logger.Logger.Trace("最后直接先出其他牌型的牌 outCards = ", outCards)
|
||
break
|
||
} else if cardType == Triple && isYuLe {
|
||
//找两张单张
|
||
minSingleKey := findMinKey(cardsTypeMap[Single])
|
||
minTwinKey := findMinKey(cardsTypeMap[Twin])
|
||
if len(cardsTypeMap[Single]) >= 2 && Value(cardsTypeMap[Single][minSingleKey][0]) < 12 {
|
||
//三代2单
|
||
if len(cardsTypeMap[Single]) >= 2 {
|
||
minValue := FindSmallestTwoValues(cardsTypeMap[Single])
|
||
outCards = append(outCards, minValue[0], minValue[1])
|
||
}
|
||
} else if len(cardsTypeMap[Twin]) >= 1 && Value(cardsTypeMap[Twin][minTwinKey][0]) < 11 {
|
||
//三代一对
|
||
outCards = append(outCards, cardsTypeMap[Twin][minTwinKey][0], cardsTypeMap[Twin][minTwinKey][1])
|
||
}
|
||
}
|
||
}
|
||
}
|
||
if len(outCards) == 0 {
|
||
nextPos, nextCards := GetNextPos(pos, data)
|
||
otherCards := getOtherPlayerCards(pos, int32(otherPos), data)
|
||
if nextPos != int32(otherPos) && Value(nextCards[len(nextCards)-1]) > Value(otherCards[0]) {
|
||
//找最小牌型的牌
|
||
outCards = GetMinCardType(cards[0], cardsTypeMap, isYuLe)
|
||
logger.Logger.Trace("最后直接找最小牌型的牌,让下一家顶上 outCards = ", outCards)
|
||
} else {
|
||
lastPos, _ := GetLastPos(pos, data)
|
||
if isEnd && len(winSnids) == 0 && nextPos != lastPos {
|
||
//找最小牌型的牌
|
||
outCards = GetMinCardType(cards[0], cardsTypeMap, isYuLe)
|
||
logger.Logger.Trace("打到底模式 最后直接找最小牌型的牌, outCards = ", outCards)
|
||
} else {
|
||
if otherMinHandNum > 2 {
|
||
//找最小牌型的牌
|
||
outCards = GetMinCardType(cards[0], cardsTypeMap, isYuLe)
|
||
logger.Logger.Trace("打到底模式 最后直接找最小牌型的牌, outCards = ", outCards)
|
||
} else {
|
||
outCards = []int32{cards[len(cards)-1]}
|
||
logger.Logger.Trace("最后直接出最大的牌 outCards = ", outCards)
|
||
}
|
||
}
|
||
|
||
}
|
||
}
|
||
} else {
|
||
//找最小牌型的牌
|
||
outCards = GetMinCardType(cards[0], cardsTypeMap, isYuLe)
|
||
logger.Logger.Trace("最后直接找最小牌型的牌 outCards = ", outCards)
|
||
}
|
||
}
|
||
logger.Logger.Trace("---------------------------出牌结束 出的牌:", outCards)
|
||
return outCards
|
||
}
|
||
|
||
// 判断牌型是否全场最大
|
||
func getMaxCardTypeNum(cardsType int, cards []int32, pos int32, data *tienlenApi.PredictRequest) bool {
|
||
//map[int][]int32
|
||
status := true
|
||
otherCardsMap := getOtherCards(pos, data)
|
||
for _, otherCards := range otherCardsMap {
|
||
if len(otherCards) == 0 {
|
||
continue
|
||
}
|
||
sort.Slice(otherCards, func(i, j int) bool {
|
||
if Value(otherCards[i]) == Value(otherCards[j]) {
|
||
return otherCards[i] < otherCards[j]
|
||
}
|
||
return Value(otherCards[i]) < Value(otherCards[j])
|
||
})
|
||
if cardsType == Single {
|
||
if len(otherCards) > 0 && len(cards) > 0 {
|
||
if Value(otherCards[len(otherCards)-1]) >= Value(cards[0]) {
|
||
if Value(otherCards[len(otherCards)-1]) == Value(cards[0]) {
|
||
if Color(otherCards[len(otherCards)-1]) > Color(cards[0]) {
|
||
return false
|
||
}
|
||
} else {
|
||
return false
|
||
}
|
||
}
|
||
}
|
||
} else if cardsType == Twin {
|
||
_, pairMap := GetPair(otherCards)
|
||
if len(pairMap) > 0 {
|
||
for _, pair := range pairMap {
|
||
if Value(pair[len(pair)-1]) >= Value(cards[0]) {
|
||
if Value(pair[len(pair)-1]) == Value(cards[0]) {
|
||
if Color(pair[len(pair)-1]) > Color(cards[0]) {
|
||
return false
|
||
}
|
||
} else {
|
||
return false
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
otherCardsTypeMap := GetCardsType(otherCards, data.IsTienLenYule) //map[int]map[int32][]int32
|
||
if otherCardsTypeMap[cardsType] != nil && len(otherCardsTypeMap[cardsType]) > 0 {
|
||
for _, cardsArr := range otherCardsTypeMap[cardsType] {
|
||
if len(cardsArr) < len(cards) {
|
||
continue
|
||
}
|
||
if Value(cardsArr[len(cardsArr)-1]) > Value(cards[len(cards)-1]) {
|
||
status = false
|
||
break
|
||
} else if Value(cardsArr[len(cardsArr)-1]) == Value(cards[len(cards)-1]) {
|
||
if Color(cardsArr[len(cardsArr)-1]) > Color(cards[len(cards)-1]) {
|
||
status = false
|
||
break
|
||
}
|
||
}
|
||
}
|
||
if !status {
|
||
break
|
||
}
|
||
}
|
||
}
|
||
return status
|
||
}
|
||
|
||
// 出单张
|
||
func getSingle(cardsTypeMap map[int]map[int32][]int32, cards []int32, isYuLe bool) []int32 {
|
||
outCards := []int32{}
|
||
if isYuLe {
|
||
if len(cardsTypeMap[Triple]) == 0 {
|
||
minKey := findMinKey(cardsTypeMap[Single])
|
||
outCards = cardsTypeMap[Single][minKey]
|
||
|
||
}
|
||
} else {
|
||
minKey := findMinKey(cardsTypeMap[Single])
|
||
outCards = cardsTypeMap[Single][minKey]
|
||
}
|
||
return outCards
|
||
}
|
||
|
||
// 出对子
|
||
func getTwin(cardsTypeMap map[int]map[int32][]int32, cards []int32, isYuLe bool) []int32 {
|
||
outCards := []int32{}
|
||
_, handNum := GetCardTypeScore(cardsTypeMap, isYuLe, cards)
|
||
if len(cardsTypeMap[Twin]) > len(cardsTypeMap[Straight]) {
|
||
minKey := findMinKey(cardsTypeMap[Twin])
|
||
if isYuLe {
|
||
if len(cardsTypeMap[Triple]) == 0 {
|
||
if Value(cardsTypeMap[Twin][minKey][0]) < 11 || (handNum <= 2 && len(cardsTypeMap[Triple]) == 0) {
|
||
outCards = cardsTypeMap[Twin][minKey]
|
||
}
|
||
}
|
||
} else {
|
||
if Value(cardsTypeMap[Twin][minKey][0]) < 11 || (handNum <= 2 && len(cardsTypeMap[Triple]) == 0) {
|
||
outCards = cardsTypeMap[Twin][minKey]
|
||
}
|
||
|
||
}
|
||
|
||
}
|
||
return outCards
|
||
}
|
||
|
||
// 出三张 cardValue三张的值 value(card)
|
||
func getTriple(cardsTypeMap map[int]map[int32][]int32, cards []int32, isYuLe bool, otherMinHandNum int, mypos, otherPos int32, data *tienlenApi.PredictRequest) ([]int32, int) {
|
||
outCards := []int32{}
|
||
cardValue := 0
|
||
_, handNum := GetCardTypeScore(cardsTypeMap, isYuLe, cards)
|
||
if isYuLe && len(cardsTypeMap[Straight_Triple]) > 0 {
|
||
//AI机器人三顺的长度只能是2 大于2的直接拆成连对炸弹了
|
||
outCards = []int32{}
|
||
if len(cards) <= 10 && len(cardsTypeMap[Four_Bomb]) == 0 {
|
||
return cards, cardValue
|
||
} else {
|
||
copyCards := make([]int32, len(cards))
|
||
copy(copyCards, cards)
|
||
copyCards = DelCards(copyCards, cardsTypeMap[Straight_Triple])
|
||
copyCards = DelCards(copyCards, cardsTypeMap[Four_Bomb])
|
||
sort.Slice(copyCards, func(i, j int) bool {
|
||
if Value(copyCards[i]) == Value(copyCards[j]) {
|
||
return copyCards[i] < copyCards[j]
|
||
}
|
||
return Value(copyCards[i]) < Value(copyCards[j])
|
||
})
|
||
num := len(cards) - 10
|
||
if num == 1 {
|
||
//留最大牌
|
||
maxCard := copyCards[len(copyCards)-1:]
|
||
for _, card := range cards {
|
||
if card == maxCard[0] {
|
||
continue
|
||
}
|
||
outCards = append(outCards, card)
|
||
}
|
||
} else if num == 2 {
|
||
//留对子
|
||
_, pairMap := GetPair(copyCards)
|
||
if len(pairMap) > 0 {
|
||
maxPair := -1
|
||
maxKey := int32(0)
|
||
for i, pair := range pairMap {
|
||
if Value(pair[0]) > maxPair {
|
||
maxPair = Value(pair[0])
|
||
maxKey = i
|
||
}
|
||
}
|
||
for _, card := range cards {
|
||
if card == pairMap[maxKey][0] || card == pairMap[maxKey][1] {
|
||
continue
|
||
}
|
||
outCards = append(outCards, card)
|
||
}
|
||
} else {
|
||
//留最后两张大牌
|
||
maxCard := copyCards[len(copyCards)-2:]
|
||
for _, card := range cards {
|
||
if card == maxCard[0] || card == maxCard[1] {
|
||
continue
|
||
}
|
||
outCards = append(outCards, card)
|
||
}
|
||
|
||
}
|
||
} else if num == 3 {
|
||
//留顺子
|
||
straights := cardsTypeMap[Straight]
|
||
if len(straights) > 0 {
|
||
straight := straights[int32(len(straights)-1)]
|
||
saveCards := straight[len(straight)-3:]
|
||
for _, card := range cards {
|
||
if card == saveCards[0] || card == saveCards[1] || card == saveCards[2] {
|
||
continue
|
||
}
|
||
outCards = append(outCards, card)
|
||
}
|
||
|
||
} else {
|
||
//留最后三张大牌
|
||
maxCard := copyCards[len(copyCards)-3:]
|
||
for _, card := range cards {
|
||
if card == maxCard[0] || card == maxCard[1] || card == maxCard[2] {
|
||
continue
|
||
}
|
||
outCards = append(outCards, card)
|
||
}
|
||
}
|
||
} else {
|
||
//直接出三顺
|
||
straightTripleMap := cardsTypeMap[Straight_Triple]
|
||
for _, straightTriple := range straightTripleMap {
|
||
outCards = straightTriple
|
||
break
|
||
}
|
||
}
|
||
}
|
||
logger.Logger.Trace("-----------出三顺--------------------", outCards)
|
||
return outCards, cardValue
|
||
|
||
}
|
||
|
||
if len(cardsTypeMap[Triple]) > 0 {
|
||
minSingleKey := findMinKey(cardsTypeMap[Single])
|
||
minTwinKey := findMinKey(cardsTypeMap[Twin])
|
||
minTripleKey := findMinKey(cardsTypeMap[Triple])
|
||
if len(cardsTypeMap[Triple]) == 2 && len(cards) <= 9 {
|
||
//先出大的三条
|
||
minTripleKey = findMaxKey(cardsTypeMap[Triple])
|
||
}
|
||
if len(cardsTypeMap[Triple]) >= 2 && len(cards) <= 8 && isYuLe {
|
||
//判断单张数量
|
||
if len(cardsTypeMap[Single]) < 2 {
|
||
//判断是不是三顺
|
||
var arr []int32
|
||
for _, three := range cardsTypeMap[Triple] {
|
||
for _, value := range three {
|
||
arr = append(arr, value)
|
||
}
|
||
}
|
||
StraightTripleMap := GetStraightTriple(arr)
|
||
if len(StraightTripleMap) > 0 {
|
||
//娱乐场 小于11张牌可以一首扔
|
||
return cards, cardValue
|
||
}
|
||
}
|
||
}
|
||
if isYuLe {
|
||
//出三代2 或三带一小对 单张小于12 三顺小于等于7
|
||
otherCard := getOtherPlayerCards(mypos, otherPos, data)
|
||
if len(cardsTypeMap[Single]) >= 2 && (Value(cardsTypeMap[Single][minSingleKey][0]) < 12 || handNum <= 2 || (otherMinHandNum == 1 && len(otherCard) == 1 && len(cardsTypeMap[Single]) >= 3)) {
|
||
//三代2单
|
||
if Value(cardsTypeMap[Triple][minTripleKey][0]) <= 9 || handNum <= 2 || (otherMinHandNum == 1 && len(otherCard) == 1 && len(cardsTypeMap[Single]) >= 3) {
|
||
outCards = cardsTypeMap[Triple][minTripleKey]
|
||
minValue := FindSmallestTwoValues(cardsTypeMap[Single])
|
||
if len(minValue) < 2 {
|
||
logger.Logger.Tracef("找出最小两张单排的值,没找出来!!!!!!!!!!!!!!!!!!!!!!!!!minValue = %v,cardsTypeMap[Single]= %v", minValue, cardsTypeMap[Single])
|
||
} else {
|
||
outCards = append(outCards, minValue[0], minValue[1])
|
||
}
|
||
|
||
}
|
||
} else if len(cardsTypeMap[Twin]) >= 1 && (Value(cardsTypeMap[Twin][minTwinKey][0]) < 11 || handNum <= 3) {
|
||
//三代一对
|
||
outCards = cardsTypeMap[Triple][minTripleKey]
|
||
outCards = append(outCards, cardsTypeMap[Twin][minTwinKey][0], cardsTypeMap[Twin][minTwinKey][1])
|
||
} else {
|
||
if len(cards) > 5 {
|
||
outCards = cardsTypeMap[Triple][minTripleKey]
|
||
if len(cardsTypeMap[Single]) > 0 {
|
||
for _, single := range cardsTypeMap[Single] {
|
||
outCards = append(outCards, single[0])
|
||
}
|
||
}
|
||
|
||
if len(outCards) < 5 {
|
||
//找顺子交集
|
||
result := FindIntersection(cardsTypeMap[Straight])
|
||
if len(result) > 0 {
|
||
sort.Slice(cards, func(i, j int) bool {
|
||
if Value(cards[i]) == Value(cards[j]) {
|
||
return cards[i] < cards[j]
|
||
}
|
||
return Value(cards[i]) < Value(cards[j])
|
||
})
|
||
}
|
||
for _, cardArr := range result {
|
||
for _, card := range cardArr {
|
||
outCards = append(outCards, card)
|
||
if len(outCards) == 5 {
|
||
break
|
||
}
|
||
}
|
||
if len(outCards) == 5 {
|
||
break
|
||
}
|
||
}
|
||
//找顺子
|
||
if len(outCards) < 5 {
|
||
if len(cardsTypeMap[Straight]) > 0 {
|
||
for _, straights := range cardsTypeMap[Straight] {
|
||
//剩余俩个三张 一共8张牌
|
||
if len(straights)-(5-len(outCards)) >= 3 || (len(cards) == 10 && len(cardsTypeMap[Triple]) == 2) {
|
||
for i := 0; i < 5-len(outCards); i++ {
|
||
outCards = append(outCards, straights[i])
|
||
if len(outCards) == 5 {
|
||
break
|
||
}
|
||
}
|
||
if len(outCards) == 5 {
|
||
break
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
if len(outCards) != 5 {
|
||
//直接出三张
|
||
outCards = cardsTypeMap[Triple][minTripleKey]
|
||
}
|
||
} else {
|
||
//直接出三张
|
||
outCards = cardsTypeMap[Triple][minTripleKey]
|
||
}
|
||
}
|
||
//出三张拦截 下面三手牌会判断牌型出 这里直接不让出三个2
|
||
if Value(cardsTypeMap[Triple][minTripleKey][0]) == 12 && handNum <= 3 && handNum != 1 && len(cards) >= 10 {
|
||
logger.Logger.Trace("出三张 拦截 三个2 !!!!!!!!!!!!!!!")
|
||
outCards = []int32{}
|
||
return outCards, 0
|
||
}
|
||
} else {
|
||
outCards = cardsTypeMap[Triple][minTripleKey]
|
||
if isYuLe {
|
||
if len(cards) <= 5 {
|
||
//最后4张牌 出三带1
|
||
outCards = cards
|
||
}
|
||
}
|
||
}
|
||
cardValue = Value(cardsTypeMap[Triple][minTripleKey][0])
|
||
}
|
||
return outCards, cardValue
|
||
}
|
||
|
||
// 出顺子
|
||
func getStraight(cardsTypeMap map[int]map[int32][]int32, cards []int32, isYuLe bool) []int32 {
|
||
outCards := []int32{}
|
||
_, handNum := GetCardTypeScore(cardsTypeMap, isYuLe, cards)
|
||
if len(cardsTypeMap[Straight]) >= 1 {
|
||
//出顺子
|
||
//如果只剩两手牌 先出最长的顺子
|
||
if handNum <= 2 {
|
||
//找长度最大的顺子
|
||
maxLength := 0
|
||
maxKey := int32(0)
|
||
for i, straight := range cardsTypeMap[Straight] {
|
||
if len(straight) > maxLength {
|
||
maxKey = i
|
||
}
|
||
}
|
||
outCards = cardsTypeMap[Straight][maxKey]
|
||
} else {
|
||
//找小顺子
|
||
outCards = cardsTypeMap[Straight][0]
|
||
}
|
||
}
|
||
return outCards
|
||
}
|
||
|
||
// 出连对
|
||
func getStraightTwin(cardsTypeMap map[int]map[int32][]int32, cards []int32, isYuLe bool) []int32 {
|
||
outCards := []int32{}
|
||
if len(cardsTypeMap[Straight_Twin]) > 0 {
|
||
//找长度最小的连对
|
||
length := 0
|
||
key := int32(0)
|
||
for i, straight := range cardsTypeMap[Straight_Twin] {
|
||
if len(straight) < length && len(straight) > 0 {
|
||
key = i
|
||
}
|
||
}
|
||
outCards = cardsTypeMap[Straight_Twin][key]
|
||
}
|
||
return outCards
|
||
}
|
||
|
||
// 出炸弹
|
||
func getBomb(cardsTypeMap map[int]map[int32][]int32, cards []int32, isYuLe bool) []int32 {
|
||
outCards := []int32{}
|
||
//炸弹
|
||
if len(cardsTypeMap[Four_Bomb]) > 0 {
|
||
//出炸弹
|
||
minTripleKey := findMinKey(cardsTypeMap[Four_Bomb])
|
||
outCards = cardsTypeMap[Four_Bomb][minTripleKey]
|
||
}
|
||
return outCards
|
||
}
|
||
|
||
// ---------------------------------------------//
|
||
|
||
// 找手里最小的牌的组合
|
||
func GetMinCardType(minCard int32, cardsType map[int]map[int32][]int32, isYuLe bool) []int32 {
|
||
for cardType, cards := range cardsType {
|
||
for _, cardArr := range cards {
|
||
for i, card := range cardArr {
|
||
if Value(card) == Value(minCard) {
|
||
if card == minCard {
|
||
if cardType == Triple && isYuLe {
|
||
//找两张单张
|
||
minSingleKey := findMinKey(cardsType[Single])
|
||
minTwinKey := findMinKey(cardsType[Twin])
|
||
if len(cardsType[Single]) >= 2 && Value(cardsType[Single][minSingleKey][0]) < 12 {
|
||
//三代2单
|
||
if len(cardsType[Single]) >= 2 {
|
||
minValue := FindSmallestTwoValues(cardsType[Single])
|
||
cardArr = append(cardArr, minValue[0], minValue[1])
|
||
}
|
||
} else if len(cardsType[Twin]) >= 1 && Value(cardsType[Twin][minTwinKey][0]) < 11 {
|
||
//三代一对
|
||
cardArr = append(cardArr, cardsType[Twin][minTwinKey][0], cardsType[Twin][minTwinKey][1])
|
||
}
|
||
}
|
||
return cardArr
|
||
} else {
|
||
//替换牌
|
||
cardArr[i] = minCard
|
||
if cardType == Triple && isYuLe {
|
||
//找两张单张 变成三代二
|
||
minSingleKey := findMinKey(cardsType[Single])
|
||
minTwinKey := findMinKey(cardsType[Twin])
|
||
if len(cardsType[Single]) >= 2 && Value(cardsType[Single][minSingleKey][0]) < 12 {
|
||
//三代2单
|
||
if len(cardsType[Single]) >= 2 {
|
||
minValue := FindSmallestTwoValues(cardsType[Single])
|
||
cardArr = append(cardArr, minValue[0], minValue[1])
|
||
}
|
||
} else if len(cardsType[Twin]) >= 1 && Value(cardsType[Twin][minTwinKey][0]) < 11 {
|
||
//三代一对
|
||
cardArr = append(cardArr, cardsType[Twin][minTwinKey][0], cardsType[Twin][minTwinKey][1])
|
||
}
|
||
}
|
||
return cardArr
|
||
}
|
||
|
||
}
|
||
}
|
||
}
|
||
}
|
||
//直接返回单张
|
||
return []int32{minCard}
|
||
}
|
||
|
||
// 获取下一家的位置和剩余的牌
|
||
func GetNextPos(pos int32, data *tienlenApi.PredictRequest) (int32, []int32) {
|
||
for i := 1; i < 4; i++ {
|
||
nextPos := pos + int32(i)
|
||
if nextPos > 3 {
|
||
nextPos -= 4
|
||
}
|
||
//判断这个位置有没有剩余牌
|
||
if nextPos == 0 && len(data.Cards_left_0) > 0 {
|
||
return nextPos, data.Cards_left_0
|
||
} else if nextPos == 1 && len(data.Cards_left_1) > 0 {
|
||
return nextPos, data.Cards_left_1
|
||
} else if nextPos == 2 && len(data.Cards_left_2) > 0 {
|
||
return nextPos, data.Cards_left_2
|
||
} else if nextPos == 3 && len(data.Cards_left_3) > 0 {
|
||
return nextPos, data.Cards_left_3
|
||
}
|
||
}
|
||
return -1, nil
|
||
}
|
||
|
||
// 获取上家的位置和剩余的牌
|
||
func GetLastPos(pos int32, data *tienlenApi.PredictRequest) (int32, []int32) {
|
||
for i := 1; i < 4; i++ {
|
||
nextPos := (pos - int32(i) + 4) % 4
|
||
//判断这个位置有没有剩余牌
|
||
if nextPos == 0 && len(data.Cards_left_0) > 0 {
|
||
return nextPos, data.Cards_left_0
|
||
} else if nextPos == 1 && len(data.Cards_left_1) > 0 {
|
||
return nextPos, data.Cards_left_1
|
||
} else if nextPos == 2 && len(data.Cards_left_2) > 0 {
|
||
return nextPos, data.Cards_left_2
|
||
} else if nextPos == 3 && len(data.Cards_left_3) > 0 {
|
||
return nextPos, data.Cards_left_3
|
||
}
|
||
}
|
||
return -1, nil
|
||
}
|
||
|
||
// 获取指定玩家的牌
|
||
func getOtherPlayerCards(mypos, otherPos int32, data *tienlenApi.PredictRequest) []int32 {
|
||
otherCardsMap := getOtherCards(mypos, data)
|
||
sort.Slice(otherCardsMap[int(otherPos)], func(i, j int) bool {
|
||
if otherCardsMap[int(otherPos)][i] == otherCardsMap[int(otherPos)][j] {
|
||
return otherCardsMap[int(otherPos)][i] < otherCardsMap[int(otherPos)][j]
|
||
}
|
||
return Value(otherCardsMap[int(otherPos)][i]) < Value(otherCardsMap[int(otherPos)][j])
|
||
})
|
||
return otherCardsMap[int(otherPos)]
|
||
}
|
||
|
||
// 判断自己手里有没有最大的牌
|
||
func getMaxCards(myCards []int32, data *tienlenApi.PredictRequest, mypos int32) (bool, int, []int32) {
|
||
sort.Slice(myCards, func(i, j int) bool {
|
||
if Value(myCards[i]) == Value(myCards[j]) {
|
||
return myCards[i] < myCards[j]
|
||
}
|
||
return Value(myCards[i]) < Value(myCards[j])
|
||
})
|
||
//getOtherCards()
|
||
otherCardsMap := getOtherCards(mypos, data)
|
||
var otherCards []int32
|
||
for _, otherCard := range otherCardsMap {
|
||
otherCards = append(otherCards, otherCard...)
|
||
}
|
||
|
||
sort.Slice(otherCards, func(i, j int) bool {
|
||
if Value(otherCards[i]) == Value(otherCards[j]) {
|
||
return otherCards[i] < otherCards[j]
|
||
}
|
||
return Value(otherCards[i]) < Value(otherCards[j])
|
||
})
|
||
maxCardNum := 0
|
||
status := false
|
||
maxCardsArr := []int32{}
|
||
for _, mycard := range myCards {
|
||
if Value(mycard) >= Value(otherCards[len(otherCards)-1]) {
|
||
if Value(mycard) == Value(otherCards[len(otherCards)-1]) {
|
||
if Color(mycard) < Color(otherCards[len(otherCards)-1]) {
|
||
continue
|
||
}
|
||
}
|
||
maxCardNum += 1
|
||
status = true
|
||
maxCardsArr = append(maxCardsArr, mycard)
|
||
}
|
||
}
|
||
//排序返回
|
||
sort.Slice(maxCardsArr, func(i, j int) bool {
|
||
if Value(maxCardsArr[i]) == Value(maxCardsArr[j]) {
|
||
return maxCardsArr[i] < maxCardsArr[j]
|
||
}
|
||
return Value(maxCardsArr[i]) < Value(maxCardsArr[j])
|
||
})
|
||
return status, maxCardNum, maxCardsArr
|
||
}
|
||
func findMinKey(data map[int32][]int32) int32 {
|
||
minValue := int32(math.MaxInt32)
|
||
minKey := int32(-1)
|
||
for i, value := range data {
|
||
if int32(Value(value[0])) < minValue {
|
||
minValue = int32(Value(value[0]))
|
||
minKey = i
|
||
}
|
||
}
|
||
return minKey
|
||
}
|
||
func findMaxKey(data map[int32][]int32) int32 {
|
||
maxKey := int32(-1)
|
||
|
||
for key := range data {
|
||
if key > maxKey {
|
||
maxKey = key
|
||
}
|
||
}
|
||
|
||
return maxKey
|
||
}
|
||
|
||
// 获取其他玩家的牌
|
||
func getOtherCards(myPos int32, data *tienlenApi.PredictRequest) map[int][]int32 {
|
||
otherCards := make(map[int][]int32)
|
||
for i := 0; i < 4; i++ {
|
||
if i == int(myPos) {
|
||
continue
|
||
}
|
||
if i == 0 {
|
||
otherCards[i] = data.Cards_left_0
|
||
} else if i == 1 {
|
||
otherCards[i] = data.Cards_left_1
|
||
} else if i == 2 {
|
||
otherCards[i] = data.Cards_left_2
|
||
} else if i == 3 {
|
||
otherCards[i] = data.Cards_left_3
|
||
}
|
||
}
|
||
return otherCards
|
||
}
|
||
|
||
// 获取其他玩家最小剩余手数 和剩余牌数及位置剩余的牌型
|
||
func getOtherMinCards(myPos int32, data *tienlenApi.PredictRequest, isYuLe bool) (int, int, int, int) {
|
||
otherCards := getOtherCards(myPos, data)
|
||
otherMinHandNum := 100
|
||
otherMinCardsNum := 13
|
||
otherPos := -1
|
||
cardsType := -1
|
||
maxCards := []int32{}
|
||
for i, other := range otherCards {
|
||
//获取牌型
|
||
if len(other) > 0 {
|
||
cardsTypeMap := GetCardsType(other, isYuLe)
|
||
//剩余手数
|
||
_, handNum := GetCardTypeScore(cardsTypeMap, isYuLe, other)
|
||
if handNum <= otherMinHandNum && len(other) <= otherMinCardsNum {
|
||
if handNum == otherMinHandNum && len(other) <= otherMinHandNum {
|
||
_, ruleType := RulePopEnable(other)
|
||
if ruleType == cardsType {
|
||
//相同牌型找最大的牌
|
||
if Value(other[len(other)-1]) < Value(maxCards[len(maxCards)-1]) {
|
||
continue
|
||
}
|
||
}
|
||
}
|
||
otherMinHandNum = handNum
|
||
otherMinCardsNum = len(other)
|
||
otherPos = i
|
||
maxCards = other
|
||
if handNum <= 1 {
|
||
isRule, ruleType := RulePopEnable(other)
|
||
if isRule {
|
||
cardsType = ruleType
|
||
} else {
|
||
//三张 三带一 三带二
|
||
cardsType = Triple
|
||
}
|
||
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return otherMinHandNum, otherMinCardsNum, otherPos, cardsType
|
||
}
|
||
|
||
// 找到最小的两个值
|
||
func FindSmallestTwoValues(m map[int32][]int32) []int32 {
|
||
// 创建一个切片存储map的键值对
|
||
pairs := make([][2]int32, 0)
|
||
|
||
// 将map的键值对存储在切片中
|
||
for key := range m {
|
||
pairs = append(pairs, [2]int32{key, key})
|
||
}
|
||
|
||
// 对切片按照键值进行排序
|
||
sort.Slice(pairs, func(i, j int) bool {
|
||
return pairs[i][0] < pairs[j][0]
|
||
})
|
||
|
||
// 取出最小的两个值
|
||
var smallestTwo []int32
|
||
if len(pairs) >= 2 {
|
||
smallestTwo = append(smallestTwo, m[pairs[0][0]]...)
|
||
if len(m[pairs[1][0]]) > 0 {
|
||
smallestTwo = append(smallestTwo, m[pairs[1][0]]...)
|
||
}
|
||
} else if len(pairs) == 1 {
|
||
smallestTwo = m[pairs[0][0]]
|
||
}
|
||
return smallestTwo
|
||
}
|
||
|
||
// 找交集
|
||
func FindIntersection(arrays map[int32][]int32) [][]int32 {
|
||
var result [][]int32
|
||
|
||
// 获取 map 中的键,并按顺序进行迭代
|
||
keys := make([]int32, 0, len(arrays))
|
||
for key := range arrays {
|
||
keys = append(keys, key)
|
||
}
|
||
sort.Slice(keys, func(i, j int) bool {
|
||
return keys[i] < keys[j]
|
||
})
|
||
|
||
// 检查相邻的数组之间的交集
|
||
for i := 0; i < len(keys)-1; i++ {
|
||
currentKey := keys[i]
|
||
nextKey := keys[i+1]
|
||
|
||
currentArray := arrays[currentKey]
|
||
nextArray := arrays[nextKey]
|
||
|
||
intersection := GetArrayIntersection(currentArray, nextArray)
|
||
if intersection != nil {
|
||
result = append(result, intersection)
|
||
}
|
||
}
|
||
|
||
return result
|
||
}
|
||
|
||
// 获取两个切片的交集
|
||
func GetArrayIntersection(arr1, arr2 []int32) []int32 {
|
||
// 创建一个 map 用于存储第一个切片中的元素
|
||
elements := make(map[int32]bool)
|
||
for _, num := range arr1 {
|
||
elements[num] = true
|
||
}
|
||
|
||
// 检查第二个切片中的元素是否在第一个切片中出现,如果是,则添加到结果中
|
||
var result []int32
|
||
for _, num := range arr2 {
|
||
if elements[num] {
|
||
result = append(result, num)
|
||
}
|
||
}
|
||
|
||
return result
|
||
}
|
||
|
||
// 是否压牌
|
||
func IsPressed(isYuLe, isEnd bool, otherCards, lastCards []int32, data *tienlenApi.PredictRequest, pos, lastPos, nextPos int32, handCardnum, cardsType int) bool {
|
||
if (!isYuLe && isEnd) && len(otherCards) == 0 {
|
||
lastNextPos, _ := GetNextPos(lastPos, data)
|
||
if lastNextPos == pos && nextPos != lastPos {
|
||
if getMaxCardTypeNum(cardsType, lastCards, pos, data) && handCardnum > 2 {
|
||
return false
|
||
}
|
||
if len(lastCards) > 0 {
|
||
if Value(lastCards[0]) == 2 && handCardnum > 2 {
|
||
return false
|
||
}
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
return true
|
||
}
|
||
|
||
// 重组牌型
|
||
func reloadcardsType(cardsTypeMap map[int]map[int32][]int32, pos int32, data *tienlenApi.PredictRequest, isYuLe bool) map[int]map[int32][]int32 {
|
||
//其他玩家只剩一张牌了
|
||
otherMinHandNum, otherMinCardsNum, otherPos, otherCardsType := getOtherMinCards(pos, data, isYuLe)
|
||
//otherCards := getOtherPlayerCards(pos, int32(otherPos), data)
|
||
|
||
//剩余两手 全是单牌
|
||
status := false
|
||
allOtherCards := getOtherCards(pos, data)
|
||
for _, otherCards := range allOtherCards {
|
||
if len(otherCards) == 2 {
|
||
otherType := GetCardsType(otherCards, isYuLe)
|
||
//剩余手数
|
||
_, handNum := GetCardTypeScore(otherType, isYuLe, otherCards)
|
||
if handNum == 2 {
|
||
otherMaxCard := otherCards[0]
|
||
if Value(otherCards[0]) < Value(otherCards[1]) {
|
||
otherMaxCard = otherCards[1]
|
||
}
|
||
if getMaxCardTypeNum(Single, []int32{otherMaxCard}, pos, data) {
|
||
logger.Logger.Trace("玩家剩余2张牌且有一张全场最大的牌,重组牌型!otherCards = ", otherCards)
|
||
status = true
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
if (otherMinHandNum == 1 && otherMinCardsNum <= 1 && otherCardsType == Single) || status {
|
||
//lastPos, _ := GetLastPos(pos, data)
|
||
//nextPos, _ := GetNextPos(pos, data)
|
||
//只考虑剩2人的情况下
|
||
//if nextPos == int32(otherPos) {
|
||
//判断我手里的单牌 组对子
|
||
if len(cardsTypeMap[Single]) >= 2 {
|
||
//判断如果单牌有2张以上小于其他玩家的牌,开始组对子
|
||
otherCards := getOtherPlayerCards(pos, int32(otherPos), data)
|
||
minCards := map[int32]int32{}
|
||
for i, card := range cardsTypeMap[Single] {
|
||
if Value(card[0]) <= Value(otherCards[0]) {
|
||
//判断花色
|
||
if Value(card[0]) == Value(otherCards[0]) {
|
||
if Color(card[0]) < Color(otherCards[0]) {
|
||
//minCards = append(minCards, card[0])
|
||
minCards[i] = card[0]
|
||
continue
|
||
}
|
||
} else {
|
||
//minCards = append(minCards, card[0])
|
||
minCards[i] = card[0]
|
||
}
|
||
}
|
||
}
|
||
//有超过两张的单牌小于其他玩家的牌,开始组对子
|
||
if len(minCards) >= 2 {
|
||
//开始拆顺子 组对子
|
||
if len(cardsTypeMap[Straight]) > 0 {
|
||
straightMap := cardsTypeMap[Straight]
|
||
for delKey, minCard := range minCards {
|
||
for straightKey, straight := range straightMap {
|
||
if len(straight) <= 3 {
|
||
continue
|
||
}
|
||
//先找最小的牌
|
||
if Value(straight[0]) == Value(minCard) {
|
||
if cardsTypeMap[Twin] == nil {
|
||
cardsTypeMap[Twin] = map[int32][]int32{}
|
||
}
|
||
cardsTypeMap[Twin][int32(Value(minCard))] = append(cardsTypeMap[Twin][int32(Value(minCard))], minCard, straight[0])
|
||
|
||
cardsTypeMap[Straight][straightKey] = cardsTypeMap[Straight][straightKey][1:]
|
||
//删除单张
|
||
delete(cardsTypeMap[Single], delKey)
|
||
break
|
||
} else if Value(straight[len(straight)-1]) == Value(minCard) {
|
||
if cardsTypeMap[Twin] == nil {
|
||
cardsTypeMap[Twin] = map[int32][]int32{}
|
||
}
|
||
cardsTypeMap[Twin][int32(Value(minCard))] = append(cardsTypeMap[Twin][int32(Value(minCard))], minCard, straight[len(straight)-1])
|
||
cardsTypeMap[Straight][straightKey] = cardsTypeMap[Straight][straightKey][:len(straight)-1]
|
||
//删除单张
|
||
delete(cardsTypeMap[Single], delKey)
|
||
break
|
||
} else {
|
||
//找中间 暂时不做 情况太复杂了 需要考虑的太多
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
//}
|
||
if len(cardsTypeMap[Single]) == 0 {
|
||
delete(cardsTypeMap, Single)
|
||
}
|
||
if len(cardsTypeMap[Straight]) == 0 {
|
||
delete(cardsTypeMap, Straight)
|
||
}
|
||
}
|
||
return cardsTypeMap
|
||
}
|
||
|
||
// 获取所有玩家剩余的牌型
|
||
func GetAllOtherCardsType(data *tienlenApi.PredictRequest, pos int32, isYuLe bool) map[int]map[int]map[int32][]int32 {
|
||
allOtherCardsType := map[int]map[int]map[int32][]int32{}
|
||
for i := 1; i < 4; i++ {
|
||
if i == int(pos) {
|
||
continue
|
||
}
|
||
//判断这个位置有没有剩余牌
|
||
if i == 0 && len(data.Cards_left_0) > 0 {
|
||
cardsTypeMap0 := GetCardsType(data.Cards_left_0, isYuLe)
|
||
allOtherCardsType[i] = cardsTypeMap0
|
||
} else if i == 1 && len(data.Cards_left_1) > 0 {
|
||
cardsTypeMap1 := GetCardsType(data.Cards_left_1, isYuLe)
|
||
allOtherCardsType[i] = cardsTypeMap1
|
||
} else if i == 2 && len(data.Cards_left_2) > 0 {
|
||
cardsTypeMap2 := GetCardsType(data.Cards_left_2, isYuLe)
|
||
allOtherCardsType[i] = cardsTypeMap2
|
||
} else if i == 3 && len(data.Cards_left_3) > 0 {
|
||
cardsTypeMap3 := GetCardsType(data.Cards_left_3, isYuLe)
|
||
allOtherCardsType[i] = cardsTypeMap3
|
||
}
|
||
}
|
||
return allOtherCardsType
|
||
}
|
||
|
||
// 判断能不能出顺子
|
||
func IsOutStraight(data *tienlenApi.PredictRequest, pos int32, isYuLe bool, mycards []int32) (bool, int) {
|
||
allOtherCardsType := GetAllOtherCardsType(data, pos, isYuLe)
|
||
copyMap := make(map[int]map[int]map[int32][]int32)
|
||
for k1, v1 := range allOtherCardsType {
|
||
copyMap[k1] = make(map[int]map[int32][]int32)
|
||
for k2, v2 := range v1 {
|
||
copyMap[k1][k2] = make(map[int32][]int32)
|
||
for k3, v3 := range v2 {
|
||
copyMap[k1][k2][k3] = make([]int32, len(v3))
|
||
copy(copyMap[k1][k2][k3], v3)
|
||
}
|
||
}
|
||
}
|
||
|
||
for i, OtherCardsType := range copyMap {
|
||
if len(OtherCardsType[Straight]) > 0 {
|
||
for _, otherStraight := range OtherCardsType[Straight] {
|
||
if len(otherStraight) >= len(mycards) {
|
||
if len(otherStraight)-len(mycards) <= 2 {
|
||
//说明要拆牌多出来2张,我可以出
|
||
}
|
||
if Value(otherStraight[len(otherStraight)-1]) <= Value(mycards[len(mycards)-1]) {
|
||
//判断花色
|
||
if Value(otherStraight[len(otherStraight)-1]) == Value(mycards[len(mycards)-1]) {
|
||
if Color(otherStraight[len(otherStraight)-1]) < Color(mycards[len(mycards)-1]) {
|
||
continue
|
||
}
|
||
} else {
|
||
continue
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
//判断剩余的牌是不是全是顺子
|
||
delete(OtherCardsType, Straight)
|
||
if len(OtherCardsType) <= 1 {
|
||
logger.Logger.Trace("全是顺子啊,还比我的大!!!!不能打顺子!")
|
||
return false, i
|
||
}
|
||
}
|
||
}
|
||
return true, -1
|
||
}
|