德州扑克比较大小的go语言暴力实现

2023-11-21 07:10

本文主要是介绍德州扑克比较大小的go语言暴力实现,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

德州扑克的规则

在这里插入图片描述

项目实现了什么

  • 5张牌的比较
  • 7张牌的比较
  • 7张牌+赖子的比较(最多只有一张赖子的情况)

项目的运行速度

5张牌,不算读取文件,压力测试下的速度
go test -bench=".*" -benchmem在这里插入图片描述
7张牌的速度

在这里插入图片描述
7张加赖子的速度
在这里插入图片描述

我的项目结构

在这里插入图片描述

5张牌的实现方式

package fireimport ("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]intcardSizeMap2 map[byte]intmax1, max2   byte
}// SizeTranByte 对面值转译整对应的byte值  -- 方便大小比较
func SizeTranByte(card byte) (res byte) {switch card {case 50:// 2res = 0x02case 51:res = 0x03case 52:res = 0x04case 53:res = 0x05case 54:res = 0x06case 55:res = 0x07case 56:res = 0x08case 57:res = 0x09case 84:res = 0x0Acase 74:res = 0x0Bcase 81:res = 0x0Ccase 75:res = 0x0Dcase 65:res = 0x0Ecase 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 Matcherr = 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.Alicebobs[k] = v.Bobresults[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 = 1if colorLen > 1 {// 非同花switch sizeLen {case 4:// 一对judeCardType = 9returncase 2: // 3带2  或是 4带1// 遍历map valuefor _, v := range cardSizeMap {if v == 4 {judeCardType = 3return}}judeCardType = 4returncase 3:// 3条 或是 两对for _, v := range cardSizeMap {if v == 3 {judeCardType = 7return}}judeCardType = 8returncase 5:// 单牌或是顺子isShun, max := IsShunZiNew(card)if isShun {resMax = maxjudeCardType = 6return}judeCardType = 10return}} else {// 同花 或是 同花顺isShun, max := IsShunZiNew(card)if isShun {resMax = maxjudeCardType = 1} else {judeCardType = 5}}return}// IsShunZiNew 判断是否是顺子 返回顺子的最大值和是否是顺子
func IsShunZiNew(card []byte) (shunZi bool, max byte) {shunZi = falsesaves := make([]byte, 14)// 把扑克牌放如slice中for i, v := range card {if i%2 == 0 {switch v {case 50:saves[1] = vcase 51:saves[2] = vcase 52:saves[3] = vcase 53:saves[4] = vcase 54:saves[5] = vcase 55:saves[6] = vcase 56:saves[7] = vcase 57:saves[8] = vcase 84:saves[9] = vcase 74:saves[10] = vcase 81:saves[11] = vcase 75:saves[12] = vcase 65:saves[13] = vsaves[0] = vdefault:fmt.Println("无法解析的扑克牌", "card --v=", v)}}}// 判断数组是否连续 倒序遍历sum := 0for i := len(saves) - 1; i >= 0; i-- {// slice有值if saves[i] != 0x00 {sum++} else {sum = 0}// 5个连续if sum >= 5 {shunZi = truemax = 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 := 0for k := range com.cardSizeMap1 {cardSizeSlice1[i] = SizeTranByte(k)i++}i = 0for 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 bytevar pair2 bytei := 0for k, v := range com.cardSizeMap1 {k = SizeTranByte(k) // 对牌子转译,才可以比较大小if v == 2 {pair1 = k} else {cardSizeSlice1[i] = ki++}}i = 0for 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 bytevar val2 bytei := 0for k, v := range com.cardSizeMap1 {k = SizeTranByte(k) // 转译面值成可以比较的if v == 2 {pairs1[i] = ki++} else {val1 = k}}i = 0for k, v := range com.cardSizeMap2 {k = SizeTranByte(k)if v == 2 {pairs2[i] = ki++} 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 bytevar three2 bytei := 0for k, v := range com.cardSizeMap1 {k = SizeTranByte(k)cardSizeSlice1[i] = kif v == 3 {three1 = k} else {i++}}i = 0for k, v := range com.cardSizeMap2 {k = SizeTranByte(k)cardSizeSlice2[i] = kif 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 bytevar four2 byte// 存放单牌的面值var val1 bytevar val2 bytefor 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 bytevar three2 byte// 存放对子的面值var two1 bytevar two2 bytefor 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带2result = 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 sevenimport ("NewPocker/fire""fmt""time"
)// Seven 调用同类型比较函数们的参数传入
type Seven struct {// 存放面值的mapcardSizeMap1, cardSizeMap2   map[byte]intcardColorMap1, cardColorMap2 map[byte]intmax1, max2                   bytecard1, card2                 []byte
}// IsShunZi 判断是不是顺子,并且返回顺子的最大值  传进来的已经转译好的面值
func IsShunZi(seq []byte) (flag bool, max byte) {flag = falsesaves := make([]byte, 14)// 遍历序列, 存放入对应的序列for _, v := range seq {switch v {case 0x02:saves[1] = vcase 0x03:saves[2] = vcase 0x04:saves[3] = vcase 0x05:saves[4] = vcase 0x06:saves[5] = vcase 0x07:saves[6] = vcase 0x08:saves[7] = vcase 0x09:saves[8] = vcase 0x0A:saves[9] = vcase 0x0B:saves[10] = vcase 0x0C:saves[11] = vcase 0x0D:saves[12] = vcase 0x0E:saves[13] = vsaves[0] = vdefault:fmt.Println("无法解析的扑克牌", "card --v=", v)}}// 判断数组是否连续sum := 0for i := len(saves) - 1; i >= 0; i-- {if saves[i] != 0x00 {// slice有值sum++} else {// 没值重置sum = 0}// 判断到有连续5个if sum >= 5 {flag = truemax = 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 := falsefor _, v := range cardColorMap {if v >= 5 { // 5个花色一样的flag = truebreak}}if flag {// 已经是同花// 然后判断是不是顺子seq := SameFlowerSeq(cardColorMap, card)isShun, max := IsShunZi(seq)if isShun {// 同花顺resMax = maxcardType = 1return}// 单纯的同花cardType = 5return}// 然后再根据存放面值的map长度来判断类型switch sizeLen {case 7: // 不是顺子 就是7个单牌// 判断是不是顺子if isShun, max := fire.IsShunZiNew(card); isShun {cardType = 6 // 顺子的类型resMax = maxreturn}cardType = 10 // 单牌的类型returncase 6: // 1对 或是 顺子// 判断是不是顺子if isShun, max := fire.IsShunZiNew(card); isShun {resMax = maxcardType = 6return}// 返回一对的类型cardType = 9returncase 5: // 可以是顺子 两对 或是 3条// 顺子大先判断是不是顺子if isShun, max := fire.IsShunZiNew(card); isShun {resMax = maxcardType = 6return}// cardSizeMap 的key是面值 value是该面值出现的次数// 然后判断是不是3条for _, v := range cardSizeMap {if v == 3 {cardType = 7 // 3条return}}// 2对cardType = 8returncase 4: // 可以是 4条 3带2  两对(3个对子)for _, v := range cardSizeMap {if v == 4 {// 4条cardType = 3return} else if v == 3 {// 3条cardType = 4return}}// 剩下两对cardType = 8returncase 3: // 4条(4条1对) 3带2(3条和3条, 3条和两对)for _, v := range cardSizeMap {if v == 4 {cardType = 3return}}cardType = 4returncase 2: // 4条(4条和3条)cardType = 3return}return}// SingleCard 同类型单牌比较 返回值0是平局 1是前面赢 2是后面赢
func (sevenCom *Seven) SingleCard() (result int) {// 用于存放面值大小的slicecardSizeSlice1 := make([]byte, len(sevenCom.cardSizeMap1))cardSizeSlice2 := make([]byte, len(sevenCom.cardSizeMap2))i := 0for k := range sevenCom.cardSizeMap1 {cardSizeSlice1[i] = fire.SizeTranByte(k)i++}i = 0for 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) {// 存放 单牌的面值的slicecardSizeSlice1 := make([]byte, len(sevenCom.cardSizeMap1))cardSizeSlice2 := make([]byte, len(sevenCom.cardSizeMap1))// 存放对子的面值var val1 bytevar val2 bytei := 0for k, v := range sevenCom.cardSizeMap1 {k = fire.SizeTranByte(k)if v == 2 {val1 = kcontinue}cardSizeSlice1[i] = ki++}i = 0for k, v := range sevenCom.cardSizeMap2 {k = fire.SizeTranByte(k)if v == 2 {val2 = kcontinue}cardSizeSlice2[i] = ki++}// 先对比对子的面值大小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) {// 存放对子的slicepairs1 := make([]byte, 3)pairs2 := make([]byte, 3)// 存放单牌的slicevals1 := make([]byte, 3)vals2 := make([]byte, 3)j := 0i := 0for k, v := range sevenCom.cardSizeMap1 {k = fire.SizeTranByte(k)if v == 2 {pairs1[i] = ki++} else {vals1[j] = kj++}}i = 0j = 0for k, v := range sevenCom.cardSizeMap2 {k = fire.SizeTranByte(k)if v == 2 {pairs2[i] = ki++} else {vals2[j] = kj++}}// 对对子序列排序  逆序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) {// 存放单牌的slicecardSizeSlice1 := make([]byte, len(sevenCom.cardSizeMap1))cardSizeSlice2 := make([]byte, len(sevenCom.cardSizeMap2))// 存放3条的面值var three1 bytevar three2 bytei := 0for k, v := range sevenCom.cardSizeMap1 {k = fire.SizeTranByte(k)if v == 3 {three1 = k} else {cardSizeSlice1[i] = ki++}}i = 0for k, v := range sevenCom.cardSizeMap2 {k = fire.SizeTranByte(k)if v == 3 {three2 = k} else {cardSizeSlice2[i] = ki++}}// 比较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 bytesliceLen := 0for k, v := range cardColorMap {if v >= 5 {color = k    // 记录颜色sliceLen = v // 颜色出现的次数break}}sizeSlice = make([]byte, sliceLen) // 大小为颜色出现的次数j := 0for 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 := 0j := 0for k, v := range sevenCom.cardSizeMap1 {k = fire.SizeTranByte(k) // 对面值进行转译 才可以大小比较if v == 3 {threes1[i] = ki++} else if v == 2 {twos1[j] = kj++}}i = 0j = 0for k, v := range sevenCom.cardSizeMap2 {k = fire.SizeTranByte(k)if v == 3 {threes2[i] = ki++} else if v == 2 {twos2[j] = kj++}}// 对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 bytevar four2 bytei := 0for k, v := range sevenCom.cardSizeMap1 {k = fire.SizeTranByte(k) // 面值转换才可以用于比较if v == 4 {four1 = k} else {cardSizeSlice1[i] = ki++}}i = 0for k, v := range sevenCom.cardSizeMap2 {k = fire.SizeTranByte(k)if v == 4 {four2 = k} else {cardSizeSlice2[i] = ki++}}// 先比较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 := 0for i := 0; i < len(alices); i++ {result := -1val1, 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带2result = 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 sevenJokerimport ("NewPocker/fire""fmt""time"
)// comSevenJoker 调用同类型比较函数传入的参数
type comSevenJoker struct {cardSizeMap1, cardSizeMap2 map[byte]intresCard1, resCard2         bytejoker1, joker2             int // 记录癞子数量
}// SameFlowerSeq 找到同花对应的面值序列
func SameFlowerSeq(cardColorMap map[byte]int, card []byte, joker int) (sizeSlice []byte) {// 存放同花的花色var color bytesliceLen := 0for k, v := range cardColorMap {if v+joker >= 5 { // joker是癞子假设癞子变花色color = ksliceLen = v + jokerbreak}}sizeSlice = make([]byte, sliceLen)j := 0for 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] = 0x0Ej++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] = vcase 0x03:saves[2] = vcase 0x04:saves[3] = vcase 0x05:saves[4] = vcase 0x06:saves[5] = vcase 0x07:saves[6] = vcase 0x08:saves[7] = vcase 0x09:saves[8] = vcase 0x0A:saves[9] = vcase 0x0B:saves[10] = vcase 0x0C:saves[11] = vcase 0x0D:saves[12] = vcase 0x0E:saves[13] = vsaves[0] = vcase 0x10:saves[14] = vdefault: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 = truemax = saves[i+4]return}}} else {tmp := jokersum = 0for i := len(saves) - 1; i >= 0; i-- {if saves[i] != 0 {sum++} else if joker > 0 {joker--sum++} else {// 这里是回退到一开始的下一个i = i + sum - joker// 重置 joker 和sumjoker = tmpsum = 0}if sum >= 5 {// 是顺子max = saves[i+4]if max == 0 {// 那么癞子就变成这个下标对应的值max = IndexTranByte(i + 4)}shunZi = truereturn}}}return
}// IndexTranByte 当是顺子时,癞子去补顺子的最大值调用这个函数去转换下标对应的面值
func IndexTranByte(index int) (b byte) {switch index {// 这个癞子补充的值,不可能是很前面的case 4:b = 0x05case 5:b = 0x06case 6:b = 0x07case 7:b = 0x08case 8:b = 0x09case 9:b = 0x0Acase 10:b = 0x0Bcase 11:b = 0x0Ccase 12:b = 0x0Dcase 13:b = 0x0Ecase 14:b = 0x10default:fmt.Println("IsShunZi say 无法解析的扑克牌", "card --b=", b)}return
}// IsShunZiNoTran 判断是不是顺子,并且返回顺子的最大牌面值 传进来的card还没有转译
func IsShunZiNoTran(card []byte, joker int) (shunZi bool, max byte) {shunZi = falsesaves := make([]byte, 14)// 将面值对号入座for i, v := range card {if i%2 == 0 {switch v {case 50:saves[1] = vcase 51:saves[2] = vcase 52:saves[3] = vcase 53:saves[4] = vcase 54:saves[5] = vcase 55:saves[6] = vcase 56:saves[7] = vcase 57:saves[8] = vcase 84:saves[9] = vcase 74:saves[10] = vcase 81:saves[11] = vcase 75:saves[12] = vcase 65:saves[13] = vsaves[0] = vcase 88:// continue// fmt.Println("88")default:fmt.Println("无法解析的扑克牌", "card --v=", v)}}}// 下面判断数组是否连续sum := 0if joker < 1 {// 没有癞子的顺子for i := len(saves) - 1; i >= 0; i-- {if saves[i] != 0x00 {sum++} else {sum = 0}if sum >= 5 {shunZi = truemax = saves[i+4]return}}} else {tmp := jokersum = 0for i := len(saves) - 1; i >= 0; i-- {if saves[i] != 0 {sum++} else if joker > 0 {joker--sum++} else {// 这里是回退到一开始的下一个i = i + sum - jokerjoker = tmpsum = 0}if sum >= 5 {// 是顺子max = saves[i+4]if max == 0 {// 需要癞子来补充这个最大的面值max = IndexFindByte(i + 4)}shunZi = truereturn}}}return
}// IndexFindByte 下标转成面值的byte
func IndexFindByte(index int) (b byte) {switch index {case 5:b = 54case 6:b = 55case 7:b = 56case 8:b = 57case 9:b = 84case 10:b = 74case 11:b = 81case 12:b = 75case 13:b = 65case 0:b = 65case 88:case 1:b = 50case 2:b = 51case 3:b = 52case 4:b = 53default: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 := falsefor _, v := range cardColorMap {if v+joker >= 5 {flag = truebreak}}if flag {// 同花// 判断是不是顺子seq := SameFlowerSeq(cardColorMap, card, joker)isShun, max := IsShunZi(seq[0:len(seq)-joker], joker)if isShun {// 同花顺resCard = maxcardType = 1return}if joker == 0 {cardType = 5return}// 有癞子的情况下,是同花,也有可能是变成4条 或是 三带2 它们都比同花大i := 0for _, v := range cardSizeMap {if v+joker == 4 {// 4 条cardType = 3return} else if v+joker == 3 {i++}}if i == 2 {// 3带2cardType = 4return}cardType = 5return}// 不是同花// 根据面值的map长度判断switch sizeLen {case 7: // 单牌也没有癞子// 判断是不是顺子if isShun, max := IsShunZiNoTran(card, joker); isShun {cardType = 6resCard = maxreturn}cardType = 10returncase 6: // 可能 顺子 单牌+癞子 或是 一对if isShun, max := IsShunZiNoTran(card, joker); isShun {resCard = maxcardType = 6return}// 就算有癞子也是一对, 因为癞子不放入map,map len为6 如果有癞子的话,其他牌是单牌cardType = 9returncase 5: // 顺子 3条 或是 两对// 判断是不是顺子if isShun, max := IsShunZiNoTran(card, joker); isShun {resCard = maxcardType = 6return}// 有癞子的五张牌一定是3条if joker > 0 {cardType = 7return}for _, v := range cardSizeMap {if v == 3 {// 3条cardType = 7return}}// 2对cardType = 8returncase 4: // 因为最多只有一个癞子 就可能出现4条  3带2 或是 2对(3个对子) 有癞子的话也不组顺子,因为可以组4条或是3带2比顺子大i := 0j := 0for _, v := range cardSizeMap {if v+joker == 4 {// 4条cardType = 3return} else if v+joker == 3 {//  有可能是本来有两对再加一个癞子i++} else if v == 2 {j++}}if j < 2 {cardType = 4return}// 这里的j=3,也就是三对并且没有癞子的cardType = 8returncase 3: // 不是3带2 就是4条了for _, v := range cardSizeMap {if v+joker == 4 {cardType = 3return}}cardType = 4returncase 2: // 只能是4条cardType = 3return}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) {// 存放单牌的slicecardSizeSlice1 := make([]byte, len(sevenJoker.cardSizeMap1))cardSizeSlice2 := make([]byte, len(sevenJoker.cardSizeMap2))// 存放4条的面值var four1 bytevar four2 bytei := 0for k, v := range sevenJoker.cardSizeMap1 {k = fire.SizeTranByte(k)if v+sevenJoker.joker1 == 4 {if four1 < k {four1 = k}} else {cardSizeSlice1[i] = ki++}}i = 0for k, v := range sevenJoker.cardSizeMap2 {k = fire.SizeTranByte(k)if v+sevenJoker.joker2 == 4 {if four2 < k {four2 = k}} else {cardSizeSlice2[i] = ki++}}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条的slicethrees1 := make([]byte, 3)threes2 := make([]byte, 3)// 存放对子的slicetwos1 := make([]byte, 3)twos2 := make([]byte, 3)i := 0j := 0for k, v := range sevenJoker.cardSizeMap1 {k = fire.SizeTranByte(k)if v+sevenJoker.joker1 == 3 {threes1[i] = ki++} else if v == 2 {twos1[j] = kj++}}i = 0j = 0for k, v := range sevenJoker.cardSizeMap2 {k = fire.SizeTranByte(k)if v+sevenJoker.joker2 == 3 {threes2[i] = ki++} else if v == 2 {twos2[j] = kj++}}// 对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) {// 存放单牌的slicecardSizeSlice1 := make([]byte, len(sevenJoker.cardSizeMap1))cardSizeSlice2 := make([]byte, len(sevenJoker.cardSizeMap2))// 存放3条的面值var three1 bytevar three2 bytei := 0for k, v := range sevenJoker.cardSizeMap1 {k = fire.SizeTranByte(k)if v+sevenJoker.joker1 == 3 {three1 = k} else {cardSizeSlice1[i] = ki++}}i = 0for k, v := range sevenJoker.cardSizeMap2 {k = fire.SizeTranByte(k)if v+sevenJoker.joker2 == 3 {three2 = k} else {cardSizeSlice2[i] = ki++}}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) {// 记录对子的slicepairs1 := make([]byte, 3)pairs2 := make([]byte, 3)// 记录单牌的slicevals1 := make([]byte, 3)vals2 := make([]byte, 3)j := 0i := 0for k, v := range sevenJoker.cardSizeMap1 {k = fire.SizeTranByte(k)if v+sevenJoker.joker1 == 2 {pairs1[i] = ki++} else {vals1[j] = kj++}}i = 0j = 0for k, v := range sevenJoker.cardSizeMap2 {k = fire.SizeTranByte(k)if v+sevenJoker.joker2 == 2 {pairs2[i] = ki++} else {vals2[j] = kj++}}// 对 对子 逆序列排序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 bytevar val2 bytei := 0for k, v := range sevenJoker.cardSizeMap1 {k = fire.SizeTranByte(k)if v == 2 {val1 = kcontinue}cardSizeSlice1[i] = ki++}i = 0for k, v := range sevenJoker.cardSizeMap2 {k = fire.SizeTranByte(k)if v == 2 {val2 = kcontinue}cardSizeSlice2[i] = ki++}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) {// 存放单牌的slicecardSizeSlice1 := make([]byte, len(sevenJoker.cardSizeMap1))cardSizeSlice2 := make([]byte, len(sevenJoker.cardSizeMap2))i := 0for k := range sevenJoker.cardSizeMap1 {cardSizeSlice1[i] = fire.SizeTranByte(k)i++}i = 0for 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 := 0for 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带2result = 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 |

项目的github地址

下载可以直接运行

这篇关于德州扑克比较大小的go语言暴力实现的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/400681

相关文章

C语言中联合体union的使用

本文编辑整理自: http://bbs.chinaunix.net/forum.php?mod=viewthread&tid=179471 一、前言 “联合体”(union)与“结构体”(struct)有一些相似之处。但两者有本质上的不同。在结构体中,各成员有各自的内存空间, 一个结构变量的总长度是各成员长度之和。而在“联合”中,各成员共享一段内存空间, 一个联合变量

C++对象布局及多态实现探索之内存布局(整理的很多链接)

本文通过观察对象的内存布局,跟踪函数调用的汇编代码。分析了C++对象内存的布局情况,虚函数的执行方式,以及虚继承,等等 文章链接:http://dev.yesky.com/254/2191254.shtml      论C/C++函数间动态内存的传递 (2005-07-30)   当你涉及到C/C++的核心编程的时候,你会无止境地与内存管理打交道。 文章链接:http://dev.yesky

大语言模型(LLMs)能够进行推理和规划吗?

大语言模型(LLMs),基本上是经过强化训练的 n-gram 模型,它们在网络规模的语言语料库(实际上,可以说是我们文明的知识库)上进行了训练,展现出了一种超乎预期的语言行为,引发了我们的广泛关注。从训练和操作的角度来看,LLMs 可以被认为是一种巨大的、非真实的记忆库,相当于为我们所有人提供了一个外部的系统 1(见图 1)。然而,它们表面上的多功能性让许多研究者好奇,这些模型是否也能在通常需要系

通过SSH隧道实现通过远程服务器上外网

搭建隧道 autossh -M 0 -f -D 1080 -C -N user1@remotehost##验证隧道是否生效,查看1080端口是否启动netstat -tuln | grep 1080## 测试ssh 隧道是否生效curl -x socks5h://127.0.0.1:1080 -I http://www.github.com 将autossh 设置为服务,隧道开机启动

时序预测 | MATLAB实现LSTM时间序列未来多步预测-递归预测

时序预测 | MATLAB实现LSTM时间序列未来多步预测-递归预测 目录 时序预测 | MATLAB实现LSTM时间序列未来多步预测-递归预测基本介绍程序设计参考资料 基本介绍 MATLAB实现LSTM时间序列未来多步预测-递归预测。LSTM是一种含有LSTM区块(blocks)或其他的一种类神经网络,文献或其他资料中LSTM区块可能被描述成智能网络单元,因为

vue项目集成CanvasEditor实现Word在线编辑器

CanvasEditor实现Word在线编辑器 官网文档:https://hufe.club/canvas-editor-docs/guide/schema.html 源码地址:https://github.com/Hufe921/canvas-editor 前提声明: 由于CanvasEditor目前不支持vue、react 等框架开箱即用版,所以需要我们去Git下载源码,拿到其中两个主

android一键分享功能部分实现

为什么叫做部分实现呢,其实是我只实现一部分的分享。如新浪微博,那还有没去实现的是微信分享。还有一部分奇怪的问题:我QQ分享跟QQ空间的分享功能,我都没配置key那些都是原本集成就有的key也可以实现分享,谁清楚的麻烦详解下。 实现分享功能我们可以去www.mob.com这个网站集成。免费的,而且还有短信验证功能。等这分享研究完后就研究下短信验证功能。 开始实现步骤(新浪分享,以下是本人自己实现

基于Springboot + vue 的抗疫物质管理系统的设计与实现

目录 📚 前言 📑摘要 📑系统流程 📚 系统架构设计 📚 数据库设计 📚 系统功能的具体实现    💬 系统登录注册 系统登录 登录界面   用户添加  💬 抗疫列表展示模块     区域信息管理 添加物资详情 抗疫物资列表展示 抗疫物资申请 抗疫物资审核 ✒️ 源码实现 💖 源码获取 😁 联系方式 📚 前言 📑博客主页:

探索蓝牙协议的奥秘:用ESP32实现高质量蓝牙音频传输

蓝牙(Bluetooth)是一种短距离无线通信技术,广泛应用于各种电子设备之间的数据传输。自1994年由爱立信公司首次提出以来,蓝牙技术已经经历了多个版本的更新和改进。本文将详细介绍蓝牙协议,并通过一个具体的项目——使用ESP32实现蓝牙音频传输,来展示蓝牙协议的实际应用及其优点。 蓝牙协议概述 蓝牙协议栈 蓝牙协议栈是蓝牙技术的核心,定义了蓝牙设备之间如何进行通信。蓝牙协议

人工和AI大语言模型成本对比 ai语音模型

这里既有AI,又有生活大道理,无数渺小的思考填满了一生。 上一专题搭建了一套GMM-HMM系统,来识别连续0123456789的英文语音。 但若不是仅针对数字,而是所有普通词汇,可能达到十几万个词,解码过程将非常复杂,识别结果组合太多,识别结果不会理想。因此只有声学模型是完全不够的,需要引入语言模型来约束识别结果。让“今天天气很好”的概率高于“今天天汽很好”的概率,得到声学模型概率高,又符合表达