詳細代碼如下: package main import ( "fmt" "strings" ) func main() { s := "1w1w2d2d3d3d4w4w3w3w7d7d8d8d" mj := InitMahjong(s) mj.Print() fmt.Println(mj.Win() ...
詳細代碼如下:
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
}
結果如下:
當前牌: 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
作者:janbar
出處:https://www.cnblogs.com/janbar
本文版權歸作者和博客園所有,歡迎轉載,轉載請標明出處。喜歡我的文章請 [關註我] 吧。
如果您覺得本篇博文對您有所收穫,可點擊 [推薦] 並 [收藏]