推荐这篇日记的豆列
&&&&&&&&&&&&
&(6人关注)一、麻将规则(云南昭通麻将)
1)&&&&&&&&&“万”“筒”和“条”三房牌,各36张,共108张牌;
2)&&&&&&&&只能 “碰”“杠”“胡”,不能吃牌
3)&&&&&&&&4人进行游戏;
4)&&&&&&&&游戏开始时,庄家摸14张牌,闲家摸13张牌;
5)&&&&&&&&有4个癞子牌(坨牌:既可以作为本身牌型可以替换为任意牌)
2.游戏术语
1)&&&&&&&&坎:自己手中有三张相同的牌;
2)&&&&&&&&碰牌:自己手中有两张,别人再打出一张,则可以用两张去碰,并将这三张亮出来;
3)&&&&&&&&明杠:自己手中有一坎,别人在打出一张,则可以用三张去杠,称之为明杠,所有的杠都是从牌墙前面补牌的。
4)&&&&&&&&暗杠:自己摸到了四张相同的牌,则可以暗杠;
5)&&&&&&&&补杠:自己已经碰了的牌,自己又摸到了第4张,则可以补杠;
6)&&&&&&&&根:自己的手牌和碰牌中有四张相同的但是没杠下来的,称之为根;
7)&&&&&&&&叫:即听牌,用户当前的13张牌,再摸一张牌就可以和牌的牌型;
8)&&&&&&&&墙子:摸完牌后,翻出一张牌,放在下家的堆牌区中。
<span style="color:#)&&&&&&&&坨:摸完牌后,翻出牌墙第一张牌,定义为癞子牌。
10)&&&& 满飞满杀:坨拿去杠。
案例<span style="color:#:手上<span style="color:#个<span style="color:#条,有人打出<span style="color:#条,可以拿<span style="color:#个<span style="color:#条加<span style="color:#个坨去杠<span style="color:#条
案列<span style="color:#:已碰了<span style="color:#万,手上有坨,可以直接拿坨去杠<span style="color:#万
11)&&&& 飞碰:坨加一张单牌拿去碰的过程。
12)&&&& 亮牌:胡牌后亮出所有牌(牌桌上的玩家都可以看),剩下的继续血战。
3.胡牌规则
1)&&&&&&&&胡牌条件:缺一门成牌型即可胡牌
缺一门:游戏开始后,必须打缺一门,中途可以换打缺哪门(不是定缺),胡牌局牌时必须只有2 门或1门(筒、万、条牌型)
胡牌的基本牌型:
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&i.&&&&&&&&&&&&&11、123、123、123、123;
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ii.&&&&&&&&&&&&&11、123、123、123、111/1111(下同);
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&iii.&&&&&&&&&&&&&11、123、123、111、111;
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&iv.&&&&&&&&&&&&&11、123、111、111、111;
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&v.&&&&&&&&&&&&&11、111、111、111、111;
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&vi.&&&&&&&&&&&&&11、22、33、44、55、66、77;
正常普通的和牌,所谓的平胡
手上有杠的牌型
庄家起手牌就和牌
庄家打出的第一手牌被闲家和
只有一种花色的牌型
玩家杠了之后摸起来那张牌点的炮
玩家杠了以后自摸,无论暗杠、明杠、加杠都相当于自摸
和别人补杠的杠牌(不是补杠后摸得那张)
11、111、111、111、111的牌型
11、22、33、44、55、66、77的牌型
11、22、33、44、55、6666的牌型
&二、麻将算法设计(二维数组形式)
1.类型定义(类型*10)
万&& 10 (万牌的张数) & & &
& & & &11——19 & & & & &一万-九万
筒&& 20&(筒牌的张数)
21——29 & &1筒 - 9筒
条&& 30&(条子牌的张数)
31——31 & 1条 - 9条 &
风牌 40(目前无风牌)41——49 &东南西北中发白 &&
2.牌下标定义
(1)万字牌的对应
4张1万 11 &11 11 &11
4张2万 12 &12 12 &12
4张3万 13 &13 13 &13
4张4万 14 &14 14 &14
4张5万 15 &15 15 &15
4张6万 16 &16 16 &16
4张7万 17 &17 17 &17
4张8万 18 &18 18 &18
4张9万 19 &19 19 &19
3.初始化牌和发牌
1)把所有牌放到牌堆
* 初始化麻将
public List&Integer& initAllPai() {
List&Integer& allPai = new LinkedList&&();
for (int i = 11; i & 40; i++) {
if (i % 10 == 0) {
for (int j = 0; j & 4; j++) {
allPai.add(i);
return allP
2)发牌,发四份牌
* @param initAllPai
public List&List&Integer&& faPai(List&Integer& initAllPai) {
// 洗牌 打乱顺序
Collections.shuffle(initAllPai);
List&List&Integer&& paiLists = new ArrayList&&();
for (int j = 0; j & 4; j++) {
List&Integer& pais = new ArrayList&&();
for (int i = 0; i & 13; i++) {
//从牌堆中移除一张牌
Integer remove = initAllPai.remove(0);
pais.add(remove);
paiLists.add(pais);
return paiL
3)把牌分成二维数组判断能否胡牌、杠牌、碰牌
* 牌的类型 一万-九万 11 - 19 一筒-九筒 21 - 29 一索-九索 31-39 将牌转换为二维数组
* 首位是牌型总数
* @param list
public static int[][] changeToArr(List&Integer& list) {
int[][] allPai = new int[4][10];
for (int i = 0; i & list.size(); i++) {
Integer pai = list.get(i);
switch (pai / 10) {
allPai[0][0] = allPai[0][0] + 1;
allPai[0][pai % 10] = allPai[0][pai % 10] + 1;
allPai[1][0] = allPai[1][0] + 1;
allPai[1][pai % 10] = allPai[1][pai % 10] + 1;
allPai[2][0] = allPai[2][0] + 1;
allPai[2][pai % 10] = allPai[2][pai % 10] + 1;
allPai[3][0] = allPai[3][0] + 1;
allPai[3][pai % 10] = allPai[3][pai % 10] + 1;
return allP
4.测试效果
public static void main(String[] args) {
List&Integer& initPais = initAllPai();
List&List&Integer&& paiLists = faPai(initPais);
for (List&Integer& pais : paiLists) {
System.out.println(&everyone pais :& + pais);
}所有的牌:all pai:[[36,4,4,4,4,4,4,4,4,4],[36,4,4,4,4,4,4,4,4,4],[36,4,4,4,4,4,4,4,4,4],[0,0,0,0,0,0,0,0,0,0]]
结果该玩家牌为 :[13, 21, 25, 16, 24, 12, 24, 38, 27, 36, 36, 15, 39]
缺牌类型为:0
该玩家牌为 :[33, 36, 26, 34, 36, 39, 39, 38, 19, 21, 24, 35, 26]
缺牌类型为:0
该玩家牌为 :[17, 26, 17, 22, 11, 29, 37, 18, 31, 23, 11, 13, 28]
缺牌类型为:2
该玩家牌为 :[13, 33, 25, 11, 17, 31, 37, 37, 27, 15, 12, 11, 28]
缺牌类型为:1
三)麻将业务算法
1)判断是否缺一门(只有筒、万、条中的一种或两种牌型)
* 是否缺一门
* @param paiList 玩家手中所有牌
* @param tuopai 癞子牌
public static boolean isQueYiMen(List&Integer& paiList, int tuopai) {
List&Integer& allPais = new ArrayList&&(paiList);
allPais.remove(tuopai);
int[][] allPai =
changeToArr(allPais);
if (allPai[0][0] == 0) {//万牌为0张
if (allPai[1][0] == 0) {//筒牌为0张
if (allPai[2][0] == 0) {//条牌为0张
//三种牌都不缺
2)缺的牌类型下标
* 缺的类型下标
* @param allPai
* @param tuopai
public static int choseQueType(int[][] allPai, int tuopai) {
if (allPai[0][0] == 0) {//万牌为0张,即可返回,不用执行下面代码,提高运行效率
if (allPai[1][0] == 0) {//筒牌为0张
if (allPai[2][0] == 0) {//条牌为0张
int yu = tuopai / 10 - 1;
int mod = tuopai % 10;
int num = allPai[yu][mod];//癞子牌的号码,癞子牌不算一种牌类型
int index = 0;
for (int count = 0; count & 2; count++) {//遍历移除癞子牌三种类型牌的数量
int last = allPai[index][0];
int next = allPai[count + 1][0];
// 除去坨牌的数量
if (index == yu) {
last = last -
if (next == yu) {
next = next -
if (next & last) {
index = count + 1;
3)能否杠牌
* 判断能否杠牌
* @param paiList
* @param targetPai
* @param gangType
public static boolean canGang(List&Integer& paiList, int targetPai, int gangType) {
int[][] allPai =
changeToArr(paiList);
int idx = targetPai / 10;
int pos = targetPai % 10;
int yetPaiNum = allPai[idx - 1][pos];
switch (gangType) {
case 1: {// 暗杠 - 4张一样的手牌
return yetPaiNum == 4;
case 2: {// 明杠
-3张一张的手牌
return yetPaiNum == 3;
4)能否碰牌
* 判断能否碰牌
* @param allPai
* @param targetPai
public static boolean canPeng(List&Integer& paiList, int targetPai) {
int[][] allPai =
changeToArr(paiList);
int idx = targetPai / 10;
int pos = targetPai % 10;
int yetPaiNum = allPai[idx - 1][pos];
if (yetPaiNum &=2) {//手上该目标牌超过两张,可执行碰操作
5)选择打某张牌(基本)
* 根据玩家的碰杠牌选择打的牌
* @param list 手牌
* @param map
* @param tuoPai
public static int chosePai(List&Integer& list, Map&Integer, List&Integer&& map , int tuoPai){
int pai = 0;//要打出去的牌
int total = 0;//花色总数
int huaSe = 0;//记录最少的花色
List&Integer& indexList = new ArrayList&Integer&();//碰杠牌的类型集合
for(Map.Entry&Integer, List&Integer&& entry : map.entrySet()){
int key = entry.getKey();
if (indexList != null && !indexList.contains(key / 10 - 1)) {
indexList.add(key / 10 - 1);
int[][] allPai = changeToArr(list);
allPai[tuoPai/10 - 1][0] -= allPai[tuoPai/10 - 1][tuoPai % 10];
allPai[tuoPai/10 - 1][tuoPai % 10] = 0;//把癞子牌的数量置零
for(int index = 0 ; index & 3 ; index ++){//遍历三种花色牌的情况,
if (indexList.contains(index)) {
if (total == 0) {
total = allPai[index][0];
if (total & allPai[index][0]) {
total = allPai[index][0];
for(int i = 1; i & 10 ; i++){//选择最左的牌
if (allPai[huaSe][i] & 0) {
pai = (huaSe + 1) * 10 +
* @param allPai 所有手牌
public static boolean duiduiHu(int[][] allPai) {
boolean isDuizi =
if (allPai[0][0] + allPai[1][0] + allPai[2][0] != 14) {//所有手牌一共14张,对对胡有7个对子
//遍历所有手牌
for (int i = 0; i & 3; i++) {
for (int j = 1; j &= 9; j++) {
if (allPai[i][j] & 0 && (allPai[i][j] != 2&&allPai[i][j] != 4)) {
if (!isDuizi) {
if (isDuizi) {
7)麻将听牌列表
* 麻将缺什么牌 型完整
* @param allPai
public static List&Integer& quePai(int[][] allPai) {
int pai = 0;
List&Integer& tingTable = new ArrayList&&();
for (int i = 1; i &= 3; i++) {
List&Integer& duizi = new ArrayList&Integer&();
for (int j = 1; j &= 9; j++) {//遍历每一张牌,统计每张牌组合牌型
pai = 10 * i +
int yu = pai / 10 - 1;
int mod = pai % 10;
// 是否有对子
int size = allPai[yu][mod];//这种牌pai张数
if (size == 0) {
boolean hasShun = shunFilter(allPai, pai, tingTable);
if (size == 2 && !hasShun) {//没有带顺序的牌 并且是一对的
duizi.add(pai);
if (size == 2 && hasShun) {//有带顺序的牌 并且是一对的
if (!tingTable.contains(pai)) {
tingTable.add(pai);
if (size == 2) {
if (!tingTable.contains(pai)) {
tingTable.add(pai);
if (size == 3 && hasShun) {
duizi.add(pai);
if (duizi.size() & 1) {
for (Integer data : duizi) {
if (!tingTable.contains(data)) {
tingTable.add(data);
// 连续牌缺牌的整体判断
for (int i = 1; i &= 3; i++) {
Map&Integer, Integer& shun = new HashMap&Integer, Integer&();
int max = 0;
int start = 0;
int yu = i - 1;
for (int j = 1; j &= 9; j++) {
int next = 1;
for (int k = k &= 8; k++) {
if (allPai[yu][k] & 0 && allPai[yu][k + 1] & 0) {
if (next & 3) {
shun.put(start, next);
if (next & max) {
for (Map.Entry&Integer, Integer& entry : shun.entrySet()) {
for (int k = 0; k & entry.getValue(); k++) {
pai = 10 * i + entry.getKey() +
if (!tingTable.contains(pai)) {
tingTable.add(pai);
if (entry.getKey() & 1) {
pai = 10 * i + entry.getKey() - 1;
if (!tingTable.contains(pai)) {
tingTable.add(pai);
int end = entry.getKey() + entry.getValue();
if (end & 10) {
pai = 10 * i +
if (!tingTable.contains(pai)) {
tingTable.add(pai);
shun.clear();
return tingT
注:未完待续,麻将算法较为复杂的地方是听牌列表判断、能否胡牌判断、特别是有癞子牌的时候简直是噩梦
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:12602次
排名:千里之外
原创:36篇
转载:17篇
(10)(7)(35)(1) 上传我的文档
 下载
 收藏
该文档贡献者很忙,什么也没留下。
 下载此文档
正在努力加载中...
麻将牌 全副牌共有5类42种图案,136张。 (一)序数牌合计108张 1 万子牌
下载积分:200
内容提示:麻将牌 全副牌共有5类42种图案,136张。 (一)序数牌合计108张 1 万子牌
文档格式:PDF|
浏览次数:498|
上传日期: 03:49:53|
文档星级:
全文阅读已结束,如果下载本文需要使用
 200 积分
下载此文档
该用户还上传了这些文档
麻将牌 全副牌共有5类42种图案,136张。 (一)序数牌合计
官方公共微信}