德州扑克的规则
项目实现了什么
- 5张牌的比较
- 7张牌的比较
- 7张牌+赖子的比较(最多只有一张赖子的情况)
项目的运行速度
5张牌,不算读取文件,压力测试下的速度
go test -bench=".*" -benchmem
7张牌的速度
7张加赖子的速度
我的项目结构
5张牌的实现方式
package fire
import (
"encoding/json"
"fmt"
"io/ioutil"
"time"
)
// Poker 存放 文件中比较数据的结构体
type poker struct {
Alice string `json:"alice"`
Bob string `json:"bob"`
Result int `json:"result"`
}
// Match 用于 存放读取文件的json格式数据
type Match struct {
Matches []poker `json:"matches"`
}
// CardCom用于同类型比较的函数传递参数
type cardCom struct {
cardSizeMap1 map[byte]int
cardSizeMap2 map[byte]int
max1, max2 byte
}
// SizeTranByte 对面值转译整对应的byte值 -- 方便大小比较
func SizeTranByte(card byte) (res byte) {
switch card {
case 50:
// 2
res = 0x02
case 51:
res = 0x03
case 52:
res = 0x04
case 53:
res = 0x05
case 54:
res = 0x06
case 55:
res = 0x07
case 56:
res = 0x08
case 57:
res = 0x09
case 84:
res = 0x0A
case 74:
res = 0x0B
case 81:
res = 0x0C
case 75:
res = 0x0D
case 65:
res = 0x0E
case 88:
res = 0x10
}
return
}
// ReadFile 把数据从文件中读取出来 分别放在切片中返回
func ReadFile(filename string) (alices, bobs []string, results []int) {
buf, err := ioutil.ReadFile(filename)
if err != nil {
panic(err)
}
var matches Match
err = json.Unmarshal(buf, &matches)
if err != nil {
panic(err)
}
alices = make([]string, len(matches.Matches))
bobs = make([]string, len(matches.Matches))
results = make([]int, len(matches.Matches))
for k, v := range matches.Matches {
alices[k] = v.Alice
bobs[k] = v.Bob
results[k] = v.Result
}
return
}
// JudgmentGroupNew 判断牌的类型
func JudgmentGroupNew(card []byte) (judeCardType uint8, cardSizeMap map[byte]int, resMax byte) {
cardColorMap := make(map[byte]int, 5)
cardSizeMap = make(map[byte]int, 5)
// 扫描牌 分别放好大小,花色 --key放的是花色或是面值,--value放的是出现的次数
for i, v := range card {
if i%2 == 0 {
// 存放大小
if _, ok := cardSizeMap[v]; ok {
cardSizeMap[v] ++
} else {
cardSizeMap[v] = 1
}
// 存放颜色
} else {
if _, ok := cardColorMap[v]; ok {
cardColorMap[v] ++
} else {
cardColorMap[v] = 1
}
}
}
// 获取map的长度
sizeLen := len(cardSizeMap)
colorLen := len(cardColorMap)
// 同花的时候,5个颜色一样,所以 colorLen = 1
if colorLen > 1 {
// 非同花
switch sizeLen {
case 4:
// 一对
judeCardType = 9
return
case 2: // 3带2 或是 4带1
// 遍历map value
for _, v := range cardSizeMap {
if v == 4 {
judeCardType = 3
return
}
}
judeCardType = 4
return
case 3:
// 3条 或是 两对
for _, v := range cardSizeMap {
if v == 3 {
judeCardType = 7
return
}
}
judeCardType = 8
return
case 5:
// 单牌或是顺子
isShun, max := IsShunZiNew(card)
if isShun {
resMax = max
judeCardType = 6
return
}
judeCardType = 10
return
}
} else {
// 同花 或是 同花顺
isShun, max := IsShunZiNew(card)
if isShun {
resMax = max
judeCardType = 1
} else {
judeCardType = 5
}
}
return
}
// IsShunZiNew 判断是否是顺子 返回顺子的最大值和是否是顺子
func IsShunZiNew(card []byte) (shunZi bool, max byte) {
shunZi = false
saves := make([]byte, 14)
// 把扑克牌放如slice中
for i, v := range card {
if i%2 == 0 {
switch v {
case 50:
saves[1] = v
case 51:
saves[2] = v
case 52:
saves[3] = v
case 53:
saves[4] = v
case 54:
saves[5] = v
case 55:
saves[6] = v
case 56:
saves[7] = v
case 57:
saves[8] = v
case 84:
saves[9] = v
case 74:
saves[10] = v
case 81:
saves[11] = v
case 75:
saves[12] = v
case 65:
saves[13] = v
saves[0] = v
default:
fmt.Println("无法解析的扑克牌", "card --v=", v)
}
}
}
// 判断数组是否连续 倒序遍历
sum := 0
for i := len(saves) - 1; i >= 0; i-- {
// slice有值
if saves[i] != 0x00 {
sum++
} else {
sum = 0
}
// 5个连续
if sum >= 5 {
shunZi = true
max = saves[i+4] // 返回顺子的最大值
return
}
}
return
}
// QuickSortByte 快排 对字节 逆序
func QuickSortByte(bs []byte) []byte {
if len(bs) <= 1 {
return bs
}
splitdata := bs[0] // 第一个数据
low := make([]byte, 0, 0) // 比我小的数据
hight := make([]byte, 0, 0) // 比我大的数据
mid := make([]byte, 0, 0) // 与我一样大的数据
mid = append(mid, splitdata) // 加入一个
for i := 1; i < len(bs); i++ {
if bs[i] > splitdata {
low = append(low, bs[i])
} else if bs[i] < splitdata {
hight = append(hight, bs[i])
} else {
mid = append(mid, bs[i])
}
}
low, hight = QuickSortByte(low), QuickSortByte(hight)
myarr := append(append(low, mid...), hight...)
return myarr
}
// SingleCardCompareSizeNew 同类型单牌比较 返回值是比较结果 0是平局 1是前面赢 2是后面赢
func (com *cardCom) SingleCardCompareSizeNew() (result int) {
cardSizeSlice1 := make([]byte, len(com.cardSizeMap1))
cardSizeSlice2 := make([]byte, len(com.cardSizeMap1))
// 遍历map,把面值放到slice中
i := 0
for k := range com.cardSizeMap1 {
cardSizeSlice1[i] = SizeTranByte(k)
i++
}
i = 0
for k := range com.cardSizeMap2 {
cardSizeSlice2[i] = SizeTranByte(k)
i++
}
// 比较5张牌的面值
result = SingleCardSizeCom(5, cardSizeSlice1, cardSizeSlice2)
return
}
// SingleCardSizeCom 对比单牌 大小0是平局 1是前面赢 2是后面赢
func SingleCardSizeCom(comLen int, cardSizeSlice1, cardSizeSlice2 []byte) (result int) {
// 对传进来的slice逆序排序
cardSizeSlice1 = QuickSortByte(cardSizeSlice1)
cardSizeSlice2 = QuickSortByte(cardSizeSlice2)
// 一个个对比
for i := 0; i < comLen; i++ {
if cardSizeSlice1[i] > cardSizeSlice2[i] {
return 1
} else if cardSizeSlice1[i] < cardSizeSlice2[i] {
return 2
}
}
return 0
}
// aPairComNew 同类型一对比较 0是平局 1是前面赢 2是后面赢
func (com *cardCom) aPairComNew() (result int) {
// 用于存放单牌的面值
cardSizeSlice1 := make([]byte, len(com.cardSizeMap1))
cardSizeSlice2 := make([]byte, len(com.cardSizeMap1))
// 用于存放对子的面值
var pair1 byte
var pair2 byte
i := 0
for k, v := range com.cardSizeMap1 {
k = SizeTranByte(k) // 对牌子转译,才可以比较大小
if v == 2 {
pair1 = k
} else {
cardSizeSlice1[i] = k
i++
}
}
i = 0
for k, v := range com.cardSizeMap2 {
if v == 2 {
pair2 = SizeTranByte(k)
} else {
cardSizeSlice2[i] = SizeTranByte(k)
i++
}
}
// 先比较对子的大小
if pair1 > pair2 {
return 1
} else if pair1 < pair2 {
return 2
} else {
// 再单牌大小
result = SingleCardSizeCom(3, cardSizeSlice1, cardSizeSlice2)
return
}
}
// twoPairComNew 同类型的两对比较 0是平局 1是前面赢 2是后面赢
func (com *cardCom) twoPairComNew() (result int) {
// 用于存放两对的牌子
pairs1 := make([]byte, 2)
pairs2 := make([]byte, 2)
// 用于存放单牌
var val1 byte
var val2 byte
i := 0
for k, v := range com.cardSizeMap1 {
k = SizeTranByte(k) // 转译面值成可以比较的
if v == 2 {
pairs1[i] = k
i++
} else {
val1 = k
}
}
i = 0
for k, v := range com.cardSizeMap2 {
k = SizeTranByte(k)
if v == 2 {
pairs2[i] = k
i++
} else {
val2 = k
}
}
// 比较对子的大小
result = SingleCardSizeCom(2, pairs1, pairs2)
if result != 0 {
return
}
// 再比较单牌的大小
if val1 > val2 {
return 1
} else if val1 < val2 {
return 2
} else {
return 0
}
}
// onlyThreeComNew 同类型的三条比较 0是平局 1是前面赢 2是后面赢
func (com *cardCom) onlyThreeComNew() (result int) {
// 用于存放单牌的面值
cardSizeSlice1 := make([]byte, len(com.cardSizeMap1))
cardSizeSlice2 := make([]byte, len(com.cardSizeMap1))
// 用于存放三条的面值
var three1 byte
var three2 byte
i := 0
for k, v := range com.cardSizeMap1 {
k = SizeTranByte(k)
cardSizeSlice1[i] = k
if v == 3 {
three1 = k
} else {
i++
}
}
i = 0
for k, v := range com.cardSizeMap2 {
k = SizeTranByte(k)
cardSizeSlice2[i] = k
if v == 3 {
three2 = k
} else {
i++
}
}
// 先比较三条的面值
if three1 > three2 {
return 1
} else if three1 < three2 {
return 2
} else {
// 再比较单牌的
result = SingleCardSizeCom(2, cardSizeSlice1, cardSizeSlice2)
return
}
}
// onlyShunZiNew 同类型顺子的比较 0是平局 1是前面赢 2是后面赢
func (com *cardCom) onlyShunZiNew() (result int) {
// max 是顺子的最大的牌,只要比较这张牌就行了
if com.max1 > com.max2 {
return 1
} else if com.max1 < com.max2 {
return 2
}
return 0
}
// onlySameFlowerNew 是同类型同花的比较 0是平局 1是前面赢 2是后面赢
func (com *cardCom) onlySameFlowerNew() (result int) {
// 同类型同花 只要比较牌面值最大的,可以看着是单牌比较面值大小
result = com.SingleCardCompareSizeNew()
return
}
// straightFlushNew 同类型同花顺比较 0是平局 1是前面赢 2是后面赢
func (com *cardCom) straightFlushNew() (result int) {
// 同类型同花顺比较,可以看作顺子之间比较
return com.onlyShunZiNew()
}
// fourComNew 同类型4条比较 0是平局 1是前面赢 2是后面赢
func (com *cardCom) fourComNew() (result int) {
// 存放四条的面值
var four1 byte
var four2 byte
// 存放单牌的面值
var val1 byte
var val2 byte
for k, v := range com.cardSizeMap1 {
k = SizeTranByte(k) // 对面值转译成可以比较的
if v == 4 {
four1 = k
} else {
val1 = k
}
}
for k, v := range com.cardSizeMap2 {
k = SizeTranByte(k) // 对面值转译成可以比较的
if v == 4 {
four2 = k
} else {
val2 = k
}
}
// 先比较4条大小
if four1 > four2 {
return 1
} else if four1 < four2 {
return 2
} else {
// 再比较单牌的大小
if val1 > val2 {
return 1
} else if val1 < val2 {
return 2
} else {
return 0
}
}
}
// threeAndTwoNew 同类型3带2比较 0是平局 1是前面赢 2是后面赢
func (com *cardCom) threeAndTwoNew() (result int) {
// 存放3条的面值
var three1 byte
var three2 byte
// 存放对子的面值
var two1 byte
var two2 byte
for k, v := range com.cardSizeMap1 {
if v == 3 {
three1 = SizeTranByte(k)
} else {
two1 = SizeTranByte(k)
}
}
for k, v := range com.cardSizeMap2 {
if v == 3 {
three2 = SizeTranByte(k)
} else {
two2 = SizeTranByte(k)
}
}
// 先对比3条的面值
if three1 > three2 {
return 1
} else if three1 < three2 {
return 2
} else {
// 再对比对子的面值
if two1 > two2 {
return 1
} else if two1 < two2 {
return 2
} else {
return 0
}
}
}
// PokerMan 5张遍历判断 文件扑克牌的函数
func PokerMan() {
file := "../resources/match_result.json"
alices, bobs, results := ReadFile(file)
t1 := time.Now()
k := 0
// 遍历全部对比
for i := 0; i < len(alices); i++ {
result := -1
// 分牌型
val1, cardSizesMap1, max1 := JudgmentGroupNew([]byte(alices[i]))
val2, cardSizesMap2, max2 := JudgmentGroupNew([]byte(bobs[i]))
if val1 < val2 {
result = 1
} else if val1 > val2 {
result = 2
} else {
// 牌型相同的处理情况
// ...
cardCom := cardCom{
cardSizeMap1: cardSizesMap1,
cardSizeMap2: cardSizesMap2,
max1: max1,
max2: max2,
}
switch val1 {
case 10:
// 同类型下的单张大牌比较
result = cardCom.SingleCardCompareSizeNew()
case 9:
// 同类型的一对
result = cardCom.aPairComNew()
case 8:
// 同类型两对
result = cardCom.twoPairComNew()
case 7:
// 同类型三条
result = cardCom.onlyThreeComNew()
case 6:
// 同类型顺子
result = cardCom.onlyShunZiNew()
case 5:
// 同类型同花
result = cardCom.onlySameFlowerNew()
case 4:
// 同类型3带2
result = cardCom.threeAndTwoNew()
case 3:
// 同类型四条
result = cardCom.fourComNew()
case 1: // 同类型同花顺
result = cardCom.straightFlushNew()
}
// 最后比较结果
}
// 打印判断出错的信息
if result != results[i] {
k++
fmt.Printf("[%#v]5张判断错误--->alice:%#v,bob:%#v<----- ===>文档的结果:%#v, 我的结果:%#v <==\n", k, alices[i], bobs[i], results[i], result)
}
}
t2 := time.Now()
fmt.Println("time--->", t2.Sub(t1))
}
7张牌的实现方式
package seven
import (
"NewPocker/fire"
"fmt"
"time"
)
// Seven 调用同类型比较函数们的参数传入
type Seven struct {
// 存放面值的map
cardSizeMap1, cardSizeMap2 map[byte]int
cardColorMap1, cardColorMap2 map[byte]int
max1, max2 byte
card1, card2 []byte
}
// IsShunZi 判断是不是顺子,并且返回顺子的最大值 传进来的已经转译好的面值
func IsShunZi(seq []byte) (flag bool, max byte) {
flag = false
saves := make([]byte, 14)
// 遍历序列, 存放入对应的序列
for _, v := range seq {
switch v {
case 0x02:
saves[1] = v
case 0x03:
saves[2] = v
case 0x04:
saves[3] = v
case 0x05:
saves[4] = v
case 0x06:
saves[5] = v
case 0x07:
saves[6] = v
case 0x08:
saves[7] = v
case 0x09:
saves[8] = v
case 0x0A:
saves[9] = v
case 0x0B:
saves[10] = v
case 0x0C:
saves[11] = v
case 0x0D:
saves[12] = v
case 0x0E:
saves[13] = v
saves[0] = v
default:
fmt.Println("无法解析的扑克牌", "card --v=", v)
}
}
// 判断数组是否连续
sum := 0
for i := len(saves) - 1; i >= 0; i-- {
if saves[i] != 0x00 {
// slice有值
sum++
} else {
// 没值重置
sum = 0
}
// 判断到有连续5个
if sum >= 5 {
flag = true
max = saves[i+4] // 返回顺子最大值
return
}
}
return
}
// JudgmentGroup 判断牌型
func JudgmentGroup(card []byte) (cardType uint8, cardSizeMap, cardColorMap map[byte]int, resMax byte) {
cardColorMap = make(map[byte]int, 7)
cardSizeMap = make(map[byte]int, 7)
// 扫描牌 分别放好大小,花色
for i, v := range card {
if i%2 == 0 {
// 大小 判断map是否有值,也就是之前是否出现过 最终 key是面值,value是该面值出现的次数
if _, ok := cardSizeMap[v]; ok {
cardSizeMap[v] ++
} else {
cardSizeMap[v] = 1
}
// 颜色 同上
} else {
if _, ok := cardColorMap[v]; ok {
cardColorMap[v] ++
} else {
cardColorMap[v] = 1
}
}
}
// 获取map的长度
sizeLen := len(cardSizeMap)
flag := false
for _, v := range cardColorMap {
if v >= 5 { // 5个花色一样的
flag = true
break
}
}
if flag {
// 已经是同花
// 然后判断是不是顺子
seq := SameFlowerSeq(cardColorMap, card)
isShun, max := IsShunZi(seq)
if isShun {
// 同花顺
resMax = max
cardType = 1
return
}
// 单纯的同花
cardType = 5
return
}
// 然后再根据存放面值的map长度来判断类型
switch sizeLen {
case 7: // 不是顺子 就是7个单牌
// 判断是不是顺子
if isShun, max := fire.IsShunZiNew(card); isShun {
cardType = 6 // 顺子的类型
resMax = max
return
}
cardType = 10 // 单牌的类型
return
case 6: // 1对 或是 顺子
// 判断是不是顺子
if isShun, max := fire.IsShunZiNew(card); isShun {
resMax = max
cardType = 6
return
}
// 返回一对的类型
cardType = 9
return
case 5: // 可以是顺子 两对 或是 3条
// 顺子大先判断是不是顺子
if isShun, max := fire.IsShunZiNew(card); isShun {
resMax = max
cardType = 6
return
}
// cardSizeMap 的key是面值 value是该面值出现的次数
// 然后判断是不是3条
for _, v := range cardSizeMap {
if v == 3 {
cardType = 7 // 3条
return
}
}
// 2对
cardType = 8
return
case 4: // 可以是 4条 3带2 两对(3个对子)
for _, v := range cardSizeMap {
if v == 4 {
// 4条
cardType = 3
return
} else if v == 3 {
// 3条
cardType = 4
return
}
}
// 剩下两对
cardType = 8
return
case 3: // 4条(4条1对) 3带2(3条和3条, 3条和两对)
for _, v := range cardSizeMap {
if v == 4 {
cardType = 3
return
}
}
cardType = 4
return
case 2: // 4条(4条和3条)
cardType = 3
return
}
return
}
// SingleCard 同类型单牌比较 返回值0是平局 1是前面赢 2是后面赢
func (sevenCom *Seven) SingleCard() (result int) {
// 用于存放面值大小的slice
cardSizeSlice1 := make([]byte, len(sevenCom.cardSizeMap1))
cardSizeSlice2 := make([]byte, len(sevenCom.cardSizeMap2))
i := 0
for k := range sevenCom.cardSizeMap1 {
cardSizeSlice1[i] = fire.SizeTranByte(k)
i++
}
i = 0
for k := range sevenCom.cardSizeMap2 {
cardSizeSlice2[i] = fire.SizeTranByte(k)
i++
}
result = fire.SingleCardSizeCom(5, cardSizeSlice1, cardSizeSlice2)
return
}
// APair 同类型一对的比较 返回值0是平局 1是前面赢 2是后面赢
func (sevenCom *Seven) APair() (result int) {
// 存放 单牌的面值的slice
cardSizeSlice1 := make([]byte, len(sevenCom.cardSizeMap1))
cardSizeSlice2 := make([]byte, len(sevenCom.cardSizeMap1))
// 存放对子的面值
var val1 byte
var val2 byte
i := 0
for k, v := range sevenCom.cardSizeMap1 {
k = fire.SizeTranByte(k)
if v == 2 {
val1 = k
continue
}
cardSizeSlice1[i] = k
i++
}
i = 0
for k, v := range sevenCom.cardSizeMap2 {
k = fire.SizeTranByte(k)
if v == 2 {
val2 = k
continue
}
cardSizeSlice2[i] = k
i++
}
// 先对比对子的面值大小
if val1 > val2 {
return 1
} else if val1 < val2 {
return 2
}
// 然后对比各自单牌中最大的三种
result = fire.SingleCardSizeCom(3, cardSizeSlice1, cardSizeSlice2)
return
}
// TwoPair 同类型两对的比较 返回值0是平局 1是前面赢 2是后面赢
func (sevenCom *Seven) TwoPair() (result int) {
// 存放对子的slice
pairs1 := make([]byte, 3)
pairs2 := make([]byte, 3)
// 存放单牌的slice
vals1 := make([]byte, 3)
vals2 := make([]byte, 3)
j := 0
i := 0
for k, v := range sevenCom.cardSizeMap1 {
k = fire.SizeTranByte(k)
if v == 2 {
pairs1[i] = k
i++
} else {
vals1[j] = k
j++
}
}
i = 0
j = 0
for k, v := range sevenCom.cardSizeMap2 {
k = fire.SizeTranByte(k)
if v == 2 {
pairs2[i] = k
i++
} else {
vals2[j] = k
j++
}
}
// 对对子序列排序 逆序
pairs1 = fire.QuickSortByte(pairs1)
pairs2 = fire.QuickSortByte(pairs2)
// 对子比较 只是比较最大的两个,因为有可能是3对的
for i := 0; i < 2; i++ {
if pairs1[i] > pairs2[i] {
return 1
} else if pairs1[i] < pairs2[i] {
return 2
}
}
// 对剩余的单牌排序
vals1 = fire.QuickSortByte(vals1)
vals2 = fire.QuickSortByte(vals2)
// 跟各自的对子slice的第三个比较, 因为可能存在第三个对子
if vals1[0] < pairs1[2] {
vals1[0] = pairs1[2]
}
if vals2[0] < pairs2[2] {
vals2[0] = pairs2[2]
}
// 对于剩下的单牌比较,只比较最大的一个
if vals1[0] > vals2[0] {
return 1
} else if vals1[0] < vals2[0] {
return 2
} else {
return 0
}
}
// OnlyThree 同类型3条比较 返回值0是平局 1是前面赢 2是后面赢
func (sevenCom *Seven) OnlyThree() (result int) {
// 存放单牌的slice
cardSizeSlice1 := make([]byte, len(sevenCom.cardSizeMap1))
cardSizeSlice2 := make([]byte, len(sevenCom.cardSizeMap2))
// 存放3条的面值
var three1 byte
var three2 byte
i := 0
for k, v := range sevenCom.cardSizeMap1 {
k = fire.SizeTranByte(k)
if v == 3 {
three1 = k
} else {
cardSizeSlice1[i] = k
i++
}
}
i = 0
for k, v := range sevenCom.cardSizeMap2 {
k = fire.SizeTranByte(k)
if v == 3 {
three2 = k
} else {
cardSizeSlice2[i] = k
i++
}
}
// 比较3条的面值大小
if three1 > three2 {
return 1
} else if three1 < three2 {
return 2
} else {
// 比较张单牌的大小
result = fire.SingleCardSizeCom(2, cardSizeSlice1, cardSizeSlice2)
return
}
}
// OnlyShunZi 同类型顺子的比较 返回值0是平局 1是前面赢 2是后面赢
func (sevenCom *Seven) OnlyShunZi() (result int) {
max1 := fire.SizeTranByte(sevenCom.max1)
max2 := fire.SizeTranByte(sevenCom.max2)
if max1 > max2 {
return 1
} else if max1 < max2 {
return 2
} else {
return 0
}
}
// SameFlowerSeq 找到同花对应的面值序列
func SameFlowerSeq(cardColorMap map[byte]int, card []byte) (sizeSlice []byte) {
// 存放同花的花色
var color byte
sliceLen := 0
for k, v := range cardColorMap {
if v >= 5 {
color = k // 记录颜色
sliceLen = v // 颜色出现的次数
break
}
}
sizeSlice = make([]byte, sliceLen) // 大小为颜色出现的次数
j := 0
for i := 1; i < len(card); i += 2 {
if card[i] == color {
sizeSlice[j] = fire.SizeTranByte(card[i-1]) // 取颜色前一个 也就是面值
j++
}
}
return
}
// onlySameFlower 同类型同花的比较 返回值0是平局 1是前面赢 2是后面赢
func (sevenCom *Seven) onlySameFlower() (result int) {
// 得到同花对应的面值序列
sizeSlice1 := SameFlowerSeq(sevenCom.cardColorMap1, sevenCom.card1)
sizeSlice2 := SameFlowerSeq(sevenCom.cardColorMap2, sevenCom.card2)
// 只对比各自最大的五个
result = fire.SingleCardSizeCom(5, sizeSlice1, sizeSlice2)
return
}
// ThreeAndTwo 同类型3带2的比较 返回值0是平局 1是前面赢 2是后面赢
func (sevenCom *Seven) ThreeAndTwo() (result int) {
// 存放 3条的面值
threes1 := make([]byte, 2)
threes2 := make([]byte, 2)
// 存放对子的面值
twos1 := make([]byte, 2)
twos2 := make([]byte, 2)
i := 0
j := 0
for k, v := range sevenCom.cardSizeMap1 {
k = fire.SizeTranByte(k) // 对面值进行转译 才可以大小比较
if v == 3 {
threes1[i] = k
i++
} else if v == 2 {
twos1[j] = k
j++
}
}
i = 0
j = 0
for k, v := range sevenCom.cardSizeMap2 {
k = fire.SizeTranByte(k)
if v == 3 {
threes2[i] = k
i++
} else if v == 2 {
twos2[j] = k
j++
}
}
// 对3条的序列进行倒序排序 可能出现2个3条的情况
threes1 = fire.QuickSortByte(threes1)
threes2 = fire.QuickSortByte(threes2)
// 对比3条
if threes1[0] > threes2[0] {
return 1
} else if threes1[0] < threes2[0] {
return 2
} else {
// 对对子的序列进行倒序排序
twos1 = fire.QuickSortByte(twos1)
twos2 = fire.QuickSortByte(twos2)
// 可能出现2个3条的情况
if twos1[0] < threes1[1] {
twos1[0] = threes1[1]
}
if twos2[0] < threes2[1] {
twos2[0] = threes2[1]
}
// 对比对子
if twos1[0] > twos2[0] {
return 1
} else if twos1[0] < twos2[0] {
return 2
} else {
return 0
}
}
}
// FourCom 同类型4条的比较 返回值0是平局 1是前面赢 2是后面赢
func (sevenCom *Seven) FourCom() (result int) {
// 存放非4条的牌面值
cardSizeSlice1 := make([]byte, len(sevenCom.cardSizeMap1))
cardSizeSlice2 := make([]byte, len(sevenCom.cardSizeMap2))
// 存放4条的面值
var four1 byte
var four2 byte
i := 0
for k, v := range sevenCom.cardSizeMap1 {
k = fire.SizeTranByte(k) // 面值转换才可以用于比较
if v == 4 {
four1 = k
} else {
cardSizeSlice1[i] = k
i++
}
}
i = 0
for k, v := range sevenCom.cardSizeMap2 {
k = fire.SizeTranByte(k)
if v == 4 {
four2 = k
} else {
cardSizeSlice2[i] = k
i++
}
}
// 先比较4条的大小
if four1 > four2 {
return 1
} else if four1 < four2 {
return 2
} else {
// 再比较各自单牌中最大一张
result = fire.SingleCardSizeCom(1, cardSizeSlice1, cardSizeSlice2)
return
}
}
// straightFlush 同类型同花顺的比较 返回值0是平局 1是前面赢 2是后面赢
func (sevenCom *Seven) straightFlush() (result int) {
// 同类型同花顺比较可以看作是同类型顺子比较
return sevenCom.OnlyShunZi()
}
// PokerMan 7张的主函数
func PokerMan() {
file := "../resources/seven_cards_with_ghost.json"
alices := make([]string, 1024)
bobs := make([]string, 1024)
results := make([]int, 1024)
alices, bobs, results = fire.ReadFile(file)
t1 := time.Now()
k := 0
for i := 0; i < len(alices); i++ {
result := -1
val1, cardSizesMap1, cardColorMap1, max1 := JudgmentGroup([]byte(alices[i]))
val2, cardSizesMap2, cardColorMap2, max2 := JudgmentGroup([]byte(bobs[i]))
seven := &Seven{
cardSizeMap1: cardSizesMap1,
cardSizeMap2: cardSizesMap2,
cardColorMap1: cardColorMap1,
cardColorMap2: cardColorMap2,
card1: []byte(alices[i]),
card2: []byte(bobs[i]),
max1: max1,
max2: max2,
}
// 牌型比较
if val1 < val2 {
result = 1
} else if val1 > val2 {
result = 2
} else {
// 同牌型下的比较
switch val1 {
case 1:
// 同花顺
seven.straightFlush()
case 3:
// 四条
result = seven.FourCom()
case 4:
// 3带2
result = seven.ThreeAndTwo()
case 5:
// 同花
result = seven.onlySameFlower()
case 6:
// 顺子
result = seven.OnlyShunZi()
case 7:
// 3条
result = seven.OnlyThree()
case 8:
// 2对
result = seven.TwoPair()
case 9:
// 一对
result = seven.APair()
case 10:
// 单牌
result = seven.SingleCard()
}
}
if results[i] != result {
fmt.Printf("[%#v]7张判断错误--->alice:%#v,bob:%#v<----- ===>文档的结果:%#v, 我的结果:%#v <==\n",
k, alices[i], bobs[i], results[i], result)
k++
}
}
t2 := time.Now()
fmt.Println("time----->>>", t2.Sub(t1))
}
7张加赖子的实现方式
package sevenJoker
import (
"NewPocker/fire"
"fmt"
"time"
)
// comSevenJoker 调用同类型比较函数传入的参数
type comSevenJoker struct {
cardSizeMap1, cardSizeMap2 map[byte]int
resCard1, resCard2 byte
joker1, joker2 int // 记录癞子数量
}
// SameFlowerSeq 找到同花对应的面值序列
func SameFlowerSeq(cardColorMap map[byte]int, card []byte, joker int) (sizeSlice []byte) {
// 存放同花的花色
var color byte
sliceLen := 0
for k, v := range cardColorMap {
if v+joker >= 5 { // joker是癞子假设癞子变花色
color = k
sliceLen = v + joker
break
}
}
sizeSlice = make([]byte, sliceLen)
j := 0
for i := 1; i < len(card); i += 2 {
if card[i] == color {
sizeSlice[j] = fire.SizeTranByte(card[i-1]) // 花色前一个是它对应的面值,转译成可以比较的
j++
}
}
// 将所有jock都变A , 因为同花下比较单牌 癞子变最大的单牌
for joker > 0 && sliceLen != 0 {
sizeSlice[j] = 0x0E
j++
joker--
}
return
}
// IsShunZi 判断是不是顺子,返回顺子的一个最大面值 传进来的已经转译好的面值
func IsShunZi(seq []byte, joker int) (shunZi bool, max byte) {
saves := make([]byte, 15)
// 遍历seq,把它对应放到saves中,安位入座
for _, v := range seq {
switch v {
case 0x02:
saves[1] = v
case 0x03:
saves[2] = v
case 0x04:
saves[3] = v
case 0x05:
saves[4] = v
case 0x06:
saves[5] = v
case 0x07:
saves[6] = v
case 0x08:
saves[7] = v
case 0x09:
saves[8] = v
case 0x0A:
saves[9] = v
case 0x0B:
saves[10] = v
case 0x0C:
saves[11] = v
case 0x0D:
saves[12] = v
case 0x0E:
saves[13] = v
saves[0] = v
case 0x10:
saves[14] = v
default:
fmt.Println("IsShunZi say 无法解析的扑克牌", "card --v=", v)
}
}
sum := 0
// 判断数组是否连续
if joker < 1 {
// 没有癞子的顺子
for i := len(saves) - 1; i >= 0; i-- {
if saves[i] != 0x00 {
sum++
} else {
sum = 0
}
if sum >= 5 {
shunZi = true
max = saves[i+4]
return
}
}
} else {
tmp := joker
sum = 0
for i := len(saves) - 1; i >= 0; i-- {
if saves[i] != 0 {
sum++
} else if joker > 0 {
joker--
sum++
} else {
// 这里是回退到一开始的下一个
i = i + sum - joker
// 重置 joker 和sum
joker = tmp
sum = 0
}
if sum >= 5 {
// 是顺子
max = saves[i+4]
if max == 0 {
// 那么癞子就变成这个下标对应的值
max = IndexTranByte(i + 4)
}
shunZi = true
return
}
}
}
return
}
// IndexTranByte 当是顺子时,癞子去补顺子的最大值调用这个函数去转换下标对应的面值
func IndexTranByte(index int) (b byte) {
switch index {
// 这个癞子补充的值,不可能是很前面的
case 4:
b = 0x05
case 5:
b = 0x06
case 6:
b = 0x07
case 7:
b = 0x08
case 8:
b = 0x09
case 9:
b = 0x0A
case 10:
b = 0x0B
case 11:
b = 0x0C
case 12:
b = 0x0D
case 13:
b = 0x0E
case 14:
b = 0x10
default:
fmt.Println("IsShunZi say 无法解析的扑克牌", "card --b=", b)
}
return
}
// IsShunZiNoTran 判断是不是顺子,并且返回顺子的最大牌面值 传进来的card还没有转译
func IsShunZiNoTran(card []byte, joker int) (shunZi bool, max byte) {
shunZi = false
saves := make([]byte, 14)
// 将面值对号入座
for i, v := range card {
if i%2 == 0 {
switch v {
case 50:
saves[1] = v
case 51:
saves[2] = v
case 52:
saves[3] = v
case 53:
saves[4] = v
case 54:
saves[5] = v
case 55:
saves[6] = v
case 56:
saves[7] = v
case 57:
saves[8] = v
case 84:
saves[9] = v
case 74:
saves[10] = v
case 81:
saves[11] = v
case 75:
saves[12] = v
case 65:
saves[13] = v
saves[0] = v
case 88:
// continue
// fmt.Println("88")
default:
fmt.Println("无法解析的扑克牌", "card --v=", v)
}
}
}
// 下面判断数组是否连续
sum := 0
if joker < 1 {
// 没有癞子的顺子
for i := len(saves) - 1; i >= 0; i-- {
if saves[i] != 0x00 {
sum++
} else {
sum = 0
}
if sum >= 5 {
shunZi = true
max = saves[i+4]
return
}
}
} else {
tmp := joker
sum = 0
for i := len(saves) - 1; i >= 0; i-- {
if saves[i] != 0 {
sum++
} else if joker > 0 {
joker--
sum++
} else {
// 这里是回退到一开始的下一个
i = i + sum - joker
joker = tmp
sum = 0
}
if sum >= 5 {
// 是顺子
max = saves[i+4]
if max == 0 {
// 需要癞子来补充这个最大的面值
max = IndexFindByte(i + 4)
}
shunZi = true
return
}
}
}
return
}
// IndexFindByte 下标转成面值的byte
func IndexFindByte(index int) (b byte) {
switch index {
case 5:
b = 54
case 6:
b = 55
case 7:
b = 56
case 8:
b = 57
case 9:
b = 84
case 10:
b = 74
case 11:
b = 81
case 12:
b = 75
case 13:
b = 65
case 0:
b = 65
case 88:
case 1:
b = 50
case 2:
b = 51
case 3:
b = 52
case 4:
b = 53
default:
fmt.Println("无法解析的下标", "card --index=", index)
}
return
}
// judgmentGroup 判断牌型 传进来的参数:面值+花色
func judgmentGroup(card [] byte) (cardType uint8, cardSizeMap, cardColorMap map[byte]int, resCard byte, joker int) {
// 对传进来的牌分拣成 面值 花色
cardColorMap = make(map[byte]int, 7)
cardSizeMap = make(map[byte]int, 7)
// 扫描牌 分别放好大小,花色
for i, v := range card {
if i%2 == 0 {
// 大小
// 判断是否有癞子
if v == 88 {
joker++ // 记录多少个癞子但是不放入map中
continue
}
if _, ok := cardSizeMap[v]; ok {
cardSizeMap[v]++
} else {
cardSizeMap[v] = 1
}
// 颜色
} else {
if v == 110 { // 癞子的花色,不作处理
continue
}
if _, ok := cardColorMap[v]; ok {
cardColorMap[v]++
} else {
cardColorMap[v] = 1
}
}
}
sizeLen := len(cardSizeMap)
flag := false
for _, v := range cardColorMap {
if v+joker >= 5 {
flag = true
break
}
}
if flag {
// 同花
// 判断是不是顺子
seq := SameFlowerSeq(cardColorMap, card, joker)
isShun, max := IsShunZi(seq[0:len(seq)-joker], joker)
if isShun {
// 同花顺
resCard = max
cardType = 1
return
}
if joker == 0 {
cardType = 5
return
}
// 有癞子的情况下,是同花,也有可能是变成4条 或是 三带2 它们都比同花大
i := 0
for _, v := range cardSizeMap {
if v+joker == 4 {
// 4 条
cardType = 3
return
} else if v+joker == 3 {
i++
}
}
if i == 2 {
// 3带2
cardType = 4
return
}
cardType = 5
return
}
// 不是同花
// 根据面值的map长度判断
switch sizeLen {
case 7: // 单牌也没有癞子
// 判断是不是顺子
if isShun, max := IsShunZiNoTran(card, joker); isShun {
cardType = 6
resCard = max
return
}
cardType = 10
return
case 6: // 可能 顺子 单牌+癞子 或是 一对
if isShun, max := IsShunZiNoTran(card, joker); isShun {
resCard = max
cardType = 6
return
}
// 就算有癞子也是一对, 因为癞子不放入map,map len为6 如果有癞子的话,其他牌是单牌
cardType = 9
return
case 5: // 顺子 3条 或是 两对
// 判断是不是顺子
if isShun, max := IsShunZiNoTran(card, joker); isShun {
resCard = max
cardType = 6
return
}
// 有癞子的五张牌一定是3条
if joker > 0 {
cardType = 7
return
}
for _, v := range cardSizeMap {
if v == 3 {
// 3条
cardType = 7
return
}
}
// 2对
cardType = 8
return
case 4: // 因为最多只有一个癞子 就可能出现4条 3带2 或是 2对(3个对子) 有癞子的话也不组顺子,因为可以组4条或是3带2比顺子大
i := 0
j := 0
for _, v := range cardSizeMap {
if v+joker == 4 {
// 4条
cardType = 3
return
} else if v+joker == 3 {
// 有可能是本来有两对再加一个癞子
i++
} else if v == 2 {
j++
}
}
if j < 2 {
cardType = 4
return
}
// 这里的j=3,也就是三对并且没有癞子的
cardType = 8
return
case 3: // 不是3带2 就是4条了
for _, v := range cardSizeMap {
if v+joker == 4 {
cardType = 3
return
}
}
cardType = 4
return
case 2: // 只能是4条
cardType = 3
return
}
return
}
// straightFlush 同类型同花顺比较 --1
func (sevenJoker *comSevenJoker) straightFlush() (result int) {
// 比较顺子最大的牌
if sevenJoker.resCard1 > sevenJoker.resCard2 {
return 1
} else if sevenJoker.resCard1 < sevenJoker.resCard2 {
return 2
} else {
return 0
}
}
// fourCom 同类型四条比较 --3
func (sevenJoker *comSevenJoker) fourCom() (result int) {
// 存放单牌的slice
cardSizeSlice1 := make([]byte, len(sevenJoker.cardSizeMap1))
cardSizeSlice2 := make([]byte, len(sevenJoker.cardSizeMap2))
// 存放4条的面值
var four1 byte
var four2 byte
i := 0
for k, v := range sevenJoker.cardSizeMap1 {
k = fire.SizeTranByte(k)
if v+sevenJoker.joker1 == 4 {
if four1 < k {
four1 = k
}
} else {
cardSizeSlice1[i] = k
i++
}
}
i = 0
for k, v := range sevenJoker.cardSizeMap2 {
k = fire.SizeTranByte(k)
if v+sevenJoker.joker2 == 4 {
if four2 < k {
four2 = k
}
} else {
cardSizeSlice2[i] = k
i++
}
}
if four1 > four2 {
return 1
} else if four1 < four2 {
return 2
} else {
// 比较单牌中最大的一张
result = fire.SingleCardSizeCom(1, cardSizeSlice1, cardSizeSlice2)
return
}
}
// threeAndTwo同类型3带2比较 --4
func (sevenJoker *comSevenJoker) threeAndTwo() (result int) {
// 存放3条的slice
threes1 := make([]byte, 3)
threes2 := make([]byte, 3)
// 存放对子的slice
twos1 := make([]byte, 3)
twos2 := make([]byte, 3)
i := 0
j := 0
for k, v := range sevenJoker.cardSizeMap1 {
k = fire.SizeTranByte(k)
if v+sevenJoker.joker1 == 3 {
threes1[i] = k
i++
} else if v == 2 {
twos1[j] = k
j++
}
}
i = 0
j = 0
for k, v := range sevenJoker.cardSizeMap2 {
k = fire.SizeTranByte(k)
if v+sevenJoker.joker2 == 3 {
threes2[i] = k
i++
} else if v == 2 {
twos2[j] = k
j++
}
}
// 对3条排序
threes1 = fire.QuickSortByte(threes1)
threes2 = fire.QuickSortByte(threes2)
// 因为有可能出现 2个3条
if threes1[0] > threes2[0] {
return 1
} else if threes1[0] < threes2[0] {
return 2
}
// 对 对子排序
twos1 = fire.QuickSortByte(twos1)
twos2 = fire.QuickSortByte(twos2)
// 当两个3条的时候, 对子就没有值,那么对子的最大应该是3条的最小
if twos1[0] < threes1[1] {
twos1[0] = threes1[1]
}
if twos2[0] < threes2[1] {
twos2[0] = threes2[1]
}
if twos1[0] > twos2[0] {
return 1
} else if twos1[0] < twos2[0] {
return 2
} else {
return 0
}
}
// onlyFlush 同类型同花比较 --5 1
func (sevenJoker *comSevenJoker) onlyFlush(cardColorMap1, cardColorMap2 map[byte]int, card1, card2 []byte) (result int) {
// 找到同花对应的面值序列
sizeSlice1 := SameFlowerSeq(cardColorMap1, card1, sevenJoker.joker1)
sizeSlice2 := SameFlowerSeq(cardColorMap2, card2, sevenJoker.joker2)
// 这个序列可以大于5个, 所以只比较各自最大的五个
result = fire.SingleCardSizeCom(5, sizeSlice1, sizeSlice2)
return
}
// OnlyShunZi 同类型顺子比较 --6
func (sevenJoker *comSevenJoker) OnlyShunZi() (result int) {
v1 := fire.SizeTranByte(sevenJoker.resCard1)
v2 := fire.SizeTranByte(sevenJoker.resCard2)
if v1 > v2 {
return 1
} else if v1 < v2 {
return 2
} else {
return 0
}
}
// onlyThree 同类型3条比较 --7
func (sevenJoker *comSevenJoker) onlyThree() (result int) {
// 存放单牌的slice
cardSizeSlice1 := make([]byte, len(sevenJoker.cardSizeMap1))
cardSizeSlice2 := make([]byte, len(sevenJoker.cardSizeMap2))
// 存放3条的面值
var three1 byte
var three2 byte
i := 0
for k, v := range sevenJoker.cardSizeMap1 {
k = fire.SizeTranByte(k)
if v+sevenJoker.joker1 == 3 {
three1 = k
} else {
cardSizeSlice1[i] = k
i++
}
}
i = 0
for k, v := range sevenJoker.cardSizeMap2 {
k = fire.SizeTranByte(k)
if v+sevenJoker.joker2 == 3 {
three2 = k
} else {
cardSizeSlice2[i] = k
i++
}
}
if three1 > three2 {
return 1
} else if three1 < three2 {
return 2
} else {
// 比较各自单牌中最大的两个
result = fire.SingleCardSizeCom(2, cardSizeSlice1, cardSizeSlice2)
return
}
}
// TwoPair 同类型两对比较 --8
func (sevenJoker *comSevenJoker) TwoPair() (result int) {
// 记录对子的slice
pairs1 := make([]byte, 3)
pairs2 := make([]byte, 3)
// 记录单牌的slice
vals1 := make([]byte, 3)
vals2 := make([]byte, 3)
j := 0
i := 0
for k, v := range sevenJoker.cardSizeMap1 {
k = fire.SizeTranByte(k)
if v+sevenJoker.joker1 == 2 {
pairs1[i] = k
i++
} else {
vals1[j] = k
j++
}
}
i = 0
j = 0
for k, v := range sevenJoker.cardSizeMap2 {
k = fire.SizeTranByte(k)
if v+sevenJoker.joker2 == 2 {
pairs2[i] = k
i++
} else {
vals2[j] = k
j++
}
}
// 对 对子 逆序列排序
pairs1 = fire.QuickSortByte(pairs1)
pairs2 = fire.QuickSortByte(pairs2)
// 因为可能出现3个对子,选择选择最大两个比较
for i := 0; i < 2; i++ {
if pairs1[i] > pairs2[i] {
return 1
} else if pairs1[i] < pairs2[i] {
return 2
}
}
// 对单牌序列排序
vals1 = fire.QuickSortByte(vals1)
vals2 = fire.QuickSortByte(vals2)
// 如果出现3个对子,让最小的对子跟最大的单牌比较
if vals1[0] < pairs1[2] {
vals1[0] = pairs1[2]
}
if vals2[0] < pairs2[2] {
vals2[0] = pairs2[2]
}
// 比较单牌最大
if vals1[0] > vals2[0] {
return 1
} else if vals1[0] < vals2[0] {
return 2
}
return 0
}
// OnePair 同类型一对比较 --9
func (sevenJoker *comSevenJoker) OnePair() (result int) {
cardSizeSlice1 := make([]byte, len(sevenJoker.cardSizeMap1))
cardSizeSlice2 := make([]byte, len(sevenJoker.cardSizeMap1))
var val1 byte
var val2 byte
i := 0
for k, v := range sevenJoker.cardSizeMap1 {
k = fire.SizeTranByte(k)
if v == 2 {
val1 = k
continue
}
cardSizeSlice1[i] = k
i++
}
i = 0
for k, v := range sevenJoker.cardSizeMap2 {
k = fire.SizeTranByte(k)
if v == 2 {
val2 = k
continue
}
cardSizeSlice2[i] = k
i++
}
cardSizeSlice1 = fire.QuickSortByte(cardSizeSlice1)
cardSizeSlice2 = fire.QuickSortByte(cardSizeSlice2)
// 癞子组成的对子
if val1 == 0 {
val1 = cardSizeSlice1[0]
}
if val2 == 0 {
val2 = cardSizeSlice2[0]
// fmt.Println("val22222222")
}
if val1 > val2 {
return 1
} else if val1 < val2 {
return 2
}
comLen := 3
// 单牌一个个对比
for i := 0; i < comLen; i++ {
if cardSizeSlice1[i+sevenJoker.joker1] > cardSizeSlice2[i+sevenJoker.joker2] {
return 1
} else if cardSizeSlice1[i+sevenJoker.joker1] < cardSizeSlice2[i+sevenJoker.joker2] {
return 2
}
}
return 0
}
// SingleCard 同类型单牌比较 --10
func (sevenJoker *comSevenJoker) SingleCard() (result int) {
// 存放单牌的slice
cardSizeSlice1 := make([]byte, len(sevenJoker.cardSizeMap1))
cardSizeSlice2 := make([]byte, len(sevenJoker.cardSizeMap2))
i := 0
for k := range sevenJoker.cardSizeMap1 {
cardSizeSlice1[i] = fire.SizeTranByte(k)
i++
}
i = 0
for k := range sevenJoker.cardSizeMap2 {
cardSizeSlice2[i] = fire.SizeTranByte(k)
i++
}
// 对比各自最大的5张
result = fire.SingleCardSizeCom(5, cardSizeSlice1, cardSizeSlice2)
return
}
// PokerMan 7张加癞子的主函数
func PokerMan() {
filePath := "../resources/seven_cards_with_ghost.result.json"
alices, bobs, results := fire.ReadFile(filePath)
t1 := time.Now()
k := 0
for i := 0; i < len(alices); i++ {
result := -1
// 先判断各自的牌型
cardType1, cardSizesMap1, cardColorMap1, max1, joker1 := judgmentGroup([]byte(alices[i]))
cardType2, cardSizesMap2, cardColorMap2, max2, joker2 := judgmentGroup([]byte(bobs[i]))
if cardType1 < cardType2 {
result = 1
} else if cardType1 > cardType2 {
result = 2
} else {
csj := &comSevenJoker{
cardSizeMap1: cardSizesMap1,
cardSizeMap2: cardSizesMap2,
resCard1: max1,
resCard2: max2,
joker1: joker1,
joker2: joker2,
}
// 同类型比较
switch cardType1 {
case 1:
// 同花顺
result = csj.straightFlush()
case 3:
// 4条
result = csj.fourCom()
case 4:
// 3带2
result = csj.threeAndTwo()
case 5:
// 同花
result = csj.onlyFlush(cardColorMap1, cardColorMap2, []byte(alices[i]), []byte(bobs[i]))
case 6:
// 顺子
result = csj.OnlyShunZi()
case 7:
// 3条
result = csj.onlyThree()
case 8:
// 两对
result = csj.TwoPair()
case 9:
// 一对
result = csj.OnePair()
case 10:
// 单牌
result = csj.SingleCard()
}
}
if result != results[i] {
k++
fmt.Println("[", k, "]"+"判断有误,alice=", alices[i], " bob=", bobs[i], " 我的结果:", result, " 文档的结果:", results[i])
}
}
t2 := time.Now()
fmt.Println("time--->", t2.Sub(t1))
}
关于规范化
go语言有golint指令和go vet指令
有关于效率的问题
暴力破解的运行时间太长了,建议:
1.用素数去求,把所有可能性的牌的素数乘积求出来存入表中,然后根据当前的手牌去查询表
利用的是 [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41] 素数相乘的值都是唯一值的这个特点
2.用位运算,首先是牌的储存,2~~A,一共13张牌,用一个14位的二进制区间来储存手牌,比如2-A,将表示为:11111111111110,出现的牌位为1,没出现的位为0,第一位是也是放A,由于德州扑克里面A 2 3 4 5是最小的顺子。
这样的储存方式除了省空间外还有什么优势呢?
我们顺子的判断为例:例如顺子10JQKA,在二进制区间将表示为11111000000000,叫它S
现在我们有手牌2 3 10 J Q K A,那么它的二进制表示是11111000000110,叫它T
那么T&S==S的话,就可以说明T包含一个顺子,并且顺子是10JQKA
S转化为10进制的话是15872
类似的我们将所有可能的顺子预先保存好,如下表(10用T表示):
TJQKA | 9TJQK | 89TJQ | 789TJ | 6789T | 56789 | 45678 | 34567 | 23456 | A2345 |
15872 | 7936 | 3968 | 1984 | 992 | 496 | 248 | 124 | 62 | 31 |