game_sync/gamerule/tala/card.go

478 lines
9.9 KiB
Go

package tala
import (
"sort"
"strconv"
)
//牌序- K, Q, J, 10, 9, 8, 7, 6, 5, 4, 3, 2, A
//方片- 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 (
TaLaNil int = iota //nil
ColorStraight //1 同花顺
Triple //2 三张
)
// Color 黑桃0 梅花1 紅桃2 方片3
func Color(c int32) int {
return int(c) / PER_CARD_COLOR_MAX
}
func Value(c int32) int {
value := int(c+1) % PER_CARD_COLOR_MAX
if value == 0 {
value = PER_CARD_COLOR_MAX
}
return value
}
func ValueStr(c int32) string {
if c == InvalideCard {
return ""
}
str := ""
value := strconv.Itoa(Value(c))
switch Color(c) {
case 0:
str = "黑桃"
case 1:
str = "梅花"
case 2:
str = "紅桃"
case 3:
str = "方片"
}
return str + value
}
func IsStraight(cards []int32) bool { //顺子
if len(cards) < 3 || len(cards) > HandCardNum {
return false
}
tmpCards := []int{}
for _, card := range cards {
tmpCards = append(tmpCards, Value(card))
}
sort.Ints(tmpCards)
for i := 0; i < len(tmpCards)-1; i++ {
card := tmpCards[i]
nextCard := tmpCards[i+1]
if nextCard-card != 1 { //不相邻
return false
}
}
return true
}
func IsColorStraight(cards []int32) bool { //同花顺子
// 先是顺子
if !IsStraight(cards) {
return false
}
c := Color(cards[0])
for _, card := range cards {
if c != Color(card) {
return false
}
}
return true
}
func IsTriple(cards []int32) bool { //三张
if len(cards) < 3 || len(cards) > 4 { // 3张或者4张
return false
}
switch len(cards) {
case 3:
if Value(cards[0]) != Value(cards[1]) {
return false
}
if Value(cards[1]) != Value(cards[2]) {
return false
}
return true
case 4:
if Value(cards[0]) != Value(cards[1]) {
return false
}
if Value(cards[1]) != Value(cards[2]) {
return false
}
if Value(cards[2]) != Value(cards[3]) {
return false
}
return true
}
return false
}
func CanChi(cards []int32, chiCard int32, excludeCards []int32) (bool, []int32) { //可吃
chi2pPhom := []int32{chiCard}
if chiCard == InvalideCard {
return false, chi2pPhom
}
cpCards := []int32{}
for _, card := range cards {
if card != InvalideCard {
cpCards = append(cpCards, card)
}
}
if len(cpCards) == 0 {
return false, chi2pPhom
}
n := 0
tmp := []int32{}
for _, card := range cpCards {
if Value(chiCard) == Value(card) && !InSliceInt32(excludeCards, card) {
n++
tmp = append(tmp, card)
}
}
if n >= 2 { //找到两张以上牌值相同的,可以吃
for _, card := range tmp {
chi2pPhom = append(chi2pPhom, card)
}
return true, chi2pPhom
}
chi2pPhom = []int32{chiCard}
min1 := false
min2 := false
minPhom := []int32{}
mid1 := false
mid2 := false
midPhom := []int32{}
max1 := false
max2 := false
maxPhom := []int32{}
for _, card := range cpCards {
if Color(chiCard) == Color(card) && !InSliceInt32(excludeCards, card) {
//最小
if chiCard+1 == card {
minPhom = append(minPhom, card)
min1 = true
}
if chiCard+2 == card {
minPhom = append(minPhom, card)
min2 = true
}
if min1 && min2 {
for _, c := range minPhom {
chi2pPhom = append(chi2pPhom, c)
}
return true, chi2pPhom
}
//中间
if chiCard+1 == card {
midPhom = append(midPhom, card)
mid1 = true
}
if chiCard-1 == card {
midPhom = append(midPhom, card)
mid2 = true
}
if mid1 && mid2 {
for _, c := range midPhom {
chi2pPhom = append(chi2pPhom, c)
}
return true, chi2pPhom
}
//最大
if chiCard-1 == card {
maxPhom = append(maxPhom, card)
max1 = true
}
if chiCard-2 == card {
maxPhom = append(maxPhom, card)
max2 = true
}
if max1 && max2 {
for _, c := range maxPhom {
chi2pPhom = append(chi2pPhom, c)
}
return true, chi2pPhom
}
}
}
return false, chi2pPhom
}
func GetCardsValue(cards []int32) int {
cardValue := 0
for _, card := range cards {
if card != InvalideCard {
cardValue += Value(card)
}
}
return cardValue
}
// 尝试组合phom
func TryPhom(cards, chiCards []int32) ([]int32, [][]int32) { //胡
cpCards := []int32{}
phomCards := [][]int32{}
for _, card := range cards {
if card != InvalideCard {
cpCards = append(cpCards, card)
}
}
if len(cpCards) == 0 {
return cpCards, phomCards
}
cardValue := GetCardsValue(cards)
tmpPhoms := [][]int32{}
var TryOpPhom func([]int32)
TryOpPhom = func(cs []int32) {
if len(cs) == 0 {
return
}
cp := []int32{}
for _, i2 := range cs {
if i2 != InvalideCard {
cp = append(cp, i2)
}
}
//fmt.Println("===2===", cp)
phoms := needPhom(cp)
if len(phoms) != 0 {
//fmt.Println("===4===", phoms)
for _, phom := range phoms {
for _, card := range phom {
for i := 0; i < len(cp); i++ {
if cp[i] == card {
cp = append(cp[:i], cp[i+1:]...)
i--
}
}
}
tmpCp := []int32{}
for _, tmp := range cp {
tmpCp = append(tmpCp, tmp)
}
tmpPhoms = append(tmpPhoms, phom)
TryOpPhom(tmpCp)
//fmt.Println("===3===", tmpCp, tmpPhoms)
if GetCardsValue(tmpCp) < cardValue && !InSliceASliceB(tmpCp, chiCards) { //是不是最优解 //吃过的牌不能留在手牌里
cardValue = GetCardsValue(cp)
phomCards = [][]int32{}
for _, tmpPhom := range tmpPhoms {
if len(tmpPhom) > 0 {
tmp := []int32{}
for _, c := range tmpPhom {
tmp = append(tmp, c)
}
phomCards = append(phomCards, tmp)
}
}
}
cp = []int32{} //回退下 next
for _, card := range cs {
cp = append(cp, card)
}
tmpPhoms = append(tmpPhoms[:len(tmpPhoms)-1])
}
}
return
}
TryOpPhom(cpCards)
//fmt.Println("===1===", phomCards)
for _, phom := range phomCards {
for _, card := range phom {
for i, cpcard := range cpCards {
if card == cpcard {
cpCards = append(cpCards[:i], cpCards[i+1:]...)
i--
break
}
}
}
}
return cpCards, phomCards
}
// b中元素是否在a里面
func InSliceASliceB(a, b []int32) bool {
for _, bi := range b {
if InSliceInt32(a, bi) {
return true
}
}
return false
}
// 有所有的同花顺组合 或者 有所有的点数相同的组合
func needPhom(cards []int32) [][]int32 { //胡
tmps := [][]int32{}
haveColorStraights, colorStraights := needColorStraight(cards)
haveTriples, triples := needTriple(cards)
if haveColorStraights || haveTriples { //有所有的同花顺组合 或者 有所有的点数相同的组合
if haveColorStraights {
for _, straight := range colorStraights {
tmps = append(tmps, straight)
}
}
if haveTriples {
for _, triple := range triples {
tmps = append(tmps, triple)
}
}
}
return tmps
}
// 找所有相同点数的三张
func needTriple(cards []int32) (bool, [][]int32) {
haveNeed := false
needCards := [][]int32{}
if len(cards) != 0 {
mapTriple := make(map[int32][]int32)
for _, card := range cards {
if card != InvalideCard {
mapTriple[int32(Value(card))] = append(mapTriple[int32(Value(card))], card)
}
}
if len(mapTriple) > 0 {
for _, tripleCards := range mapTriple {
if len(tripleCards) == 3 {
haveNeed = true
needCards = append(needCards, tripleCards)
}
if len(tripleCards) == 4 {
haveNeed = true
needCards = append(needCards, tripleCards)
for _, card := range tripleCards {
tmps := []int32{}
for _, tmp := range tripleCards {
if card != tmp {
tmps = append(tmps, tmp)
}
}
if len(tmps) > 0 {
needCards = append(needCards, tmps)
}
}
}
}
}
}
return haveNeed, needCards
}
// 所有的同花顺
func needColorStraight(cards []int32) (bool, [][]int32) {
haveNeed := false
needCards := [][]int32{}
if len(cards) != 0 {
sliceCS := [4][]int32{} //color-card
for _, card := range cards {
if card != InvalideCard {
sliceCS[Color(card)] = append(sliceCS[Color(card)], card)
}
}
for _, colorCards := range sliceCS {
if len(colorCards) > 0 {
sort.Slice(colorCards, func(i, j int) bool {
if Value(colorCards[i]) > Value(colorCards[j]) {
return false
}
return true
})
for i := len(colorCards); i > 2; i-- {
tmps := FindStraightWithWidth(i, colorCards)
if len(tmps) > 0 {
haveNeed = true
for _, tmp := range tmps {
needCards = append(needCards, tmp)
}
}
}
}
}
}
return haveNeed, needCards
}
// 找一个固定长度的顺子 (2,3,4,5,6) 3-> [2,3,4]
func FindOneStraightWithWidth(n int, pairs []int32) []int32 {
if len(pairs) == 0 {
return nil
}
lastKey := pairs[0]
tempPair := []int32{lastKey}
if n == 1 {
return tempPair
}
for i := 1; i < len(pairs); i++ {
if pairs[i]-lastKey == 1 {
tempPair = append(tempPair, pairs[i])
} else {
tempPair = []int32{pairs[i]}
}
if len(tempPair) == n {
break
}
lastKey = pairs[i]
}
if len(tempPair) == n {
return tempPair
}
return nil
}
// 找多个固定长度的顺子(2,3,4,5,6) 3-> [[2,3,4][3,4,5][4,5,6]]
func FindStraightWithWidth(n int, pairs []int32) [][]int32 {
if len(pairs) == 0 || n < 2 {
return nil
}
var tempPairs [][]int32
lastKey := pairs[0]
tempPair := []int32{lastKey}
for i := 1; i < len(pairs); i++ {
if pairs[i]-lastKey == 1 {
tempPair = append(tempPair, pairs[i])
} else {
tempPair = []int32{pairs[i]}
}
if len(tempPair) == n {
tempPairs = append(tempPairs, tempPair)
tempPair = []int32{}
for j := n - 1; j > 0; j-- {
tempPair = append(tempPair, pairs[i-j+1])
}
}
lastKey = pairs[i]
}
return tempPairs
}
func DelSliceInt32(sl []int32, v int32) []int32 {
index := -1
for key, value := range sl {
if value == v {
index = key
break
}
}
if index != -1 {
sl = append(sl[:index], sl[index+1:]...)
}
return sl
}
func InSliceInt32(sl []int32, v int32) bool {
for _, vv := range sl {
if vv == v {
return true
}
}
return false
}