麻將簡單胡牌演算法
2 * 檔名:hu.cpp *
3 * *
4 * 功 能:演示一個簡潔明瞭的遞迴函式——判斷[麻將]的和牌。 *
5 * *
7 * 讀者不難自行判斷; *
8 * 同時由於麻將的規則各不相同,也請讀者自己新增和修改。*
9 * *
10 * 2. 其他與麻將類似的遊戲,如[字牌](又稱跑鬍子、 *
11 * 二七十)等牌類遊戲,也可採用類似的判斷函式。 *
12 * *
14 * *
15 * 作 者:shyworm(怕怕蟲)&&haowu111(吳昊) *
16 * E_Mail: [email protected] *
17 **************************************************************
18
19 #include <stdio.h>
20
21int Hu(int PAI[38]); //判定是否和牌的函式 22
23int Remain(int PAI[38]); //判定還剩下多少張牌 24
25int QIDUI(int PAI[38]);//七小對的判定 26
27int SHISANYAO(int PAI[38]);//十三么的判定 28
29int main()
30 {
31// 把一副牌放在下面的數組裡,可以任意填入數字來測試函式正確與否。
32// 為了方便,PAI[0],PAI[10],PAI[20],PAI[30]都棄之不用,並且必須
33// 置為0,千萬注意!這裡是隨意的一些資料,因為沒有設定輸入函式,可以在這裡改進的 34int PAI[38] = { 0,
351,1,1,0,1,1,1,0,0, // PAI[ 1- 9] 壹萬~玖萬的個數 360,
370,0,0,0,0,3,0,0,0, // PAI[11-19] 壹銅~玖銅的個數 380,
390,0,0,0,0,0,0,0,0, // PAI[21-29] 壹條~玖條的個數 400,
410,1,1,1,0,0,0// PAI[31-37] 東南西北中發白的個數 42 };
43// 請務必先排除“七對” 和“十三么”,由於簡單,所以不提供了
44// if( QIDUI(PAI) )...
45// if( SHISANYAO(PAI) )...
46//這裡吳昊已經給出了具體的辦法,並設定在Hu(int PAI[38])函式中 47if( Hu(PAI) )
48 printf("win\n");
49else
50 printf("not win\n");
51return1;
52 }
53
54// 判斷和牌的遞迴函式,不考慮“七對” 和“十三么”。因為如果
55// 把“七對” 和“十三么”的判斷放在遞迴函式裡,將得不償失。 56
57int Hu(int PAI[38])
58 {
59 QIDUI(PAI);
60 SHISANYAO(PAI);
61int i;
62staticint JIANG = 0; // 將牌標誌 63if( !Remain(PAI) ) return1; // 遞迴退出條件:如果沒有剩牌,則和牌返回。 64for(i=1;!PAI[i]&&i<38;i++); // 找到有牌的地方,i就是當前牌, PAI[i]是個數
65 66// 4張組合(槓子) 67if ( PAI[i] == 4 ) // 如果當前牌數等於4張 68 {
69 PAI[i] = 0; // 除開全部4張牌 70if( Hu(PAI) ) return1; // 如果剩餘的牌組合成功,和牌 71 PAI[i] = 4; // 否則,取消4張組合 72 }
73// 3張組合(大對) 74if ( PAI[i] >= 3 ) // 如果當前牌不少於3張 75 {
76 PAI[i] -= 3; // 減去3張牌
80 // 2張組合(將牌) 81 if ( !JIANG && PAI[i] >= 2 ) // 如果之前沒有將牌,且當前牌不少於2張,這裡假定所有的牌都是可以作為將的 82 {
83 JIANG = 1; // 設定將牌標誌 84 PAI[i] -= 2; // 減去2張牌 85 if( Hu(PAI) ) return 1; // 如果剩餘的牌組合成功,和牌 86 PAI[i] += 2; // 取消2張組合 87 JIANG = 0; // 清除將牌標誌 88 }
89 if ( i > 30 ) return 0; // “東南西北中發白”沒有順牌組合,不和
90 91 // 順牌組合,注意是從前往後組合! 92 if( i%10 != 8 && i%10 != 9 && // 排除數值為8和9的牌 93 PAI[i+1] && PAI[i+2] ) // 如果後面有連續兩張牌 94 {
95 PAI[i]--;
96 PAI[i+1]--;
97 PAI[i+2]--; // 各牌數減1 98 if( Hu(PAI) ) return 1; // 如果剩餘的牌組合成功,和牌 99 PAI[i]++;
100 PAI[i+1]++;
101 PAI[i+2]++; // 恢復各牌數102 }
103 // 無法全部組合,不和!104 return 0;
105 }
106
107 // 檢查剩餘牌數108 int Remain(int PAI[38])
109 {
110 int sum = 0;
111 for(int i=1;i<38;i++)
112 sum +=