四川麻将判断胡牌,找到要听的牌

jan-bar · · 1358 次点击 · 开始浏览    置顶
这是一个创建于 的主题,其中的信息可能已经有所发展或是发生改变。

详细代码如下: ```go package main import ( "fmt" "strings" ) func main() { s := "1w1w2d2d3d3d4w4w3w3w7d7d8d8d" mj := InitMahjong(s) mj.Print() fmt.Println(mj.Win()) fmt.Println("-------------------------------") s = "1w2w2d3d4d5d3w4w5w6w7d8d8w9w" mj = InitMahjong(s) mj.Print() fmt.Println(mj.Win()) fmt.Println("-------------------------------") s = "1w2w2d3d4d5d3w4w5w6w7d8d9w9w" mj = InitMahjong(s) mj.Print() fmt.Println(mj.Win()) fmt.Println("-------------------------------") s = "2w2w2w4w4w4w5w5w6w6w7w3d3d" mj = InitMahjong(s) mj.Print() fmt.Println(strings.Join(mj.Solution(), "\n")) fmt.Println("-------------------------------") s = "2w2w2w4w4w4w5w6w6w6w7w8w9w" mj = InitMahjong(s) mj.Print() fmt.Println(strings.Join(mj.Solution(), "\n")) } type Mahjong struct { // 万,条,筒数量, 例如: // cardNum[0][5]=3,表示6万有3张 // cardNum[1][8]=4,表示9条有4张 // cardNum[2][2]=1,表示3筒有1张 cardNum [3][9]uint8 // 每种花色数量, 例如: // typeNum[0]=5,表示万有5张 // typeNum[1]=6,表示条有6张 // typeNum[2]=3,表示筒有3张 typeNum [3]uint8 // 4张一样的牌,杠数量 gangNum uint8 // w: 万,t: 条,d: 筒 typedef string } func InitMahjong(data string) *Mahjong { mj := &Mahjong{typedef: "wtd"} for i := 1; i < len(data); i += 2 { for j := 0; j < 3; j++ { if data[i] == mj.typedef[j] { if num := data[i-1] - '1'; num < 9 { mj.typeNum[j]++ mj.cardNum[j][num]++ } break } } } return mj } func (mj *Mahjong) Print() { fmt.Print("当前牌: ") for i := 0; i < 3; i++ { for j := 0; j < 9; j++ { for k := mj.cardNum[i][j]; k > 0; k-- { fmt.Printf("%d%c,", j+1, mj.typedef[i]) } } } fmt.Println() } func (mj *Mahjong) IsOneTypeWin(msg *strings.Builder, cards []uint8, num uint8, hasCouple *bool, mt byte) bool { // n * AAA + m * ABC + DD,如有4个一样的,则剔除后满足前面条件则胡牌 if num == 0 { return true // 当前花色数量为0,计算完毕 } for i := 0; i < 9; i++ { // 表示有对子,胡牌时只能有一个对子,因此判断 !*hasCouple if cards[i] >= 2 && !*hasCouple { cards[i] -= 2 *hasCouple = true if mj.IsOneTypeWin(msg, cards, num-2, hasCouple, mt) { _, _ = fmt.Fprintf(msg, "[%d%c%d%c],", i+1, mt, i+1, mt) return true } cards[i] += 2 *hasCouple = false } if cards[i] == 4 { cards[i] -= 4 if mj.IsOneTypeWin(msg, cards, num-4, hasCouple, mt) { _, _ = fmt.Fprintf(msg, "[%d%c%d%c%d%c%d%c],", i+1, mt, i+1, mt, i+1, mt, i+1, mt) mj.gangNum++ // 有4个一样的,将杠数量+1 return true } cards[i] += 4 } if cards[i] >= 3 { cards[i] -= 3 if mj.IsOneTypeWin(msg, cards, num-3, hasCouple, mt) { _, _ = fmt.Fprintf(msg, "[%d%c%d%c%d%c],", i+1, mt, i+1, mt, i+1, mt) return true // 组成3张一样的 } cards[i] += 3 } if i < 7 && cards[i] > 0 && cards[i+1] > 0 && cards[i+2] > 0 { cards[i]-- cards[i+1]-- cards[i+2]-- if mj.IsOneTypeWin(msg, cards, num-3, hasCouple, mt) { _, _ = fmt.Fprintf(msg, "[%d%c%d%c%d%c],", i+1, mt, i+2, mt, i+3, mt) return true // 组成一个顺子 } cards[i]++ cards[i+1]++ cards[i+2]++ } } return false } /* 1. 和牌的基本牌型 11,123,123,123,123 11,123,123,123,111 (1111,下同) 11,123,123,111,111 11,123,111,111,111 11,111,111,111,111 2. 和牌的特殊牌型 11,11,11,11,11,11,11 (小七对) 1,1,1,1,1,1,1,1,1,1,1,1,11 (十三幺) 1,1,1,1,1,1,1,1,1,1,1,1,1,1 (七星不靠,全不靠) 注: 1=单张,11=将/对子,111=刻子,1111=杠,123=顺子 */ func (mj *Mahjong) Win() (string, bool) { if mj.typeNum[0] > 0 && mj.typeNum[1] > 0 && mj.typeNum[2] > 0 { return "没有缺一门", false } var cnt [3][]string for i := 0; i < 3; i++ { for j := 0; j < 9; j++ { if n := mj.cardNum[i][j]; n > 4 { return fmt.Sprintf("%d%c有%d张", j+1, mj.typedef[i], n), false } else if n == 1 || n == 2 { // 将数量为1和2的牌记录下来,用于判断特殊牌型 cnt[n] = append(cnt[n], fmt.Sprintf("%d%c", j+1, mj.typedef[i])) } } } // 2种花色总共14张时,判断特殊胡牌 if mj.typeNum[0]+mj.typeNum[1]+mj.typeNum[2] == 14 { switch l1, l2 := len(cnt[1]), len(cnt[2]); { case l1 == 14: return "七星不靠: " + strings.Join(cnt[1], ","), true case l2 == 7: return "小七对: " + strings.Join(cnt[2], ","), true case l1 == 12 && l2 == 1: return "十三幺: " + strings.Join(cnt[1], ",") + ", 2 * " + cnt[2][0], true } } var ( hasCouple bool msg strings.Builder tmpCard = make([]uint8, 9) ) mj.gangNum = 0 // 重新统计杠牌数量 for i := 0; i < 3; i++ { copy(tmpCard, mj.cardNum[i][:]) // 使用副本,不要修改mj.typeNum if !mj.IsOneTypeWin(&msg, tmpCard, mj.typeNum[i], &hasCouple, mj.typedef[i]) { return fmt.Sprintf("花色:%c 不满足胡牌", mj.typedef[i]), false } } if !hasCouple { return "没有对子,不能胡牌", false } // 所有手头的牌-14后多余的牌个数就是杠的数量,没有杠则刚好等于14 if mj.typeNum[0]+mj.typeNum[1]+mj.typeNum[2]-14 != mj.gangNum { return "你丫诈和,牌的数量不对", false } return "正常胡牌: " + msg.String(), true } func (mj *Mahjong) Solution() (res []string) { for i := 0; i < 3; i++ { for j := 0; j < 9; j++ { if mj.cardNum[i][j] == 4 { continue // 已经有4张牌,跳过 } mj.cardNum[i][j]++ mj.typeNum[i]++ msg, ok := mj.Win() mj.cardNum[i][j]-- mj.typeNum[i]-- if ok { // 假设得到一张牌,能胡牌时该牌就是要听的牌 res = append(res, fmt.Sprintf("%s听%d%c", msg, j+1, mj.typedef[i])) } } } return } ``` 结果如下: ```go 当前牌: 1w,1w,3w,3w,4w,4w,2d,2d,3d,3d,7d,7d,8d,8d, 小七对: 1w,3w,4w,2d,3d,7d,8d true ------------------------------- 当前牌: 1w,2w,3w,4w,5w,6w,8w,9w,2d,3d,4d,5d,7d,8d, 七星不靠: 1w,2w,3w,4w,5w,6w,8w,9w,2d,3d,4d,5d,7d,8d true ------------------------------- 当前牌: 1w,2w,3w,4w,5w,6w,9w,9w,2d,3d,4d,5d,7d,8d, 十三幺: 1w,2w,3w,4w,5w,6w,2d,3d,4d,5d,7d,8d, 2 * 9w true ------------------------------- 当前牌: 2w,2w,2w,4w,4w,4w,5w,5w,6w,6w,7w,3d,3d, 正常胡牌: [5w6w7w],[4w5w6w],[4w4w4w],[2w2w2w],[3d3d],听4w 正常胡牌: [5w6w7w],[5w6w7w],[4w4w4w],[2w2w2w],[3d3d],听7w 正常胡牌: [5w6w7w],[4w5w6w],[4w4w],[2w2w2w],[3d3d3d],听3d ------------------------------- 当前牌: 2w,2w,2w,4w,4w,4w,5w,6w,6w,6w,7w,8w,9w, 正常胡牌: [7w8w9w],[6w6w6w],[4w4w],[3w4w5w],[2w2w2w],听3w 正常胡牌: [7w8w9w],[6w6w],[4w5w6w],[4w4w4w],[2w2w2w],听4w 正常胡牌: [7w8w9w],[6w6w6w],[5w5w],[4w4w4w],[2w2w2w],听5w 正常胡牌: [7w8w9w],[6w6w6w],[4w5w6w],[4w4w],[2w2w2w],听6w 正常胡牌: [7w8w9w],[6w6w],[5w6w7w],[4w4w4w],[2w2w2w],听7w ```

有疑问加站长微信联系(非本文作者)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1358 次点击  ∙  1 赞  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传