上一篇文章序数了关于使用索引查表法进行麻将胡牌判定,这篇文章,我们将会对胡牌的番型进行计算,这里的番型指的是国标下的麻将番型,文章中的代码,暂时只考虑了二人麻将(只有万牌和字牌),想要通用,可以按着同样的方法进行扩展。
国标二人麻将番型表
88番
番型 | 胡牌方式 | 示例 |
---|
大四喜 | 胡牌时,牌里有4组风刻子(杠)加一对将牌组成的牌型。(不计门风刻、圈风刻、小四喜、三风刻、碰碰胡、幺九刻) |  |
大三元 | 胡牌时,牌里有中、发、白3副刻子。(不计双箭刻、箭刻) |  |
九莲宝灯 | 由一种花色序数组成的特定牌型,见同花色任何一张序数牌即成胡牌。不计清一色,门前清,自摸 |  |
大七星 | 胡牌为七对子,并且由“东南西北中发白“其中字牌构成,不计七对,三元七对,四喜七对,全带幺,单钓将,门前清,自摸,字一色 |  |
四杠 | 4个杠,不计三杠,双明杠,明杠,单钓将 |  |
连七对 | 由一种花色序数牌组成序数相连的7个对子的胡牌。不计七对,单钓将,门前清,自摸,清一色 |  |
天胡 | 庄家在发完牌就胡牌。如果庄家有补花,在补完花后就胡牌也算。如果庄家在发完牌后有暗杠, 那么不算天和,不计边张,坎张单钓将不求人,和绝张,自摸 | |
地胡 | 闲家摸到第一张牌 就胡牌,称为地和。如果闲家抓的第一张牌是花牌,那么补花之后胡牌也算地和。如果闲家抓牌前有人吃碰杠(包括暗杠),那么不算地和。 | |
64番
番型 | 胡牌方式 | 示例 |
---|
小四喜 | 胡牌时,牌里有风牌的3副刻子及将牌。不记番:三风刻、幺九刻。 |  |
小三元 | 胡牌时,牌里有箭牌的两副刻子及将牌。不记番:箭刻、双箭刻。 |  |
字一色 | 字一色:胡牌时,牌型由字牌的刻子(杠)、将组成。不记番:碰碰和、混么九、全带幺、么九刻。 |  |
四暗刻 | 胡牌时,牌里有4个暗刻(暗杠)。不记番:门前清、碰碰和、三暗刻、双暗刻、不求人。 |  |
一色双龙会 | 胡牌时,牌型由一种花色的两个老少副,5为将牌组成。不记番:平和、七对、清色、一般高、老少副。 |  |
48番
番型 | 胡牌方式 | 示例 |
---|
一色四同顺 | 胡牌时,牌里有一种花色且序数相同的4副顺子。不记番:一色三节高、一般高、四归一,一色三同顺、七对。 |  |
一色四节高 | 胡牌时牌里有一种花色且序数依次递增一位数的4副刻子(或杠子)。不记番:一色三同顺、一色三节高、碰碰和。 |  |
32番
番型 | 胡牌方式 | 示例 |
---|
一色四步高 | 胡牌时,牌里有一种花色4副依次递增一位数或依次递增二位数的顺子。不记番:一色三步高。 |  |
三杠 | 胡牌时,牌里有3副杠,明杠暗杠均可。 |  |
混幺九 | 胡牌时,由字牌和序数牌、九的刻子及将牌组成的牌型。不记番:碰碰和、幺九刻、全带么。 |  |
24番
番型 | 胡牌方式 | 示例 |
---|
七对 | 胡牌时,胡牌时,牌型由7个对子组成。(不计门前清、不求人、单钓将) |  |
清一色 | 胡牌时,牌型由一种花色的顺序牌组成。 |  |
一色三同顺 | 胡牌时,牌里有一种花色且依次递增一位数字的3副刻子。不记番: 一色三节高、一般高 |  |
一色三节高 | 胡牌时,牌里有一种花色且依次递增一位数字的3副刻子。不记番: 一色三同顺 |  |
16番
番型 | 胡牌方式 | 示例 |
---|
清龙 | 胡牌时,有一种相同花色的123,456,789三付顺子即可。清龙就是清一色条龙。不记番:连6、老少副。 |  |
一色三步高 | 胡牌时,牌里有一种花色的牌,依次递增一位或依次递增二位数字的3副顺子。三暗刻:胡牌时,牌里有3个暗刻。不记番:双暗刻。 |  |
天听 | 庄家打出第-张牌时报听称为天听;发完牌后闲家便报听也称为天听。天听要在胡牌后才算番。如果庄家在发完牌后有暗杠,则庄家不算天听。如果发完牌之后有补花,补花之后报听也算天听。 | |
三暗刻 | 胡牌时,牌里有3个暗刻。 |  |
12番
番型 | 胡牌方式 | 示例 |
---|
大于5 | 胡牌时,牌型由序数牌6 9的顺子、刻子、将牌组成。 |  |
小于5 | 胡牌时,牌型由序数牌1-4的顺子、刻子、将牌组成。 |  |
三风刻 | 胡牌时,牌里有3个风刻。 |  |
8番
番型 | 胡牌方式 | 示例 |
---|
妙手回春 | 自摸牌墙上最后一张牌胡牌。不记番: 自摸。 | |
海底捞月 | 和打出的最后一张牌。 | |
杠上开花 | 胡牌时,开杠抓进的牌成胡牌。不记番:自摸。 | |
抢杠胡 | 胡牌时,和别人自抓开明杠的牌。不记番:胡绝张。 | |
6番
番型 | 胡牌方式 | 示例 |
---|
碰碰胡 | 胡牌时,牌型由4副刻子(或杠)、将牌组成。 |  |
双暗杠 | 胡牌时,有2个暗杠。 |  |
混一色 | 胡牌时,牌型由一种花色序数牌及字牌组成。 |  |
全求人 | 胡牌时,全靠吃牌、碰牌、单钓别人打出的牌胡牌。不记番:单钓。 |  |
双箭刻 | 胡牌时,牌里有2副箭刻(或杠)。不记番:箭刻。 |  |
4番
番型 | 胡牌方式 | 示例 |
---|
全带幺 | 胡牌时,每副牌、将牌都有么牌。(胡牌时各组牌除了字牌都必须有一或九的序数牌)。 |  |
不求人 | 胡牌时,4副牌及将中没有吃牌、碰牌(包括明杠),自摸胡牌。 | |
双明杠 | 胡牌时,牌里有2个明杠。不记番:明杠。 |  |
和绝张 | 胡牌时,胡牌池、桌面已亮明的3张牌所剩的第4张牌。 | |
2番
番型 | 胡牌方式 | 示例 |
---|
箭刻 | 胡牌时,牌里有中、发、白,这3个牌中的任一个牌组成的1副刻子。 |  |
门风刻 | 胡牌时牌里有与门风相同的风刻。 | |
门前清 | 没有吃、碰、明杠,和别人打出的牌。 | |
平胡 | 胡牌时,牌型由4副顺子及序数牌作将组成。边、坎、钓不影响平和。 | |
四归一 | 胡牌时,牌里有4张相同的牌归于一家的顺、刻子、对、将牌中(不包括杠牌)。双暗刻:胡牌时,牌里有2个暗刻。 |  |
双暗刻 | 胡牌时,牌里有2个暗刻。 | |
暗杠 | 胡牌时,牌里有一副自抓4张相同的牌且开杠。 | |
断幺 | 胡牌时,牌里没有一、九牌及字牌。 |  |
报听 | 报听后胡牌。 | |
1番
番型 | 胡牌方式 | 示例 |
---|
一般高 | 胡牌时,牌里有一种花色且序数相同的2副顺子。 |  |
连六 | 一种花色六张序数相连的顺子(例如: 3-4-5条和6-7-8条) |  |
老少副 | 胡牌时,牌里花色相同的123、789的顺子各一副。 |  |
幺九刻 | 胡牌时,牌里有序数为一、九的一副刻子(杠)或是字牌的一副刻子(杠)。 |  |
明杠 | 自己有暗刻,碰别人打出的一张相同的牌开杠:或自己抓进一张与碰的明刻相同。 |  |
边张 | 单和123的3及789的7或1233和3、7789和7都为边张。手中有12345和3,56789和7不算边张。 |  |
坎张 | 胡牌时,和2张牌之间的牌。4556和5也为坎张,手中有45567和6不算坎张。 |  |
单钓将 | 钓单张牌作将成和。 |  |
自摸 | 自己抓进牌成胡牌。 | |
二五八将 | 胡牌时,将牌是二万、五万、八万。 | |
番型计算
在上一篇文章中提到的查表法进行胡牌判定,其中查表法会给我们提供两个返回值,一个是是否胡牌的布尔值,还有一个是胡牌类型返回结果(MahjongResult):
type MahjongResult struct {
Num_ke int
Num_shun int
Jiang byte
Array_ke []byte
Array_shun []byte
Qidui bool
Tongtian bool
}
右手牌(吃碰杠):
type Meld struct {
Key byte
Kind WEAVE_KIND
Ids []byte
Values []byte
Sites []byte
}
结合右手牌(吃碰杠)信息,将每一种胡牌牌型统计成一个结构体:
type MahjongCount struct {
Jiang byte
Array_ke []byte
Array_a_ke []byte
Array_shun []byte
Array_c_shun []byte
Array_h_shun []byte
Array_gang []byte
Array_m_gang []byte
Array_a_gang []byte
TileIndexs []byte
QiDui bool
TongTian bool
Zimo bool
HuId byte
HuIndex byte
MenFeng byte
TingBool bool
}
转换代码:
func CountMahjongResult(results []*MahjongResult, meld []*Meld, tileIndexs []byte, zimo bool, huId, huIndex, menFeng byte, baoTing bool) []*MahjongCount {
res := make([]*MahjongCount, 0)
if results != nil && len(results) > 0 {
for _, v := range results {
mc := &MahjongCount{}
mc.Zimo = zimo
mc.HuId = huId
mc.HuIndex = huIndex
mc.TingBool = baoTing
mc.TileIndexs = make([]byte, len(tileIndexs))
mc.TileIndexs = append(mc.TileIndexs, tileIndexs...)
mc.QiDui = v.Qidui
mc.TongTian = v.Tongtian
mc.Jiang = v.Jiang
mc.MenFeng = menFeng
mc.Array_ke = append(mc.Array_ke, v.Array_ke...)
mc.Array_a_ke = append(mc.Array_a_ke, v.Array_ke...)
mc.Array_shun = append(mc.Array_shun, v.Array_shun...)
mc.Array_h_shun = append(mc.Array_h_shun, v.Array_shun...)
res = append(res, mc)
}
}
if meld != nil && len(meld) > 0 {
for _, m := range meld {
index := ValueToIndex(m.Values[0])
if len(res) == 0 {
mc := &MahjongCount{}
mc.Zimo = zimo
mc.HuId = huId
mc.HuIndex = huIndex
mc.MenFeng = menFeng
mc.TingBool = baoTing
mc.TileIndexs = make([]byte, len(tileIndexs))
mc.TileIndexs = append(mc.TileIndexs, tileIndexs...)
res = append(res, mc)
}
for _, v := range res {
if m.Kind == KIND_LEFT || m.Kind == KIND_RIGHT || m.Kind == KIND_CENTER {
v.Array_shun = append(v.Array_shun, index)
v.Array_c_shun = append(v.Array_c_shun, index)
for _, m := range m.Values {
v.TileIndexs[ValueToIndex(m)] ++
}
} else if m.Kind == KIND_PENG {
v.Array_ke = append(v.Array_ke, index)
v.TileIndexs[index] += 3
} else if m.Kind == KIND_GANG || m.Kind == KIND_ANGANG || m.Kind == KIND_JIAGANG {
v.Array_gang = append(v.Array_gang, index)
v.TileIndexs[index] += 4
if m.Kind == KIND_ANGANG {
v.Array_a_gang = append(v.Array_a_gang, index)
} else {
v.Array_m_gang = append(v.Array_m_gang, index)
}
}
}
}
}
for _, v := range res {
sortByte(v.Array_ke)
sortByte(v.Array_gang)
sortByte(v.Array_shun)
sortByte(v.Array_m_gang)
sortByte(v.Array_a_ke)
sortByte(v.Array_a_gang)
sortByte(v.Array_c_shun)
}
return res
}
func sortByte(a []byte) {
for i := 0; i < len(a); i++ {
l := len(a)
for j := i + 1; j < l; j++ {
if a[i] > a[j] {
temp := a[j]
a[j] = a[i]
a[i] = temp
}
}
l--
}
}
进过统计之后的牌型,只需要遍历所有番型进行判断即可。
由于番型种类过多,所以这里我们将函数写进map中,通过遍历这个map对其进行判断。番型返回的结果是一个二进制掩码,这里的番型有62种,所以我们可以使用int64位数对番型进行表示,一位二进制代表着一种番型。同时再使用一种排除番型,表示不能胡某种番。番型二进制掩码表示如下:
package mahjong
const NULL = int64(0)
const (
ERWUBAJIANG = int64(1) << iota
ZIMO
DANDIAOJIANG
KANZHANG
BIANZHANG
MINGGANG
YAOJIUKE
LAOSHAOFU
LIANLIU
YIBANGAO
BAOTING
DUANYAO
ANGANG
SHUANGANKE
SIGUIYI
PINGHU
MENQIANQING
MENFENGKE
JIANKE
HUJUEZHANG
SHUANGMINGGANG
BUQIUREN
QUANDAIYAO
SHUANGJIANKE
QUANQIUREN
HUNYISE
SHUANGANGANG
PENGPENGHU
QIANGGANGHU
GANGSHANGKAIHUA
HAIDILAOYUE
MIAOSHOUHUICHUN
SANFENGKE
XIAOYUWU
DAYUWU
SANANKE
TIANTING
YISESANBUGAO
QINGLONG
YISESANJIEGAO
YISESANTONGSHUN
QINGYISE
QIDUI
HUNYAOJIU
SANGANG
YISESIBUGAO
YISESIJIEGAO
YISESITONGSHUN
YISESHUANGLONGHUI
SIANKE
ZIYISE
XIAOSANYUAN
XIAOSIXI
DIHU
TIANHU
LIANQIDUI
SIGANG
DAQIXING
JIUBAOLIANDENG
DASANYUAN
DASIXI
)
var HuType_slice = []int64 {
DASIXI,
DASANYUAN,
JIUBAOLIANDENG,
DAQIXING,
SIGANG,
LIANQIDUI,
XIAOSIXI,
XIAOSANYUAN,
ZIYISE,
SIANKE,
YISESHUANGLONGHUI,
YISESITONGSHUN,
YISESIJIEGAO,
YISESIBUGAO,
SANGANG,
HUNYAOJIU,
QIDUI,
QINGYISE,
YISESANTONGSHUN,
YISESANJIEGAO,
QINGLONG,
YISESANBUGAO,
TIANTING,
SANANKE,
DAYUWU,
XIAOYUWU,
SANFENGKE,
MIAOSHOUHUICHUN,
HAIDILAOYUE,
GANGSHANGKAIHUA,
PENGPENGHU,
SHUANGANGANG,
HUNYISE,
QUANQIUREN,
SHUANGJIANKE,
QUANDAIYAO,
BUQIUREN,
HUJUEZHANG,
JIANKE,
MENFENGKE,
MENQIANQING,
PINGHU,
SIGUIYI,
SHUANGANKE,
ANGANG,
DUANYAO,
BAOTING,
YIBANGAO,
LIANLIU,
LAOSHAOFU,
YAOJIUKE,
MINGGANG,
BIANZHANG,
KANZHANG,
DANDIAOJIANG,
ZIMO,
ERWUBAJIANG,
}
var HuType_name = map[int64]string{
NULL: "NULL",
ERWUBAJIANG: "ERWUBAJIANG",
ZIMO: "ZIMO",
DANDIAOJIANG: "DANDIAOJIANG",
KANZHANG: "KANZHANG",
BIANZHANG: "BIANZHANG",
MINGGANG: "MINGGANG",
YAOJIUKE: "YAOJIUKE",
LAOSHAOFU: "LAOSHAOFU",
LIANLIU: "LIANLIU",
YIBANGAO: "YIBANGAO",
BAOTING: "BAOTING",
DUANYAO: "DUANYAO",
ANGANG: "ANGANG",
SHUANGANKE: "SHUANGANKE",
SIGUIYI: "SIGUIYI",
PINGHU: "PINGHU",
MENQIANQING: "MENQIANQING",
MENFENGKE: "MENFENGKE",
JIANKE: "JIANKE",
HUJUEZHANG: "HUJUEZHANG",
SHUANGMINGGANG: "SHUANGMINGGANG",
BUQIUREN: "BUQIUREN",
QUANDAIYAO: "QUANDAIYAO",
SHUANGJIANKE: "SHUANGJIANKE",
QUANQIUREN: "QUANQIUREN",
HUNYISE: "HUNYISE",
SHUANGANGANG: "SHUANGANGANG",
PENGPENGHU: "PENGPENGHU",
QIANGGANGHU: "QIANGGANGHU",
GANGSHANGKAIHUA: "GANGSHANGKAIHUA",
HAIDILAOYUE: "HAIDILAOYUE",
MIAOSHOUHUICHUN: "MIAOSHOUHUICHUN",
SANFENGKE: "SANFENGKE",
XIAOYUWU: "XIAOYUWU",
DAYUWU: "DAYUWU",
SANANKE: "SANANKE",
TIANTING: "TIANTING",
YISESANBUGAO: "YISESANBUGAO",
QINGLONG: "QINGLONG",
YISESANJIEGAO: "YISESANJIEGAO",
YISESANTONGSHUN: "YISESANTONGSHUN",
QINGYISE: "QINGYISE",
QIDUI: "QIDUI",
HUNYAOJIU: "HUNYAOJIU",
SANGANG: "SANGANG",
YISESIBUGAO: "YISESIBUGAO",
YISESIJIEGAO: "YISESIJIEGAO",
YISESITONGSHUN: "YISESITONGSHUN",
YISESHUANGLONGHUI: "YISESHUANGLONGHUI",
SIANKE: "SIANKE",
ZIYISE: "ZIYISE",
XIAOSANYUAN: "XIAOSANYUAN",
XIAOSIXI: "XIAOSIXI",
DIHU: "DIHU",
TIANHU: "TIANHU",
LIANQIDUI: "LIANQIDUI",
SIGANG: "SIGANG",
DAQIXING: "DAQIXING",
JIUBAOLIANDENG: "JIUBAOLIANDENG",
DASANYUAN: "DASANYUAN",
DASIXI: "DASIXI",
}
var HuType_Fan_Value = map[string]int32{
"NULL": 0,
"ERWUBAJIANG": 1,
"ZIMO": 1,
"DANDIAOJIANG": 1,
"KANZHANG": 1,
"BIANZHANG": 1,
"MINGGANG": 1,
"YAOJIUKE": 1,
"LAOSHAOFU": 1,
"LIANLIU": 1,
"YIBANGAO": 1,
"BAOTING": 2,
"DUANYAO": 2,
"ANGANG": 2,
"SHUANGANKE": 2,
"SIGUIYI": 2,
"PINGHU": 2,
"MENQIANQING": 2,
"MENFENGKE": 2,
"JIANKE": 2,
"HUJUEZHANG": 4,
"SHUANGMINGGANG": 4,
"BUQIUREN": 4,
"QUANDAIYAO": 4,
"SHUANGJIANKE": 6,
"QUANQIUREN": 6,
"HUNYISE": 6,
"SHUANGANGANG": 6,
"PENGPENGHU": 6,
"QIANGGANGHU": 8,
"GANGSHANGKAIHUA": 8,
"HAIDILAOYUE": 8,
"MIAOSHOUHUICHUN": 8,
"SANFENGKE": 12,
"XIAOYUWU": 12,
"DAYUWU": 12,
"SANANKE": 16,
"TIANTING": 16,
"YISESANBUGAO": 16,
"QINGLONG": 16,
"YISESANJIEGAO": 24,
"YISESANTONGSHUN": 24,
"QINGYISE": 24,
"QIDUI": 24,
"HUNYAOJIU": 32,
"SANGANG": 32,
"YISESIBUGAO": 32,
"YISESIJIEGAO": 48,
"YISESITONGSHUN": 48,
"YISESHUANGLONGHUI": 64,
"SIANKE": 64,
"ZIYISE": 64,
"XIAOSANYUAN": 64,
"XIAOSIXI": 64,
"DIHU": 88,
"TIANHU": 88,
"LIANQIDUI": 88,
"SIGANG": 88,
"DAQIXING": 88,
"JIUBAOLIANDENG": 88,
"DASANYUAN": 88,
"DASIXI": 88,
}
番型掩码确定后就可以定义函数,
var funcFan map[int64]func(countResults *mahjong.MahjongCount, mask, noMask *int64)
胡牌番型判定只需遍历这个函数:
func CountHuFan(countResults []*mahjong.MahjongCount) (int64, int64) {
mask := make([]int64, len(countResults))
noMask := make([]int64, len(countResults))
maxMask := int64(0)
maxNoMask := int64(0)
for k, v := range countResults {
for _, i := range mahjong.HuType_slice {
if noMask[k]&i > 0 {
continue
}
f, ok := funcFan[i]
if !ok {
continue
}
f(v, &mask[k], &noMask[k])
}
if mask[k] > maxMask {
maxMask = mask[k]
maxNoMask = noMask[k]
}
}
return maxMask, maxNoMask
}
番型函数的map初始化需要在init函数中进行,
func init() {
funcFan = make(map[int64]func(countResults *mahjong.MahjongCount, mask, noMask *int64), len(mahjong.HuType_slice))
funcFan[mahjong.DASIXI] = IsBigFourHappy
funcFan[mahjong.DASANYUAN] = IsDaSanYuan
funcFan[mahjong.JIUBAOLIANDENG] = IsJiuLianBaoDeng
funcFan[mahjong.DAQIXING] = IsDaQiXing
funcFan[mahjong.SIGANG] = IsSiGang
funcFan[mahjong.LIANQIDUI] = IsLianQiDui
funcFan[mahjong.XIAOSIXI] = IsXiaoSiXi
funcFan[mahjong.XIAOSANYUAN] = IsXiaoSanYuan
funcFan[mahjong.ZIYISE] = IsZiYiSe
funcFan[mahjong.SIANKE] = IsSiAnKe
funcFan[mahjong.YISESHUANGLONGHUI] = IsYiSeShuangLongHui
funcFan[mahjong.YISESITONGSHUN] = IsYiSeSiTongShun
funcFan[mahjong.YISESIJIEGAO] = IsYiSeSiJieGao
funcFan[mahjong.YISESIBUGAO] = IsYiSeSiBuGao
funcFan[mahjong.SANGANG] = IsSanGang
funcFan[mahjong.HUNYAOJIU] = IsHunYaoJiu
funcFan[mahjong.QIDUI] = IsQiDui
funcFan[mahjong.QINGYISE] = IsQingYiSe
funcFan[mahjong.YISESANTONGSHUN] = IsYiSeSanTongShun
funcFan[mahjong.YISESANJIEGAO] = IsYiSeSanJieGao
funcFan[mahjong.QINGLONG] = IsQingLong
funcFan[mahjong.YISESANBUGAO] = IsYiSeSanBuGao
funcFan[mahjong.TIANTING] = IsTianTing
funcFan[mahjong.SANANKE] = IsSanAnKe
funcFan[mahjong.DAYUWU] = IsDaYuWu
funcFan[mahjong.XIAOYUWU] = IsXiaoYuWu
funcFan[mahjong.SANFENGKE] = IsSanFengKe
funcFan[mahjong.MIAOSHOUHUICHUN] = IsMiaoShouHuiChun
funcFan[mahjong.HAIDILAOYUE] = IsHaiDiLaoYue
funcFan[mahjong.GANGSHANGKAIHUA] = IsGangShangKaiHua
funcFan[mahjong.QIANGGANGHU] = IsQiangGangHu
funcFan[mahjong.PENGPENGHU] = IsPengPengHu
funcFan[mahjong.SHUANGANGANG] = IsShuangAnGang
funcFan[mahjong.HUNYISE] = IsHunYiSe
funcFan[mahjong.QUANQIUREN] = IsQuanQiuRen
funcFan[mahjong.SHUANGJIANKE] = IsShuangJianKe
funcFan[mahjong.QUANDAIYAO] = IsQuanDaiYao
funcFan[mahjong.BUQIUREN] = IsBuQiuRen
funcFan[mahjong.SHUANGMINGGANG] = IsShuangMingGang
funcFan[mahjong.HUJUEZHANG] = IsHuJueZhang
funcFan[mahjong.JIANKE] = IsJianKe
funcFan[mahjong.MENFENGKE] = IsMenFengKe
funcFan[mahjong.MENQIANQING] = IsMenQianQing
funcFan[mahjong.PINGHU] = IsPingHu
funcFan[mahjong.SIGUIYI] = IsSiGuiYi
funcFan[mahjong.SHUANGANKE] = IsShuangAnKe
funcFan[mahjong.ANGANG] = IsAnGang
funcFan[mahjong.DUANYAO] = IsDuanYao
funcFan[mahjong.BAOTING] = IsBaoTing
funcFan[mahjong.YIBANGAO] = IsYiBanGao
funcFan[mahjong.LIANLIU] = IsLianLiu
funcFan[mahjong.LAOSHAOFU] = IsLaoShaoFu
funcFan[mahjong.YAOJIUKE] = IsYaoJiuKe
funcFan[mahjong.MINGGANG] = IsMingGang
funcFan[mahjong.BIANZHANG] = IsBianZhang
funcFan[mahjong.KANZHANG] = IsKanZhang
funcFan[mahjong.DANDIAOJIANG] = IsDanDiaoJiang
funcFan[mahjong.ZIMO] = IsZiMo
funcFan[mahjong.ERWUBAJIANG] = IsErWuBaJiang
}
下面是62种番型计算方法:
func IsBigFourHappy(v *mahjong.MahjongCount, mask, noMask *int64) {
num_ke := len(v.Array_ke)
num_gang := len(v.Array_gang)
if num_ke != 4 && num_gang != 4 {
return
} else {
arr := v.Array_ke
if num_gang == 4 {
arr = v.Array_gang
}
bo := true
for _, m := range arr {
if m < 27 || m > 30 {
bo = false
break
}
}
if !bo {
return
}
*mask |= mahjong.DASIXI
*noMask |= mahjong.MENFENGKE | mahjong.XIAOSIXI | mahjong.SANFENGKE | mahjong.PENGPENGHU | mahjong.YAOJIUKE
return
}
return
}
func IsDaSanYuan(v *mahjong.MahjongCount, mask, noMask *int64) {
lenKe := len(v.Array_ke)
if lenKe < 3 {
return
}
if (lenKe == 3 && mahjong.IndexToValue(v.Array_ke[0]) != 0x35) || (lenKe == 4 && mahjong.IndexToValue(v.Array_ke[1]) != 0x35) {
return
}
*mask |= mahjong.DASANYUAN
*noMask |= mahjong.SHUANGJIANKE | mahjong.JIANKE
return
}
func IsJiuLianBaoDeng(v *mahjong.MahjongCount, mask, noMask *int64) {
fmt.Println("jiang:", v.Jiang)
if v.Jiang != 0 {
return
}
if len(v.Array_ke) != 1 || (v.Array_ke[0] != 8) {
return
}
if len(v.Array_shun) != 3 || (v.Array_shun[0] != 0 || v.Array_shun[1] != 3 || v.Array_shun[2] != 6) {
return
}
*mask |= mahjong.JIUBAOLIANDENG
*noMask |= mahjong.QINGYISE | mahjong.MENQIANQING | mahjong.ZIMO
}
func IsDaQiXing(v *mahjong.MahjongCount, mask, noMask *int64) {
if !v.QiDui {
return
}
bo := true
for i := byte(27); i < mahjong.MAX_INDEX; i++ {
if v.TileIndexs[i] != 2 {
bo = false
break
}
}
if bo {
*mask |= mahjong.DAQIXING
*noMask |= mahjong.QIDUI | mahjong.QUANDAIYAO | mahjong.DANDIAOJIANG | mahjong.MENQIANQING | mahjong.ZIMO | mahjong.ZIYISE
}
}
func IsSiGang(v *mahjong.MahjongCount, mask, noMask *int64) {
if len(v.Array_gang) != 4 {
return
}
*mask |= mahjong.SIGANG
*noMask |= mahjong.SANGANG | mahjong.SHUANGMINGGANG | mahjong.MINGGANG | mahjong.DANDIAOJIANG
}
func IsLianQiDui(v *mahjong.MahjongCount, mask, noMask *int64) {
if !v.QiDui {
return
}
bo := true
for i := byte(0); i < 9; i++ {
if v.TileIndexs[i] != 2 {
bo = false
break
}
}
if bo {
*mask |= mahjong.LIANQIDUI
*noMask |= mahjong.QIDUI | mahjong.DANDIAOJIANG | mahjong.MENQIANQING | mahjong.QINGYISE
}
}
func IsXiaoSiXi(v *mahjong.MahjongCount, mask, noMask *int64) {
lke := len(v.Array_ke)
fmt.Println(v)
if lke < 3 {
return
}
if v.Jiang > 30 || v.Jiang < 27 {
return
}
num := 0
for _, m := range v.Array_ke {
if m >= 27 && m <= 30 {
num ++
}
}
if num != 3 {
return
}
*mask |= mahjong.XIAOSIXI
*noMask |= mahjong.SANFENGKE | mahjong.YAOJIUKE
}
func IsXiaoSanYuan(v *mahjong.MahjongCount, mask, noMask *int64) {
if v.Jiang < 31 {
return
}
if len(v.Array_ke) <= 1 {
return
}
num := 0
for _, m := range v.Array_ke {
if m >= 31 {
num++
}
}
if num < 2 {
return
}
*mask |= mahjong.XIAOSANYUAN
*noMask |= mahjong.JIANKE | mahjong.SHUANGJIANKE
}
func IsZiYiSe(v *mahjong.MahjongCount, mask, noMask *int64) {
if v.Jiang < 27 {
return
}
if len(v.Array_shun) > 0 {
return
}
bo := true
kg := make([]byte, 0)
kg = append(append(kg, v.Array_ke...), v.Array_gang...)
for _, m := range kg {
if m < 27 {
bo = false
break
}
}
if !bo {
return
}
*mask |= mahjong.ZIYISE
*noMask |= mahjong.PENGPENGHU | mahjong.HUNYAOJIU | mahjong.QUANDAIYAO | mahjong.YAOJIUKE
}
func IsSiAnKe(v *mahjong.MahjongCount, mask, noMask *int64) {
if len(v.Array_a_ke)+len(v.Array_a_gang) < 4 {
return
}
*mask |= mahjong.SIANKE
*noMask |= mahjong.MENQIANQING | mahjong.PENGPENGHU | mahjong.SANANKE | mahjong.SHUANGANKE | mahjong.BUQIUREN
}
func IsYiSeShuangLongHui(v *mahjong.MahjongCount, mask, noMask *int64) {
if v.Jiang != 4 {
return
}
if len(v.Array_shun) != 4 {
return
}
num1 := 0
num9 := 0
for _, m := range v.Array_shun {
if m == 0 {
num1++
}
if m == 6 {
num9++
}
}
if num1 != 2 || num9 != 2 {
return
}
*mask |= mahjong.YISESHUANGLONGHUI
*noMask |= mahjong.PINGHU | mahjong.QIDUI | mahjong.QINGYISE | mahjong.YIBANGAO | mahjong.LAOSHAOFU
}
func IsYiSeSiTongShun(v *mahjong.MahjongCount, mask, noMask *int64) {
if len(v.Array_shun) != 4 {
return
}
bo := true
f := v.Array_shun[0]
for _, m := range v.Array_shun {
if f != m {
bo = false
break
}
}
if !bo {
return
}
*mask |= mahjong.YISESITONGSHUN
*noMask |= mahjong.YISESANJIEGAO | mahjong.YIBANGAO | mahjong.SIGUIYI | mahjong.YISESANTONGSHUN | mahjong.QIDUI
}
func IsYiSeSiJieGao(v *mahjong.MahjongCount, mask, noMask *int64) {
if len(v.Array_ke) != 4 && len(v.Array_gang) != 4 {
return
}
a := make([]byte, 0)
a = v.Array_ke[:]
if len(v.Array_gang) == 4 {
a = v.Array_gang[:]
}
if a[3]-a[0] != 3 {
return
}
*mask |= mahjong.YISESIJIEGAO
*noMask |= mahjong.YISESANTONGSHUN | mahjong.YISESANJIEGAO | mahjong.PENGPENGHU
}
func IsYiSeSiBuGao(v *mahjong.MahjongCount, mask, noMask *int64) {
if len(v.Array_shun) != 4 {
return
}
c := v.Array_shun[1] - v.Array_shun[0]
if c != 1 && c != 2 {
return
}
bo := true
for i := 2; i < len(v.Array_shun); i++ {
if v.Array_shun[i]-v.Array_shun[i-1] != c {
bo = false
break
}
}
if !bo {
return
}
*mask |= mahjong.YISESIBUGAO
*noMask |= mahjong.YISESANBUGAO
}
func IsSanGang(v *mahjong.MahjongCount, mask, noMask *int64) {
if len(v.Array_gang) != 3 {
return
}
*mask |= mahjong.SANGANG
}
func IsHunYaoJiu(v *mahjong.MahjongCount, mask, noMask *int64) {
if len(v.Array_ke) < 2 {
return
}
ziKe := 0
yjKe := 0
for _, m := range v.Array_ke {
if m == 0 || m == 8 {
yjKe ++
} else if m > 30 {
ziKe ++
}
}
if yjKe != 2 {
return
}
if ziKe < 1 {
return
}
*mask |= mahjong.HUNYAOJIU
*noMask |= mahjong.PENGPENGHU | mahjong.YAOJIUKE | mahjong.QUANDAIYAO
}
func IsQiDui(v *mahjong.MahjongCount, mask, noMask *int64) {
if !v.QiDui {
return
}
*mask |= mahjong.QIDUI
*noMask |= mahjong.MENQIANQING | mahjong.BUQIUREN | mahjong.DANDIAOJIANG
}
func IsQingYiSe(v *mahjong.MahjongCount, mask, noMask *int64) {
if v.Jiang > 8 {
return
}
if len(v.Array_ke) > 0 && v.Array_ke[len(v.Array_ke)-1] > 8 {
return
}
if len(v.Array_gang) > 0 && v.Array_gang[len(v.Array_gang)-1] > 8 {
return
}
*mask |= mahjong.QINGYISE
}
func IsYiSeSanTongShun(v *mahjong.MahjongCount, mask, noMask *int64) {
l := len(v.Array_shun)
if l < 3 {
return
}
num := 1
for i := 0; i < l-1; i++ {
if v.Array_shun[i] == v.Array_shun[i+1] {
num++
} else if i == 1 {
num = 0
}
}
if num < 3 {
return
}
*mask |= mahjong.YISESANTONGSHUN
*noMask |= mahjong.YISESANJIEGAO | mahjong.YIBANGAO
}
func IsYiSeSanJieGao(v *mahjong.MahjongCount, mask, noMask *int64) {
l := len(v.Array_ke)
if l < 3 {
return
}
num := 1
for i := 0; i < l-1; i++ {
if v.Array_ke[i]+1 == v.Array_ke[i+1] {
num++
} else if i == 1 {
break
}
}
if num < 3 {
return
}
*mask |= mahjong.YISESANJIEGAO
*noMask |= mahjong.YISESANTONGSHUN
}
func IsQingLong(v *mahjong.MahjongCount, mask, noMask *int64) {
l := len(v.Array_shun)
if l < 3 {
return
}
num1 := false
num4 := false
num7 := false
for _, m := range v.Array_shun {
if m == 0 {
num1 = true
} else if m == 3 {
num4 = true
} else if m == 6 {
num7 = true
}
}
if num1 && num4 && num7 {
*mask |= mahjong.QINGLONG
*noMask |= mahjong.LIANLIU | mahjong.LAOSHAOFU
}
}
func IsYiSeSanBuGao(v *mahjong.MahjongCount, mask, noMask *int64) {
l := len(v.Array_shun)
if l < 3 {
return
}
n1 := 0
n2 := 0
for i := 0; i < l-1; i++ {
if v.Array_shun[i+1]-v.Array_shun[i] == 1 {
n1 ++
} else if v.Array_shun[i+1]-v.Array_shun[i] == 2 {
n2 ++
}
}
if n1 < 2 && n2 < 2 {
return
}
c := byte(1)
if n2 > 1 {
c = 2
}
if l == 3 {
*mask |= mahjong.YISESANBUGAO
} else {
if v.Array_shun[2]-v.Array_shun[1] == c {
*mask |= mahjong.YISESANBUGAO
}
}
}
func IsTianTing(v *mahjong.MahjongCount, mask, noMask *int64) {
}
func IsSanAnKe(v *mahjong.MahjongCount, mask, noMask *int64) {
if len(v.Array_a_ke) < 3 {
return
}
*mask |= mahjong.SANANKE
}
func IsDaYuWu(v *mahjong.MahjongCount, mask, noMask *int64) {
sum := byte(0)
for i := 5; i < 9; i++ {
sum += v.TileIndexs[i]
}
if sum < 14 {
return
}
*mask |= mahjong.DAYUWU
}
func IsXiaoYuWu(v *mahjong.MahjongCount, mask, noMask *int64) {
sum := byte(0)
for i := 0; i < 5; i++ {
sum += v.TileIndexs[i]
}
if sum < 14 {
return
}
*mask |= mahjong.XIAOYUWU
}
func IsSanFengKe(v *mahjong.MahjongCount, mask, noMask *int64) {
if len(v.Array_ke) < 3 {
return
}
sum := 0
for _, m := range v.Array_ke {
if m < 31 && m > 26 {
sum++
}
}
if sum > 2 {
*mask |= mahjong.SANFENGKE
}
}
func IsMiaoShouHuiChun(v *mahjong.MahjongCount, mask, noMask *int64) {
if !v.Zimo {
return
}
if v.HuId == MaxTiles-1 {
*mask |= mahjong.MIAOSHOUHUICHUN
*noMask |= mahjong.ZIMO
}
}
func IsHaiDiLaoYue(v *mahjong.MahjongCount, mask, noMask *int64) {
if v.Zimo {
return
}
if v.HuId == MaxTiles-1 {
*mask |= mahjong.HAIDILAOYUE
}
}
func IsGangShangKaiHua(v *mahjong.MahjongCount, mask, noMask *int64) {
}
func IsQiangGangHu(v *mahjong.MahjongCount, mask, noMask *int64) {
}
func IsPengPengHu(v *mahjong.MahjongCount, mask, noMask *int64) {
if len(v.Array_ke) != 4 && len(v.Array_gang) != 4 {
return
}
*mask |= mahjong.PENGPENGHU
}
func IsShuangAnGang(v *mahjong.MahjongCount, mask, noMask *int64) {
if len(v.Array_a_gang) == 2 {
*mask |= mahjong.SHUANGANGANG
}
}
func IsHunYiSe(v *mahjong.MahjongCount, mask, noMask *int64) {
bo := false
bo1 := false
for i := byte(0); i < byte(9); i++ {
if v.TileIndexs[i] > 0 {
bo = true
break
}
}
for i := byte(27); i < mahjong.MAX_INDEX; i++ {
if v.TileIndexs[i] > 0 {
bo1 = true
break
}
}
if bo && bo1 {
*mask |= mahjong.HUNYISE
}
}
func IsQuanQiuRen(v *mahjong.MahjongCount, mask, noMask *int64) {
if len(v.Array_c_shun) != len(v.Array_shun) || len(v.Array_a_gang) != 0 || len(v.Array_a_ke) != 0 {
return
}
*mask |= mahjong.QUANQIUREN
*noMask |= mahjong.DANDIAOJIANG
}
func IsShuangJianKe(v *mahjong.MahjongCount, mask, noMask *int64) {
if len(v.Array_ke) != 2 && len(v.Array_gang) != 2 {
return
}
var a []byte
if len(v.Array_ke) == 2 {
a = v.Array_ke
} else {
a = v.Array_gang
}
bo := true
for _, m := range a {
if m < 31 {
bo = false
break
}
}
if bo {
*mask |= mahjong.SHUANGJIANKE
*noMask |= mahjong.JIANKE
}
}
func IsQuanDaiYao(v *mahjong.MahjongCount, mask, noMask *int64) {
if v.Jiang != 0 && v.Jiang != 8 {
return
}
for _, m := range v.Array_shun {
if m != 0 && m != 7 {
return
}
}
var a []byte
a = append(append(a, v.Array_ke...), v.Array_shun...)
for _, m := range a {
if m != 0 && m != 8 {
return
}
}
*mask |= mahjong.QUANDAIYAO
}
func IsBuQiuRen(v *mahjong.MahjongCount, mask, noMask *int64) {
if !v.Zimo {
return
}
if len(v.Array_c_shun) != 0 || len(v.Array_a_ke) != len(v.Array_ke) || len(v.Array_m_gang) != 0 {
return
}
*mask |= mahjong.BUQIUREN
}
func IsShuangMingGang(v *mahjong.MahjongCount, mask, noMask *int64) {
if len(v.Array_m_gang) != 2 {
return
}
*mask |= mahjong.SHUANGMINGGANG
*noMask |= mahjong.MINGGANG
}
func IsHuJueZhang(v *mahjong.MahjongCount, mask, noMask *int64) {
}
func IsJianKe(v *mahjong.MahjongCount, mask, noMask *int64) {
for _, m := range v.Array_ke {
if m > 29 {
*mask |= mahjong.JIANKE
return
}
}
}
func IsMenFengKe(v *mahjong.MahjongCount, mask, noMask *int64) {
if len(v.Array_ke) < 1 {
return
}
for _, m := range v.Array_ke {
if m == v.MenFeng {
*mask |= mahjong.MENFENGKE
return
}
}
}
func IsMenQianQing(v *mahjong.MahjongCount, mask, noMask *int64) {
if v.Zimo {
return
}
if len(v.Array_c_shun) != 0 || len(v.Array_a_ke) != len(v.Array_ke) || len(v.Array_m_gang) != 0 {
return
}
*mask |= mahjong.MENQIANQING
}
func IsPingHu(v *mahjong.MahjongCount, mask, noMask *int64) {
if v.Jiang > 8 {
return
}
if len(v.Array_shun) != 4 {
return
}
*mask |= mahjong.PINGHU
}
func IsSiGuiYi(v *mahjong.MahjongCount, mask, noMask *int64) {
s := make([]byte, 0)
for i, m := range v.TileIndexs {
if m == 4 {
s = append(s, byte(i))
}
}
for _, c := range s {
bo := true
for _, k := range v.Array_gang {
if k == c {
bo = false
break
}
}
if bo {
*mask |= mahjong.SIGUIYI
return
}
}
}
func IsShuangAnKe(v *mahjong.MahjongCount, mask, noMask *int64) {
if len(v.Array_a_ke) == 2 {
*mask |= mahjong.SHUANGANKE
}
}
func IsAnGang(v *mahjong.MahjongCount, mask, noMask *int64) {
if len(v.Array_a_gang) > 0 {
*mask |= mahjong.ANGANG
}
}
func IsDuanYao(v *mahjong.MahjongCount, mask, noMask *int64) {
if v.TileIndexs[0] != 0 || v.TileIndexs[8] != 0 {
return
}
for i := byte(27); i < mahjong.MAX_INDEX; i++ {
if v.TileIndexs[i] != 0 {
return
}
}
*mask |= mahjong.DUANYAO
}
func IsBaoTing(v *mahjong.MahjongCount, mask, noMask *int64) {
if v.TingBool {
*mask |= mahjong.BAOTING
}
}
func IsYiBanGao(v *mahjong.MahjongCount, mask, noMask *int64) {
if len(v.Array_shun) < 2 {
return
}
bo := false
for i, m := range v.Array_shun {
for j := i + 1; j < len(v.Array_shun); j++ {
if v.Array_shun[j] == m {
bo = true
break
}
}
if bo {
*mask |= mahjong.YIBANGAO
return
}
}
}
func IsLianLiu(v *mahjong.MahjongCount, mask, noMask *int64) {
if len(v.Array_shun) < 2 {
return
}
for i := 0; i < len(v.Array_shun)-1; i++ {
if v.Array_shun[i+1]-v.Array_shun[i] == 3 {
*mask |= mahjong.LIANLIU
return
}
}
}
func IsLaoShaoFu(v *mahjong.MahjongCount, mask, noMask *int64) {
if len(v.Array_shun) < 2 {
return
}
o := 0
y := 0
for _, m := range v.Array_shun {
if o > 0 && y > 0 {
*mask |= mahjong.LAOSHAOFU
return
}
if m == 0 {
y++
} else if m == 8 {
o++
}
}
}
func IsYaoJiuKe(v *mahjong.MahjongCount, mask, noMask *int64) {
var a []byte
a = append(append(a, v.Array_ke...), v.Array_gang...)
for _, m := range a {
if m == 0 || m == 8 || (m > 26 && m < 31) {
*mask |= mahjong.YAOJIUKE
return
}
}
}
func IsMingGang(v *mahjong.MahjongCount, mask, noMask *int64) {
if len(v.Array_m_gang) > 0 {
*mask |= mahjong.MINGGANG
}
}
func IsBianZhang(v *mahjong.MahjongCount, mask, noMask *int64) {
if v.HuIndex != 2 && v.HuIndex != 6 {
return
}
for _, m := range v.Array_h_shun {
if v.HuIndex == 2 {
if m == 2 {
return
}
} else if v.HuIndex == 6 && m+2 == 6 {
return
}
}
*mask |= mahjong.BIANZHANG
}
func IsKanZhang(v *mahjong.MahjongCount, mask, noMask *int64) {
if v.HuIndex == 0 || v.HuIndex == 8 {
return
}
for _, m := range v.Array_h_shun {
if v.HuIndex == m || v.HuIndex == m+2 {
return
}
}
*mask |= mahjong.KANZHANG
}
func IsDanDiaoJiang(v *mahjong.MahjongCount, mask, noMask *int64) {
if v.HuIndex == v.Jiang {
*mask |= mahjong.DANDIAOJIANG
}
}
func IsZiMo(v *mahjong.MahjongCount, mask, noMask *int64) {
if v.Zimo {
*mask |= mahjong.ZIMO
}
}
func IsErWuBaJiang(v *mahjong.MahjongCount, mask, noMask *int64) {
if v.Jiang == 1 || v.Jiang == 4 || v.Jiang == 7 {
*mask |= mahjong.ERWUBAJIANG
}
}