四川地方麻将具有以下特点:
1、只有条(索)、筒(饼)、万三种牌共108张,没有花、风牌和箭牌。
2、不可以吃。
3、必须缺门可胡,即胡牌的时候不能有三种花色的牌。
4、最后四张自动胡。即当牌墙只剩下最后4张的时候,如果玩家的手牌已经叫,而叫牌正好是这4张中的任意一张,那么当这张牌出现时,叫的玩家只能胡牌,而不能跳过胡牌去进入后面的查叫过程。玩家没有选择的权利。
5、一炮多响。即某个玩家打出一张牌,有不止一个的玩家要之成胡,则均可胡牌。
6、刮风下雨。刮风(明杠):直杠和面下杠。直杠就是玩家手中有三张一样的牌,当其他玩家打出了第四张一样的牌时,玩家选择的杠牌。
面下杠就是玩家已经碰了三张一样的牌时,玩家自己又摸到了第四张一样的牌,这时候选择的杠牌。直杠,立刻收取引杠者1倍点数。面下杠,立刻收取其他未胡者1倍点数。
7、留局查花猪查大叫
普通场中,流局指没人胡牌。血战场中,流局指最后还有两个人或者以上没有胡牌。
8、坐庄
非血战:第二局起点炮者坐庄,流局则连庄,人员变动则投骰。
血战:每局投骰。
9、点胡,点炮者输分,如果为杠上炮,还要将刚才所杠牌所得,转给胡牌家(如果1炮多响则胡家给多份);自摸,杠上花(实为自摸一种),未胡者输分。
10、死叫算叫,算杠收入。(有的地区不算叫或无叫不用赔死叫)
11、缺门可胡。不能吃牌。杠牌补下一张牌。一家胡了并不结束这局,未胡的玩家继续打,直到有三家胡牌或摸牌结束时游戏结束。若牌摸完时有两家或以上未胡牌,此时查叫,无叫的给有叫的赔叫。
1.牌从孤张出,弃张最易和——麻将打到中盘,听牌的时候等放炮的经验。经常打麻将的人就知道,如果听的是熟张,易和牌。越往后打,如果听牌是孤张,也容易胡牌。所以以后打麻将,尽量用别人不要的弃张听胡,那是好牌。2.审时度势,学会争和让——这是实战中的心里技巧。上桌打牌的时候,起手的牌,有没有听牌、和牌的可能,要首先做到心中有数。起手牌不错,想办法尽快听牌,起手差牌相,有时候可以提前放弃。该争不争时,不果断容易输。不适合发力的时候,没有和牌却拼命去争取和牌,一般也是枉然。
3.碰牌的学问——很多新手总是能碰就碰。我自己打牌的时候就有这种经历在刚学牌的时候特别喜欢碰,有对子这样的话来一碰一个,感觉这样比较容易胡了,但在实际上就会发现有些牌该碰有些牌不该碰。
4.上家碰完你摸牌。这是一种机遇牌。你的上家喊碰,你就可以多摸一张牌,在听胡的时候,因上家碰的次数多,你的摸牌次数就多了,弄不好就自摸胡牌了,所以称作上碰下自摸。
“麻将是一种中国古人发明的博弈游戏,牌类娱乐用具,用竹子、骨头或塑料制成的小长方块,上面刻有花纹或字样,每副136张(有的地区74张)南方麻将多八个花牌,分别是春夏秋冬,梅竹兰菊,共计144张。
不同地区的游戏规则稍有不同。麻将的牌式主要有“饼(文钱)”、“条(索子)”、“万(万贯)”等。
以前我写了一个判断麻将是否胡牌的算法,不过不支持百搭。最近有一个朋友问我,如何有百搭,算法如何写。我写了一个,贴出来,让网友看看。算法输入: 整数数组 a[0..n-1]表示一手牌,其中,n 是牌的张数,比如 14。
牌的编码可自定,比如: 101-109 表示一万到九万,
201-209表示一条到九条,
301-309表示一筒到九筒,
411,421,431,441,451,461,471表示东南西北中发白,
500表示百搭。
算法预处理:
若 n 模 3不等于 2,直接输出:牌数不对,是相公,算法结束。否则:
把百搭删除,把剩下的普通牌进行排序:
int i,m
m=0
for (i=0i<ni++)
if (a[i]不是百搭) a[m++]=a[i] // m 就是普通牌的张数
把 a 中前 m 个元素进行排序;
随后,我把 a 看成左、中、右三段,其中,左侧段表示“成牌区”,即:它们由刻、顺组成;
中段表示试探区,算法要重点处理它们;而右侧段则是“杂牌”区,即:它们由非刻非顺组成。
在算法预处理后,显然,a 的左段长度为0,中段长度是m,右段长度是0,调用下面的“理牌”算法:
LiPai(a,0,m,0,n-m)
其中,n-m是指百搭的张数。
理牌算法:
void LiPai(int a[],int LeftCount,int MidCount,int RightCount,int CountOfBaiDa)
{
if (MidCount<3) // 试探区已不足 3 张,理牌过程结束,进入“理杂牌”阶段
{
调用测试算法; // 见后文
}
else // 试探区至少 3 张,可以试着从中取出刻子和顺子
{
int * p=&a[LeftCount] // 让 p 指向试探区首张
int x=p[0] // 取出试探区首张
if (p[1]==x &&p[2]==x) // 发现一个刻子
{
LiPai(a,LeftCount+3,MidCount-3,RightCount,CountOfBaiDa) // 把刻子放到成牌区,递归地调用理牌算法
}
在 p[0],p[1],...p[MidCount-1] 中寻找 x+1 和 x+2
if (找到)
{
把 x,x+1,x+2 放入 p[0],p[1],p[2]
把剩下的牌放入 p[3],p[4],...,p[MidCount-1]中
LiPai(a,LeftCount+3,MidCount-3,RightCount,CountOfBaiDa) // 把顺子放到成牌区,递归地调用理牌算法
对p[0],p[1],...,p[MidCount-1] 排序; // 恢复原样
}
让 p[0],p[1],...p[MidCount-1] 循环左移一次; // 这样,X 就成为杂牌区左边的元素了
LiPai(a,LeftCount,MidCount-1,RightCount+1,CountOfBaiDa) // 把x放入杂牌区,递归地调用理牌算法
让 p[0],p[1],...p[MidCount-1] 循环右移一次; // 这样,X 又回到试探区最左侧了
}
上述递归算法的终止条件是 MidCount<3,当该条件满足时,调用下面算法(即上文提到的测试算法)
杂牌总张数=MidCount+RightCount // 不足 2 张的中段,实际上也是杂牌
if (CountOfBaiDa==0) // 如果没有百搭
{
if (杂牌总张数==2 &&两张杂牌相同) // 杂牌只能是一个对子,它将是麻将头
{
输出一个胡牌方案:刻、顺是 a[0],a[1],...,a[LeftCount-1],麻将头(对子)是 剩下的两张杂牌;
}
}
else // 如果有百搭, 让一张百搭配2张杂牌
{
if (杂牌总张数-2*CountOfBaiDa<=2) // 配完之后,剩下的牌数若不超过 2,则有希望胡牌,需要进一步探测
{
申请数组 b[]
把 a[LeftCount],a[LeftCount+1],...,a[m-1] 放入 b[0],b[1],...,b[MidCount+RightCount-1] 中;
把b[]排序;
LiZaPai(a,LeftCount,b,0,MidCount+RightCount,0,CountOfBaiDa) // 总杂牌区也被划分成 3 段:左段 中段 右段,见下文
释放b[]
}
}
“理杂牌”LiZaPai(...) 算法,与普通理牌算法类似,不过,它的目标是理出对子或搭子。它也把待理区划分成 3 段:
左段:成对/搭区
中段:待测区
右段:杂牌区
void LiZaPai(int a[],int OKCount,int b[],int LeftCount,int MidCount,int RightCount,int CountOfBaiDa) // OKCount 是刻子/顺子的张数,在 a 的最左侧
{
if (MidCount<2) // 待测区不足 2 张,
{
调用试配算法; // 见下文
}
else
{
int * p=&b[LeftCount] // 让 p 指向试探区;
int x=p[0]// 取出首张
if (x==p[1]) // 找到一个对子
{
LiZaPai(a,OKCount,b,LeftCount+2,MidCount-2,RightCount,CountOfBaiDa)// 递归地求解
}
在 p[1],p[2],...p[MidCount-1] 中寻找 x+1
if (找到)
{
把 x,x+1 放入 p[0],p[1]
把剩下的牌放入 p[2],p[3],...,p[MidCount-1]
LiZaPai(a,OKCount,b,LeftCount+2,MidCount-2,RightCount,CountOfBaiDa)// 递归地求解
把 p[0],p[1],...,p[MidCount-1] 排序;
}
在 p[1],p[2],...p[MidCount-1] 中寻找 x+2
if (找到)
{
把 x,x+2 放入 p[0],p[1]
把剩下的牌放入 p[2],p[3],...,p[MidCount-1]
LiZaPai(a,OKCount,b,LeftCount+2,MidCount-2,RightCount,CountOfBaiDa)// 递归地求解
把 p[0],p[1],...,p[MidCount-1] 排序;
}
让 p[0],p[1]....,p[MidCount-1] 循环左移; // x 称到杂牌区;
LiZaPai(a,OKCount,b,LeftCount,MidCount-1,RightCount+1,CountOfBaiDa)// 递归地求解
让 p[0],p[1]....,p[MidCount-1] 循环右移; // x 回到首位
}
}
试配算法如下:
杂牌总数=MidCount+RightCount // 此时,试探区成了杂牌区
if (杂牌总数==0) // 全是对子/搭子
{
for (i=0i<LeftCounti+=2)// 寻找对子
if (b[i]==b[i+1]) // 找到一个对子, 它是麻将头
{
if (LeftCount/2-1<=CountOfBaiDa) // 剩下的对子搭子必须全部由百搭配成刻/顺
{
输出一个胡牌方案:刻/顺是 a[0],a[1],...,a[OKCount-1],以及 b[0]到b[LeftCount-1] 中除去 i,i+1 两元素后, 剩下的对/搭与百搭配成的刻/顺,以及剩下的百搭组成的刻子;
麻将头是是 b[i],b[i+1]
}
}
// 现在,必须用两个百搭配成麻将头, 所有搭子要由剩下的百搭配成刻/顺
if (CountOfBaiDa>=2 &&LeftCount/2<=CountOfBaiDa-2)
{
输出一个胡牌方案:刻/顺是 a[0],a[1],...,a[OKCount-1],以及 b[0]到b[LeftCount-1] 每个对/搭与百搭配成的刻/顺,以及剩下的百搭组成的刻子;
麻将头是百搭,百搭
}
}
else
if (杂牌总数==1) // 只有一张杂牌, 此时,必须用一个百搭与此杂牌配成麻将头
{
if (CountOfBaiDa>=1 && LeftCount/2<=CountOfBaiDa-1) // 用一个百搭与杂牌配成对子,而对子/搭子的副数不能比剩下的百搭数多, 这样就可以胡牌
{
输出一个胡牌方案:刻子/顺子是 a[0],a[1],...,a[OKCount-1],以及 b[0],b[1],百搭,b[2],b[3],百搭,...b[LeftCount-2],b[LeftCount-1],百搭,以及
配完对子、刻/顺后剩下的百搭组成的刻子;
麻将头是:杂牌,百搭。
}
}
else // 有2张或以上杂牌,不胡,因为,最多只能用一个百搭+一张杂牌形成麻将头
{
}
上面算法我用 VC++ 实现,运算速度很快,一般耗时 0.04368ms。我的 CPU:2.3GHz ,i7
望采纳,谢谢
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)