652 lines
13 KiB
Go
652 lines
13 KiB
Go
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
|
||
})
|
||
}
|