题目描述麻将是一个中国原创的4人玩的游戏。这个游戏有很多变种,但本题只考虑一种有136张牌的玩法。这136张牌所包含的内容如下。饼(筒)牌:每张牌包括一系列
题目描述
麻将是一个中国原创的4人玩的游戏。这个游戏有很多变种,但本题只考虑一种有136张牌的玩法。这136张牌所包含的内容如下。
饼(筒)牌:每张牌包括一系列点,每个点代表一个铜钱。本题中用1T、2T、3T、4T、5T、6T、7T、8T、9T表示。
索(条)牌:每张牌由一系列竹棍组成,每根棍代表一挂铜钱。本题中用1S、2S、3S、4S、5S、6S、7S、8S、9S表示。
万牌:每张牌代表一万枚铜钱,如图1-14所示。本题中用1W、2W、3W、4W、5W、6W、7W、8W、9W表示。
风牌:东、南、西、北风。本题中用DONG、NAN、XI、BEI表示。
箭牌:中、发、白。本题中用ZHONG、FA、BAI表示。
总共有9×3+4+3=34种牌,每种4张,一共有136张牌。
其实麻将中还有如图1-17所示的8张花牌,所以共有136 + 8 = 144张牌,但是本题中不予考虑。
中国麻将的规则十分复杂,,本题中只需考虑部分规则。在本题中,手牌(即每个人手里的牌)总是有13张。如果多了某张牌以后,整副牌可以拆成一个将(两张相同的牌)、0个或多个刻子(3张相同的牌)和0个或多个顺子(3张同花相连的牌。注意,风牌和箭牌不能形成顺子),我们就说这手牌“听”这张牌,即拿到那张牌以后就赢了,称为“和”(实战中还要考虑番数和特殊和法,在本题中可以忽略)。
输入格式
输入数据最多50组。每组数据由一行13张牌给出,输入保证给出的牌是合法的。输入结束标记为一行单个0。
输出
对于每组数据,输出所有“听”的牌,按照描述中的顺序列出(1T-9T,1S-9S,1W-9W,DONG,NAN,XI,BEI,ZHONG,FA,BAI)。每张牌最多被列出一次。如果没有“听”牌,输出Not ready。
样例输入
1S
1S
2T
2T
2T
3S
3S
3S
4T
4T
4T
5S
5S
样例输出
Case:1
1S
5S
import java.util.Arrays;
import java.util.Scanner;
public class Main {
private final static String[] mahjong = { "1T", "2T", "3T", "4T", "5T",
"6T", "7T", "8T", "9T", "1S", "2S", "3S", "4S", "5S", "6S", "7S",
"8S", "9S", "1W", "2W", "3W", "4W", "5W", "6W", "7W", "8W", "9W",
"DONG", "NAN", "XI", "BEI", "ZHONG", "FA", "BAI" };
private static int[] c = new int[34];
// 只在预处理调用,因此速度无关紧要
// 麻将列序号
public static int convert(String s) {
for (int i = 0; i < 34; i++)
if (s.equals(mahjong[i]))
return i;
return -1;
}
// 回溯法递归过程
// 遍历判断顺子和刻子,每当判断成立,相应麻将牌c[i]减一,继续递归调用search(int dep),若和了,那么dep=3。
private static boolean search(int dep) {
int i;
// 判读刻子
for (i = 0; i < 34; i++)
if (c[i] >= 3) {
if (dep == 3)
return true;
c[i] -= 3;
if (search(dep + 1))
return true;
c[i] += 3;
}
// 判断顺子
for (i = 0; i <= 24; i++)
if (i % 9 <= 6 && c[i] >= 1 && c[i + 1] >= 1 && c[i + 2] >= 1) {
if (dep == 3)
return true;
c[i]--;
c[i + 1]--;
c[i + 2]--;
if (search(dep + 1))
return true;
c[i]++;
c[i + 1]++;
c[i + 2]++;
}
return false;
}
// 判断是否和了
// 暴力找出所有的将牌,再根据各个将牌找出刻子和顺子。
private static boolean check() {
int i;
for (i = 0; i < 34; i++) {
if (c[i] >= 2) {
c[i] -= 2;
if (search(0))
return true;
c[i] += 2;
}
}
return false;
}
public static void main(String[] args) {
int caseno = 0, i, j;
boolean ok;
String s;
int mj[] = new int[15];
Scanner cin = new Scanner(System.in);
while (cin.hasNext()) {
s = cin.nextLine();
if (s.charAt(0) == '0')
break;
System.out.print("Case:" + (++caseno));
mj[0] = convert(s);
for (i = 1; i < 13; i++) {
s = cin.nextLine();
mj[i] = convert(s);
// System.out.println(mahjong[mj[i]]);
}
ok = false;
for (i = 0; i < 34; i++) {
Arrays.fill(c, 0);// 清零
for (j = 0; j < 13; j++)
c[mj[j]]++;
if (c[i] >= 4)
continue;
c[i]++;//假设摸了这张牌
if (check()) {//和了
ok = true;
System.out.println(mahjong[i]);//那么这副牌听这个牌
}
c[i]--;
}
if (!ok)
System.out.println("not ready");
System.out.println("\n");
}
}
}