麻將牌和牌問題

2021-07-14 04:55:29 字數 2765 閱讀 2504

在知乎上看到乙個問題,如何用程式判斷麻將牌是否和牌。和牌的規則為:14張麻將牌當中,必須要有乙個對子,即兩張相同的牌,除去對子後,剩下的牌可以組合成」a, a, a」或者」a, a+1, a+2」兩種模式的組合,其中a為某種花色的某張牌。

我的解法是:

首先定義一下麻將牌在程式中的表示方式:

把萬,餅,條分別用連續的數字代表,比如:一萬到九萬用1到9表示,一餅到九餅用11到19表示,一條到九條用21到29表示。重要的是每一種牌內部數字是連續的,不同牌之間的數字不連續。對於風和中發白,每一種都用互相之間不連續的數字表示,比如中是31,發是33,白是35等等。

由於和牌中必需要有乙個對子,所以我們的思路是,去除可能的對子,然後判斷剩下的牌是否可以表示成「a a a」或者「a a+1 a+2 」這兩種模式的組合。

具體流程是:對輸入的14張麻將牌序列進行排序,排序後,由低到高依次尋找對子,如果佇列中沒有對子,那麼肯定不是和牌,程式結束。找到對子後,將這兩張對子從序列中刪除,判斷其餘的牌是否滿足下面的條件,如果滿足,則為和牌,結束,如果不滿足,則在排序後的輸入佇列中尋找下乙個對子,重複本過程,直到條件1滿足或者搜尋到序列結尾。

條件1:序列中的元素可以分為每3個元素一組,每組元素均為「a a a」或者「a a+1 a+2 」的形式。

為了判斷乙個序列是否滿足條件1,我們觀察到以下幾個性質:

性質1:排序後的麻將牌序列可以分割成若干子串行,其中每個子串行內部的元素是連續的,且不同序列間的元素不連續(連續指相鄰元素的值相同或值相差1)。

性質2:排序後的麻將牌序列滿足條件1的充分必要條件是,按性質1分割的每個子串行均滿足條件1。

性質3:如果乙個序列滿足條件1,則按性質1分割後的子串行元素個數必定為3的整數倍。

於是,我們下一步要做的事情就是,將排序後的序列按照連續性分組,然後遞迴判斷每組是否滿足條件1,如果所有組都滿足條件1,則分組前序列也滿足條件1,否則不滿足。

為了判斷乙個連續序列是否滿足條件1,可以分幾種情況考慮:

1. 如果序列中有3個元素,則直接判斷是否屬於條件1中的兩種情況即可;

否則,設a為序列中的最小值,

2. 如果a的個數大於等於3(即3或4),則序列滿足條件1的充分必要條件是序列去掉3個a後的剩餘元素滿足條件1;

3. 如果a的個數小於3(即1或2),則序列滿足條件1的充分必要條件是序列去掉(a, a+1, a+2)後的剩餘元素滿足條件1;

時間複雜度:

由於牌的個數是常數14,且每輪迭代資料規模都會減小,因此,該演算法時間複雜度為o(1)。

**:

#include 

#include

#include

using

namespace

std;

static

vector

result;

//for debug

void prtvct(const

vector

&v, bool nxtline = true)

if (nxtline)

cout

<< endl;

}bool erase_by_val(vector

&in, int val)

}return

false;

}void push_result(int a, int b, int c)

bool shrink(vector

&in) else

}int i, t;

for (i = 0, t = in[0]; i < 3; ++i, ++t)

push_result(t-3, t-2, t-1);

return

true;

}void group(vector

&input, vector

> &grp) else

for (auto it = input.begin()+1; it != input.end(); ++it)

grp.push_back(member);

member.clear();

member.push_back(*it);

}grp.push_back(member);

}bool islegal(vector

&input)

if (input.size() == 3)

if (input[1] == input[0] + 1 && input[2] == input[1] + 1)

return

false;

}group(input, grp);

// for each group

for (auto it = grp.begin(); it != grp.end(); ++it)

if (islegal(*it) == false)

}return

true;

}bool ishu(vector

&input)

}do while (i < input.size()-1 && input[i] == input[i-1]);

}return

false;

}int main()

if (ishu(input)) else

}return

0;}

實現麻將牌發牌操作

import random class card 建立5個列表,總牌堆和四名玩家各乙個牌堆 cards player1 player2 player3 player4 def init self,name self.name name def str self return self.name 使用...

麻將胡牌判決

胡牌有以下幾種情況 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種牌...