java+麻将嵌档_麻将和牌解析算法Java实现

这个Java程序实现了麻将和牌的判断算法,包括3n+2和牌、国士无双、七对子三种牌型的检测。通过输入牌组,程序会检查是否存在和牌并返回结果。
摘要由CSDN通过智能技术生成

package com.zdg.mahjong;

public class Rule {

public String get_HuPai(String paiZu) {

String result = null;

int[] intTemp = null;

for (int i = 1; i < 40; i++) {

if (!(i == 8 || i == 9 || i == 10 || i == 20 || i == 30)) {

intTemp = zhengLi(paiZu + "," + tr2(i));

if (isHuPai(intTemp)) {

result = result + "," + tr2(i);

}

}

}

//===================打印排序后的牌组===================

System.out.print("待和牌:");

for (int n = 0; n < intTemp.length - 1; n++) {

System.out.print(tr2(intTemp[n]));

if (n != intTemp.length - 2) {

System.out.print(",");

}

}

System.out.println();

//===================打印排序后的牌组===================

if (result == null) {

//没有找到和牌

return "0";

} else {

//去除第一个逗号

return result.substring(5);

}

}

public boolean is_HuPai(String paiZu) {

int[] intTemp = zhengLi(paiZu);

//===================打印排序后的牌组===================

System.out.print("待测牌:");

for (int n = 0; n < intTemp.length; n++) {

System.out.print(tr2(intTemp[n]));

if (n != intTemp.length - 1) {

System.out.print(",");

}

}

System.out.println();

//===================打印排序后的牌组===================

return isHuPai(intTemp);

}

private int[] zhengLi(String paiZu) {

String[] strTemp = paiZu.split(",");

int[] intTemp = new int[strTemp.length];

//防止牌组超过14张,或者传入空牌组

if (strTemp.length > 14 | strTemp.length == 0) {

return null;

} else {

//String转int,便于后续使用

for (int i = 0; i < strTemp.length; i++) {

//牌组文字编号转换

intTemp[i] = tr1(strTemp[i]);

if (intTemp[i] == 0) {

//牌组不在编号范围内

return null;

}

}

//对牌组进行排序,从小到大

intTemp = xuanzePaiXu(intTemp);

//同一种牌不超4张牌检测

for (int anIntTemp : intTemp) {

if (is4(intTemp, anIntTemp)) {

} else {

return null;

}

}

return intTemp;

}

}

private boolean isHuPai(int[] paiZu) {

/*

如果是和牌,返回true

*/

int[] tempPaiZu = paiZu;//tempPaiZu是用来拆解的牌组

/*

3n+2和牌牌型

大致过程:去除将牌;剩余牌组去除刻牌;剩余牌组去除连续牌

*/

for (int a = 0; a < tempPaiZu.length - 1; a++) {

int temp1 = tempPaiZu[a];

int temp1Type = tempPaiZu[a] / 10;

if (tempPaiZu[a + 1] == temp1 & tempPaiZu[a + 1] / 10 == temp1Type) {

//找到将牌,删除,继续删除刻牌

tempPaiZu = delArr(tempPaiZu, a);

tempPaiZu = delArr(tempPaiZu, a);

if (tempPaiZu.length % 3 != 0) {

//相公牌,永不和牌

return false;

} else {

if (tempPaiZu.length == 0) {

//和牌类型:一对牌,只有两张

return true;

} else {

//去除刻牌和链牌,最多四组,四层for循环

/*

刻        刻        刻        刻

刻        刻        刻        链

刻        刻        链        刻

刻        刻        链        链

刻        链        刻        刻

刻        链        刻        链

刻        链        链        刻

刻        链        链        链

链        刻        刻        刻

链        刻        刻        链

链        刻        链        刻

链        刻        链        链

链        链        刻        刻

链        链        刻        链

链        链        链        刻

链        链        链        链

*/

int[] backPaiZu = tempPaiZu;//备份牌组

int[] result;

for (int n1=0;n1<2;n1++){

for (int n2=0;n2<2;n2++){

for (int n3=0;n3<2;n3++){

for (int n4=0;n4<2;n4++){

result = fenjiePaiZu(fenjiePaiZu(fenjiePaiZu(fenjiePaiZu(tempPaiZu, n1), n2), n3), n4);

if (result[0] == -1) {

return true;

} else if (result[0] == 0) {

tempPaiZu= backPaiZu;

}else {

return false;

}

}

}

}

}

}

//还原将牌

tempPaiZu = addArr(tempPaiZu,temp1);

tempPaiZu = addArr(tempPaiZu,temp1);

tempPaiZu=xuanzePaiXu(tempPaiZu);

}

}

}

//3n+2匹配失败

tempPaiZu = paiZu;

/*

国士无双和牌牌型

国士无双牌组只有一个对牌,其余牌全部为除对牌以外的杂牌和三花边牌,且不能重复

*/

//去除对牌的一张单牌

if (tempPaiZu.length == 14) {

for (int a = 1; a < 14; a++) {

if (tempPaiZu[a] == tempPaiZu[a - 1]) {

if (tempPaiZu[a] / 10 == 0 | tempPaiZu[a] % 10 == 1 | tempPaiZu[a] % 10 == 9) {

tempPaiZu = delArr(tempPaiZu, a);

break;

}

}

}

}

boolean isGuoShiWuShuang = false;

if (tempPaiZu.length == 13) {

isGuoShiWuShuang = true;

for (int a = 0; a < 13; a++) {

//边牌杂牌检测

if (!(tempPaiZu[a] / 10 == 0 | tempPaiZu[a] % 10 == 1 | tempPaiZu[a] % 10 == 9)) {

isGuoShiWuShuang = false;

break;

}

}

}

if (isGuoShiWuShuang) {

return true;

}

//国士无双匹配失败,还原牌组

tempPaiZu = paiZu;

/*

七对子和牌牌型

*/

boolean isQiDuiZi = false;

if (tempPaiZu.length == 14) {

int[] tempQiDuiZi = new int[7];

for (int i = 0; i < tempQiDuiZi.length; i++) {

//判断都为对牌,牌型不重复

if ((tempPaiZu[2 * i] == tempPaiZu[2 * i + 1]) & (tempPaiZu[2 * i] / 10 == tempPaiZu[2 * i + 1] / 10)) {

tempQiDuiZi[i] = tempPaiZu[2 * i];

isQiDuiZi = true;

} else {

isQiDuiZi = false;

break;

}

}

if (isQiDuiZi) {

for (int i = 1; i < 7; i++) {

//七个对子牌组没有重复

if (tempQiDuiZi[i - 1] == tempQiDuiZi[i]) {

isQiDuiZi = false;

break;

} else {

isQiDuiZi = true;

}

}

}

if (isQiDuiZi) {

return true;

}

}

/*

//七对子匹配失败,还原数组

tempPaiZu = paiZu;

*/

//所有可能都没有匹配

return false;

}

private static int[] fenjiePaiZu(int[] tempPaiZu, int type) {

/*

type==>0删除刻牌

type==>1删除链牌

fenjiePaiZu==>返回tempPaiZu,表示删除成功

fenjiePaiZu==>返回{-1},表示和牌成功

fenjiePaiZu==>返回{0},表示分解失败

*/

if (tempPaiZu[0] == -1) {

return new int[]{-1};

}

if (tempPaiZu[0] == 0) {

return new int[]{0};

}

if (type == 0) {

for (int b = 0; b < tempPaiZu.length - 2; b++) {

int temp2 = tempPaiZu[b];

int temp2Type = tempPaiZu[b] / 10;

if (tempPaiZu[b + 1] == temp2 & tempPaiZu[b + 1] / 10 == temp2Type &

tempPaiZu[b + 2] == temp2 & tempPaiZu[b + 2] / 10 == temp2Type) {

//删除刻牌

tempPaiZu = delArr(tempPaiZu, b);

tempPaiZu = delArr(tempPaiZu, b);

tempPaiZu = delArr(tempPaiZu, b);

if (tempPaiZu.length == 0) {

//和牌成立

return new int[]{-1};

}

//删除刻牌成功

return tempPaiZu;

}

}

} else if (type == 1) {

for (int b = 0; b < tempPaiZu.length - 2; b++) {

int temp2 = tempPaiZu[b];

int temp2Type = tempPaiZu[b] / 10;

for (int c = b + 1; c < tempPaiZu.length - 1; c++) {

int temp3 = tempPaiZu[c];

int temp3Type = tempPaiZu[c] / 10;

if (temp2 == temp3 - 1 & temp2Type != 0 & temp3Type != 0) {

for (int d = c + 1; d < tempPaiZu.length; d++) {

int temp4 = tempPaiZu[d];

int temp4Type = tempPaiZu[d] / 10;

if (temp3 == temp4 - 1 & temp2 == temp3 - 1 & temp4Type != 0

) {

//删除链牌

tempPaiZu = delArr(tempPaiZu, d);

tempPaiZu = delArr(tempPaiZu, c);

tempPaiZu = delArr(tempPaiZu, b);

//拆解完毕,没有剩余和牌成功

if (tempPaiZu.length == 0) {

//和牌成立

return new int[]{-1};

}

//删除刻牌成功

return tempPaiZu;

}

}

}

}

}

}

//删除失败

return new int[]{0};

}

/*

辅助方法

*/

private static int[] xuanzePaiXu(int[] arr) {

/**

* 选择排序

* 从第2-n个元素中找出最小的元素,与第1个比较交换,

* 从第3-n个元素中找出最小的元素,与第2个比较交换

* O(n*n)

*/

int temp;

int loc = 0;

for (int i = 0; i < arr.length - 1; i++) {

temp = arr[i];

for (int j = i + 1; j < arr.length; j++) {

if (arr[j] < temp) {

// 从小到大

temp = arr[j];

loc = j;

}

}

if (temp != arr[i]) {

// temp是最值

arr[loc] = arr[i];

arr[i] = temp;

} // 相等不需要交换

}

return arr;

}

private static boolean is4(int[] arr, int jiance) {

/*

检测的牌超过4张返回false

*/

int count = 0;

for (int i = 0; i < arr.length; i++) {

if (jiance == arr[i]) {

count++;

}

}

if (count > 4) {

return false;

} else {

return true;

}

}

//定长数组的长度调整

private static int[] delArr(int[] arr, int loc) {

int[] temp = new int[arr.length - 1];

System.arraycopy(arr, 0, temp, 0, loc);

System.arraycopy(arr, loc + 1, temp, loc, arr.length - loc - 1);

return temp;

}

private static int[] addArr(int[] arr, int add) {

int[] temp = new int[arr.length + 1];

System.arraycopy(arr, 0, temp, 0, arr.length);

temp[temp.length - 1] = add;

return temp;

}

//牌组编号互转:String转int

private static int tr1(String a) {

switch (a) {

case "东风":

return 1;

case "西风":

return 2;

case "南风":

return 3;

case "北风":

return 4;

case "红中":

return 5;

case "白板":

return 6;

case "发财":

return 7;

case "一万":

return 11;

case "二万":

return 12;

case "三万":

return 13;

case "四万":

return 14;

case "五万":

return 15;

case "六万":

return 16;

case "七万":

return 17;

case "八万":

return 18;

case "九万":

return 19;

case "一筒":

return 21;

case "二筒":

return 22;

case "三筒":

return 23;

case "四筒":

return 24;

case "五筒":

return 25;

case "六筒":

return 26;

case "七筒":

return 27;

case "八筒":

return 28;

case "九筒":

return 29;

case "一索":

return 31;

case "二索":

return 32;

case "三索":

return 33;

case "四索":

return 34;

case "五索":

return 35;

case "六索":

return 36;

case "七索":

return 37;

case "八索":

return 38;

case "九索":

return 39;

default:

return 0;

}

}

//牌组编号互转:int转String

private static String tr2(int a) {

switch (a) {

case 1:

return "东风";

case 2:

return "西风";

case 3:

return "南风";

case 4:

return "北风";

case 5:

return "红中";

case 6:

return "白板";

case 7:

return "发财";

case 11:

return "一万";

case 12:

return "二万";

case 13:

return "三万";

case 14:

return "四万";

case 15:

return "五万";

case 16:

return "六万";

case 17:

return "七万";

case 18:

return "八万";

case 19:

return "九万";

case 21:

return "一筒";

case 22:

return "二筒";

case 23:

return "三筒";

case 24:

return "四筒";

case 25:

return "五筒";

case 26:

return "六筒";

case 27:

return "七筒";

case 28:

return "八筒";

case 29:

return "九筒";

case 31:

return "一索";

case 32:

return "二索";

case 33:

return "三索";

case 34:

return "四索";

case 35:

return "五索";

case 36:

return "六索";

case 37:

return "七索";

case 38:

return "八索";

case 39:

return "九索";

default:

return "0";

}

}

}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值