game_sync/gamerule/tienlen/poker.go

652 lines
13 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package tienlen
import (
"math/rand"
"sort"
"time"
)
//牌序- 2, A, K, Q, J, 10, 9, 8, 7, 6, 5, 4, 3
//红桃- 51,50,49,48,47,46,45,44,43,42,41,40,39
//方片- 38,37,36,35,34,33,32,31,30,29,28,27,26
//梅花- 25,24,23,22,21,20,19,18,17,16,15,14,13
//黑桃- 12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
const (
POKER_CNT = 52
PER_CARD_COLOR_MAX = 13
Hand_CardNum = 13 //手牌
Card_Value_2 = 12 //特殊牌值2
Player_Num_Max = 4 //桌上最大人數
HongTao2 = 51
FangPian2 = 38
MeiHua2 = 25
HeiTao2 = 12
)
// 不同牌型分值
const (
hei2 = 0
fang2 = 3
hong2 = 5
zhadan = 20
liandui5 = 21
liandui4 = 18
liandui3 = 15
shunzi8 = 15
shunzi7 = 10
shunzi6 = 5
sanzhang = 3
)
const (
yl_hei2 = 0
yl_fang2 = 3
yl_hong2 = 5
yl_zhadan = 30
yl_liandui5 = 21
yl_liandui4 = 18
yl_liandui3 = 15
yl_shunzi8 = 15
yl_shunzi7 = 10
yl_shunzi6 = 5
yl_sanzhang = 15
)
type Card int
type Poker struct {
buf [POKER_CNT]Card
copyBuf [POKER_CNT]Card
tianhuBuf [POKER_CNT]Card
isTianhu bool
}
func (this *Poker) GetPokerBuf() [POKER_CNT]Card {
return this.buf
}
func (this *Poker) CopyPokerBuf() {
for i := 0; i < len(this.buf); i++ {
this.copyBuf[i] = this.buf[i]
}
}
func (this *Poker) UncopyPokerBuf() {
for i := 0; i < len(this.copyBuf); i++ {
this.buf[i] = this.copyBuf[i]
this.copyBuf[i] = Card(i)
}
}
func (this *Poker) TianhuPokerBuf() {
for i := 0; i < len(this.buf); i++ {
this.tianhuBuf[i] = this.buf[i]
}
this.isTianhu = true
}
func (this *Poker) UnTianhuPokerBuf() {
for i := 0; i < len(this.tianhuBuf); i++ {
this.buf[i] = this.tianhuBuf[i]
this.tianhuBuf[i] = Card(i)
}
this.isTianhu = false
}
func (this *Poker) IsTianhuPoker() bool {
return this.isTianhu
}
func NewPoker() *Poker {
p := &Poker{}
p.init()
return p
}
func (this *Poker) init() {
for i := int32(0); i < POKER_CNT; i++ {
this.buf[i] = Card(i)
}
rand.Seed(time.Now().UnixNano())
this.Shuffle()
}
func (this *Poker) Shuffle() {
for i := int32(0); i < POKER_CNT; i++ {
j := rand.Intn(int(i) + 1)
this.buf[i], this.buf[j] = this.buf[j], this.buf[i]
}
}
// GetCardsGrade 给手牌打分
func GetCardsGrade(cards []int32, yl bool) int {
grade := 0
cpCards := []int32{}
for _, card := range cards {
if card != InvalideCard {
cpCards = append(cpCards, card)
grade += Value(card) + 1 // 基础分
}
}
if Have2FourBomb(cpCards) || Have6StraightTwin(cpCards) || Have12Straight(cpCards) {
return 9999
}
//找单2
for i := 0; i < len(cpCards); i++ {
card := cpCards[i]
switch card {
case HongTao2:
if yl {
grade += yl_hong2
} else {
grade += hong2
}
cpCards = append(cpCards[:i], cpCards[i+1:]...)
i--
case FangPian2:
if yl {
grade += yl_fang2
} else {
grade += fang2
}
cpCards = append(cpCards[:i], cpCards[i+1:]...)
i--
case MeiHua2, HeiTao2:
if yl {
grade += yl_hei2
} else {
grade += hei2
}
cpCards = append(cpCards[:i], cpCards[i+1:]...)
i--
}
}
// 找炸弹
if len(cpCards) >= 4 {
mapBomb := make(map[int32]int)
for _, card := range cpCards {
mapBomb[int32(Value(card))]++
}
bombValue := []int32{}
for card, num := range mapBomb {
if num == 4 {
bombValue = append(bombValue, card)
}
}
if len(bombValue) > 0 {
findCards := []int32{}
for _, card := range bombValue {
for i := int32(0); i < 4; i++ {
findCards = append(findCards, card+(i*PER_CARD_COLOR_MAX))
cpCards = DelSliceInt32(cpCards, card+(i*PER_CARD_COLOR_MAX))
}
}
if yl {
grade += len(bombValue) * yl_zhadan
} else {
grade += len(bombValue) * zhadan
}
}
}
//找五连
if len(cpCards) >= 10 {
sort.Slice(cpCards, func(i, j int) bool {
if cpCards[i] > cpCards[j] {
return false
}
return true
})
map5STwin := make(map[int32]int32)
for _, card := range cpCards {
map5STwin[int32(Value(card))]++
}
Value5STwin := []int32{}
for card, num := range map5STwin {
if num >= 2 {
Value5STwin = append(Value5STwin, card)
}
}
sort.Slice(Value5STwin, func(i, j int) bool {
if Value5STwin[i] > Value5STwin[j] {
return false
}
return true
})
if len(Value5STwin) > 0 {
tmpPairs := FindOneStraightWithWidth(5, Value5STwin)
if len(tmpPairs) > 0 {
findCards := []int32{}
for _, card := range tmpPairs {
delC := 0
for i := 0; i < len(cpCards); i++ {
if cpCards[i] == InvalideCard {
continue
}
if int32(Value(cpCards[i])) == card && (delC < 2) { //删除2次
findCards = append(findCards, card)
delC++
cpCards = append(cpCards[:i], cpCards[i+1:]...)
i--
continue
}
}
}
if yl {
grade += yl_liandui5
} else {
grade += liandui5
}
}
}
}
//找四连
if len(cpCards) >= 8 {
sort.Slice(cpCards, func(i, j int) bool {
if cpCards[i] > cpCards[j] {
return false
}
return true
})
map4STwin := make(map[int32]int32)
for _, card := range cpCards {
map4STwin[int32(Value(card))]++
}
Value4STwin := []int32{}
for card, num := range map4STwin {
if num >= 2 {
Value4STwin = append(Value4STwin, card)
}
}
sort.Slice(Value4STwin, func(i, j int) bool {
if Value4STwin[i] > Value4STwin[j] {
return false
}
return true
})
if len(Value4STwin) > 0 {
tmpPairs := FindOneStraightWithWidth(4, Value4STwin)
if len(tmpPairs) > 0 {
findCards := []int32{}
for _, card := range tmpPairs {
delC := 0
for i := 0; i < len(cpCards); i++ {
if cpCards[i] != InvalideCard {
if int32(Value(cpCards[i])) == card && (delC < 2) { //删除2次
findCards = append(findCards, card)
delC++
cpCards = append(cpCards[:i], cpCards[i+1:]...)
i--
continue
}
}
}
}
if yl {
grade += yl_liandui4
} else {
grade += liandui4
}
}
}
}
//找三连
if len(cpCards) >= 6 {
sort.Slice(cpCards, func(i, j int) bool {
if cpCards[i] > cpCards[j] {
return false
}
return true
})
map3STwin := make(map[int32]int32)
for _, card := range cpCards {
map3STwin[int32(Value(card))]++
}
Value3STwin := []int32{}
for card, num := range map3STwin {
if num >= 2 {
Value3STwin = append(Value3STwin, card)
}
}
sort.Slice(Value3STwin, func(i, j int) bool {
if Value3STwin[i] > Value3STwin[j] {
return false
}
return true
})
if len(Value3STwin) > 0 {
tmpPairs := FindOneStraightWithWidth(3, Value3STwin)
if len(tmpPairs) > 0 {
findCards := []int32{}
for _, card := range tmpPairs {
delC := 0
for i := 0; i < len(cpCards); i++ {
if cpCards[i] == InvalideCard {
continue
}
if int32(Value(cpCards[i])) == card && (delC < 2) { //删除2次
findCards = append(findCards, card)
delC++
cpCards = append(cpCards[:i], cpCards[i+1:]...)
i--
continue
}
}
}
if yl {
grade += yl_liandui3
} else {
grade += liandui3
}
}
}
}
//再找三连
if len(cpCards) >= 6 {
sort.Slice(cpCards, func(i, j int) bool {
if cpCards[i] > cpCards[j] {
return false
}
return true
})
map3STwin := make(map[int32]int32)
for _, card := range cpCards {
map3STwin[int32(Value(card))]++
}
Value3STwin := []int32{}
for card, num := range map3STwin {
if num >= 2 {
Value3STwin = append(Value3STwin, card)
}
}
sort.Slice(Value3STwin, func(i, j int) bool {
if Value3STwin[i] > Value3STwin[j] {
return false
}
return true
})
if len(Value3STwin) > 0 {
tmpPairs := FindOneStraightWithWidth(3, Value3STwin)
if len(tmpPairs) > 0 {
findCards := []int32{}
for _, card := range tmpPairs {
delC := 0
for i := 0; i < len(cpCards); i++ {
if cpCards[i] == InvalideCard {
continue
}
if int32(Value(cpCards[i])) == card && (delC < 2) { //删除2次
findCards = append(findCards, card)
delC++
cpCards = append(cpCards[:i], cpCards[i+1:]...)
i--
continue
}
}
}
if yl {
grade += yl_liandui3
} else {
grade += liandui3
}
}
}
}
//找8顺子
if len(cpCards) >= 8 {
del, tmpCards, _ := delStraight(cpCards, 8)
if del {
if yl {
grade += yl_shunzi8
} else {
grade += shunzi8
}
cpCards = tmpCards
}
}
// 找三张
if len(cpCards) >= 3 {
mapTriple := make(map[int32]int)
for _, card := range cpCards {
mapTriple[int32(Value(card))]++
}
tripleValues := []int32{}
for card, num := range mapTriple {
if num == 3 {
tripleValues = append(tripleValues, card)
}
}
if len(tripleValues) > 0 {
findCards := []int32{}
for _, value := range tripleValues {
delC := 0
for i := 0; i < len(cpCards); i++ {
card := cpCards[i]
if card != InvalideCard {
if Value(card) == int(value) && (delC < 3) { //删除3次
findCards = append(findCards, card)
delC++
cpCards = append(cpCards[:i], cpCards[i+1:]...)
i--
continue
}
}
}
}
if yl {
grade += len(tripleValues) * yl_sanzhang
} else {
grade += len(tripleValues) * sanzhang
}
}
}
//找7顺子
if len(cpCards) >= 7 {
del, tmpCards, _ := delStraight(cpCards, 7)
if del {
if yl {
grade += yl_shunzi7
} else {
grade += shunzi7
}
cpCards = tmpCards
}
}
//找6顺子
if len(cpCards) >= 6 {
del, tmpCards, _ := delStraight(cpCards, 6)
if del {
if yl {
grade += yl_shunzi6
} else {
grade += shunzi6
}
cpCards = tmpCards
}
}
//再找6顺子
if len(cpCards) >= 6 {
del, tmpCards, _ := delStraight(cpCards, 6)
if del {
if yl {
grade += yl_shunzi6
} else {
grade += shunzi6
}
cpCards = tmpCards
}
}
return grade
}
// 发顺子不包括2 最少3顺子
func delStraight(cards []int32, value int) (bool, []int32, []int32) {
haveNeed := false
needCards := []int32{}
if cards == nil || len(cards) < value {
return haveNeed, cards, needCards
}
mapStraights := make(map[int32]int32)
for _, card := range cards {
if card != InvalideCard && Value(card) != Card_Value_2 {
mapStraights[int32(Value(card))]++
}
}
valueStraights := []int32{}
for cardValue, _ := range mapStraights {
valueStraights = append(valueStraights, cardValue)
}
if len(valueStraights) > 0 {
sort.Slice(valueStraights, func(i, j int) bool {
if valueStraights[i] > valueStraights[j] {
return false
}
return true
})
straights := FindStraightWithWidth(value, valueStraights)
if len(straights) > 0 {
randStraight := straights[rand.Intn(len(straights))] //随机一条顺子
for _, cardValue := range randStraight {
delC := 0
for i := 0; i < len(cards); i++ {
card := cards[i]
if card == InvalideCard {
continue
}
if int32(Value(card)) == cardValue && (delC < 1) { //删除1次
delC++
needCards = append(needCards, card)
cards = append(cards[:i], cards[i+1:]...)
i--
continue
}
}
}
haveNeed = true
}
}
return haveNeed, cards, needCards
}
// 发连对不包括2 最少2顺子
func delStraightTwin(cards []int32, value int) (bool, []int32, []int32) {
haveNeed := false
needCards := []int32{}
if cards == nil || len(cards) < value {
return haveNeed, cards, needCards
}
mapStraights := make(map[int32]int32)
for _, card := range cards {
if card != InvalideCard && Value(card) != Card_Value_2 {
mapStraights[int32(Value(card))]++
}
}
valueStraights := []int32{}
for cardValue, count := range mapStraights {
if count >= 2 /*&& !common.InSliceInt32(valueStraights, cardValue)*/ {
valueStraights = append(valueStraights, cardValue)
}
}
if len(valueStraights) > 0 {
sort.Slice(valueStraights, func(i, j int) bool {
if valueStraights[i] > valueStraights[j] {
return false
}
return true
})
straights := FindStraightWithWidth(value, valueStraights)
if len(straights) > 0 {
randStraight := straights[rand.Intn(len(straights))] //随机一条顺子
for _, cardValue := range randStraight {
delC := 0
for i := 0; i < len(cards); i++ {
card := cards[i]
if card == InvalideCard {
continue
}
if int32(Value(card)) == cardValue && (delC < 2) { //删除2次
delC++
needCards = append(needCards, card)
cards = append(cards[:i], cards[i+1:]...)
i--
continue
}
}
}
haveNeed = true
}
}
return haveNeed, cards, needCards
}
func SendHandCard(poker *Poker) []int {
poker.Shuffle()
buf := poker.GetPokerBuf()
cardss := map[int][]int32{}
for i, card := range buf {
if int32(card) != InvalideCard {
index := i / 13
cardss[index] = append(cardss[index], int32(card))
}
}
type gradeInfo struct {
id int
grade int
cards []int32
}
grades := []gradeInfo{}
for i, card13 := range cardss {
cardTmp := make([]int32, 13)
copy(cardTmp, card13)
grade := GetCardsGrade(cardTmp, false)
gi := gradeInfo{
id: i,
grade: grade,
cards: card13,
}
grades = append(grades, gi)
}
sort.Slice(grades, func(i, j int) bool {
return grades[i].grade > grades[j].grade
})
//fmt.Println("grades: ", grades)
sortGrades := []int{}
for _, grade := range grades {
sortGrades = append(sortGrades, grade.grade)
}
return sortGrades
}
func MinSortCards(cs []int32) {
sort.Slice(cs, func(i, j int) bool {
vI := Value(cs[i])
vJ := Value(cs[j])
cI := Color(cs[i])
cJ := Color(cs[j])
if vI > vJ {
return false
} else if vI == vJ {
return cI < cJ
}
return true
})
}