c 胡牌 聽牌

2021-09-26 16:28:19 字數 4077 閱讀 2381

生成一張n維的圖去分析, 比較容易一些

這個是2人麻將, 4人麻將改幾個數值就可以用了;

判斷胡牌的思路:

比如 :

1~9萬, 0x01 ~ 0x09  ;

1~9筒 , 0x11~0x19;

1~9條 , 0x21~ 0x29;

東南西北中發白 : 0x31 ~ 0x39

花牌 : 0x41 ~ 0x48;

弄乙個 arr[4][10] 的陣列, 做乙個牌型的圖出來 , 不算花牌;

然後比如 筒子 :  (0x11&0xf0 << 4) 作為花色 , 0x11 & 0x0f 作為值[不論什麼牌都是 1 ~ 9 ];

陣列的第乙個索引放花色 ; 這個花色索引對應的陣列首個元素存放此花色的數量

現在比如有 2萬,2萬, 3萬 ,1筒

在陣列應是 arr[0][0] == 3, arr[1][0] == 1;  第0個元素作為此花色的總數量, 他們的值統計在對應的陣列上;

因此 arr[0][2]  == 2 ,  arr[1][1] == 1. 

這樣每個索引都記錄此牌的數量; 如此就知道了所有的牌;

胡牌首先判斷7個一對, 有了這個陣列, 直接迴圈就可以得出結果;

然後迴圈每個花色的首元素, 通過牌的數量來判斷, 如果要胡牌必然有一對, 其他的牌都是3個一組.

因此對 3 除餘. 如果餘數是 1 則不滿足胡牌的牌數, 如果是 2 則表示 此花色或許在此行中 ;

接下去就要分析牌型了, 寫乙個能判斷順子和剋子的函式, 除了一對所在的行, 把其他行都扔進去看看能否滿足牌型;

之後要對 一對所在的行做特殊處理, 因為你無法知道一對是什麼樣的牌型 1[11] / [11]

因此需要每次要在對應的索引上 減去2, 然後把剩餘的牌去匹配是否是順子/剋子; 

如果能匹配成功, 最後能得到 [一對] 所在的 索引;  

下面的**只用了乙個arr[2][10] 來做演示 , arr[0] 筒子, arr[1] 風牌;

**裡全是注釋;

//先寫2個後面要用的函式

int getcolor(char card)

int getvalue(char card)

//檢查是否是花牌

bool isflowercard(char card)

//所有的牌都是16進製制

//每個陣列第乙個元素用於計算此種花色含有多少張牌

//此分布圖, 不允許放入花牌,花牌先成其他牌後再使用此圖即可

struct card_pic

}bool gen_pic(char * arr, int len)

++cards[color_index][0]; //增加此牌型的數量

++cards[color_index][value]; //增加此牌的數量

}return true;

}void reset()

void show()

cout << endl;

}cout << endl;

}//復原牌, hand_cars 能足夠長度 14就ok,我就不做檢測了

int restorecards(char * hand_cards)}}

}std::sort(hand_cards, hand_cards + count);

return count;

}//檢查七對

bool check_qidui()

else if(cards[i][j] == 4)}}

return qidui_count == 7;

}//胡

bool checkhu()

//檢測是否滿足33332模型

//任意一行上必然一對, 因此從總數上 cards[i]%3 == 2 ,就是 " 一對"所在的位置

//第一遍只從數量上來分析一次, 把不能滿足此條件的先過濾掉

int ret = 0;

bool dui_exists = 0;

int dui_pos = 0;

for(int i = 0 ; i < 2; ++i)

else if( 2 == ret)

}//現在開始分析牌面,由於一對所在的行,會影響檢測,把一對所在的行放到後面檢測

//因此先把別的行進行檢測 , 別的行必然要滿足3333/333/33/3 這種模型

for(int i = 0 ; i < 2; ++i)

}//到此,證明別的行 都能滿足胡的條件了, 現在開始檢測 一對所在的行

//由於這個[一對]不知道是怎麼形成的,可能是1[11],也可以是11[11],或11,因此要迴圈

bool find = false;

int pos = -1;

for(int i = 1; i < 10 ; ++i)

}cout << "yi dui :" << pos << endl;

return find;

}//用於分析第n行的順子和剋子

//遞迴呼叫 . 每次把找到的順子或克子 減掉後[ -3 ], 在去遞迴,直到把此行的牌都減完,說明此行可以

bool fenxi_shunzi_kezi(int index , bool isfengpai)

bool ret = false;

int start_index = 0;

//找到第乙個不為0的,開始處理順子和剋子

for(int i = 1 ; i < 10 ; ++i)

}//如果首先找到的是剋子

if(cards[index][start_index] >=3)

//由於風牌[東南西北中發白] 沒有順子,因此首先判斷是不是風牌

if( !isfengpai && start_index < 8 &&

cards[index][start_index] > 0 &&

cards[index][start_index + 1] > 0 &&

cards[index][start_index + 2] > 0)

return ret;

}};bool checkting(char * leftcards, int leftcards_len , char * handcards, int handcards_len); //把花牌都刪去

int left_count = 0;

for(int i = 0 ; i < leftcards_len ; ++i)

}setsets(filter_leftcards, filter_leftcards+left_count);

set::iterator iter_end = sets.end();

set::iterator iter_begin = sets.begin();

char cp_handcards[14];

memset(cp_handcards,0,sizeof(cp_handcards));

memcpy(cp_handcards,handcards,handcards_len);

cout << "handcards:" << endl;

for(int i = 0; i < handcards_len ; ++ i)

cout << endl;

static card_pic pic;

int icount = 0 ;

for(; iter_begin != iter_end ; ++iter_begin)

if(pic.checkhu())

cp_handcards[i] = restore_card;}}

return false;

}//測試

int main(int argc, char* ar**)

; char arr[14] = ;

int len = 14;

char qarr[14] = ;

card_pic pic(qarr,len);

pic.show();

cout << (pic.checkhu() ? "hu!" : "nooooooooooo") << endl;

checkting(a,72,qarr,14);

return 0;

}

麻將胡牌演算法 C

這裡只介紹普通的麻將胡牌演算法,也就是7個對子或者 1個對子 3 n n 三個順子或者三個一樣的 其中字牌 東南西北中發白 不能算順子。首先對於每張牌 它有牌的的數字 1 9,牌的種類 萬條筒以及字 所以先封裝乙個牌的包裝類。如果要和伺服器互動的話就應該給這個類序列化 即加上system.seria...

麻將胡牌判決

胡牌有以下幾種情況 1 乙個對子 4組 3個相同的牌或者順子。只有m s p是可以構成順子的。東西南北這樣的牌沒有順子。2 7個不同的對子。3 1m,9m,1p,9p,1s,9s,1c,2c,3c,4c,5c,6c,7c.這13種牌每種都有,而且僅有這13種牌。肯定是有一種2張。其他的1張。首先是列...

麻將胡牌判決

就是給了13張牌。問增加哪些牌可以胡牌。胡牌有以下幾種情況 1 乙個對子 4組 3個相同的牌或者順子。只有m s p是可以構成順子的。東西南北這樣的牌沒有順子。2 7個不同的對子。3 1m,9m,1p,9p,1s,9s,1c,2c,3c,4c,5c,6c,7c.這13種牌每種都有,而且僅有這13種牌...