有一個一樣的兩張牌作將,而後剩下的組成ABC或者AAA的形式。假設每種有13張牌,都是1到9,共四種牌的類型html
package toutiao;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Scanner;
/** * 麻將遊戲 * * @author zyq */
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String string = scanner.next();
String[] s = string.split(" ");
int[] arr = new int[13];
int index = 0;
for (String temp: s) {
arr[index]=Integer.parseInt(temp);
index++;
}
Main game = new Main();
// 可能有兩組將的狀況下
// int[] arr = {1, 1, 1, 2, 2, 2, 5, 5, 5, 6, 6, 6, 9};
// int[] arr = {1, 1, 1, 2, 2, 2, 3, 3, 3, 5,6, 7, 7, 9};
// int[] arr = {1, 1, 1, 1, 3, 3, 2, 2, 5, 6, 7, 8, 9};
// int[] arr = {1, 1, 1, 1, 2, 2, 3, 3, 5, 6, 7, 8, 9};
game.detectHu(arr);
}
/** * 校驗是否能夠胡牌,而且輸出全部胡牌狀況下將和聽的牌。13張牌的數組,假設都是萬(若是包括其餘的花色其實道理同樣)。胡牌的規則爲:有一個一樣的兩張牌作將,而後剩下的組成ABC或者AAA的形式。 * * @param arr */
private void detectHu(int[] arr) {
if (arr == null || arr.length != 13) {
System.out.println("Illegal array for mahjong game!");
return;
}
// 定義一個新的數組,存儲每個萬出現的次數
int[] countArr = new int[10];
for (int i = 0; i < arr.length; i++) {
countArr[arr[i]]++;
}
// 咱們的算法思路是:先依次假設每個牌做爲將,剩下牌的再去判斷是否知足ABC的形式。
List<Hu> possibleHu = new ArrayList<Hu>(); // 存儲胡的結果列表
int[] newArrOne = new int[countArr.length];
ArrayList<Integer> res = new ArrayList<>();
for (int i = 1; i <= 9; i++) {
if (countArr[i] == 1) {
System.arraycopy(countArr, 0, newArrOne, 0, newArrOne.length);
newArrOne[i] = newArrOne[i] - 1;
if (isABCOrAAAPattern(newArrOne)) {
res.add(i);
}
}
}
for (int i = 1; i <= 9; i++) {
// 若是對應的萬字牌個數小於兩個,則不可能作將。這裏直接忽略。
if (countArr[i] < 2) {
continue;
}
// 用一個全新的數組,判斷數組中的數是否都知足ABC的形式。
int[] newArr = new int[countArr.length];
List<Integer> tings = new ArrayList<Integer>();
// 咱們能夠假設每次聽的不一樣的萬字牌,將要胡的萬字牌加進去以後,若是剩下的牌知足AAA或者ABC模式,則證實能夠聽該萬字牌
for (int j = 1; j <= 9; j++) {
System.arraycopy(countArr, 0, newArr, 0, newArr.length);
newArr[i] -= 2; // 對應作將的萬字個數減2
if (j == i && newArr[j] + 1 > 2) { // 不能超過4個牌
continue;
} else {
if (newArr[j] + 1 > 4) { // 不能超過4個牌
continue;
}
newArr[j] += 1; // 假設聽該萬字牌
}
if (isABCOrAAAPattern(newArr)) {
tings.add(j);
}
}
// 當以i爲將的時候存在能夠聽得牌,則證實該將能夠胡。將其存入結果列表
if (!tings.isEmpty()) {
Hu newOne = new Hu();
newOne.jiang = i;
newOne.tings = tings;
possibleHu.add(newOne);
}
}
if (possibleHu.isEmpty() && res.isEmpty()) {
System.out.println("0");
} else {
for (Hu one : possibleHu) {
res.addAll(one.tings);
}
Collections.sort(res);
for (int i = 0; i < res.size(); i++) {
System.out.print(res.get(i) + " ");
}
}
}
/** * 校驗數組是否知足ABC形式 * * @param newArr */
private boolean isABCOrAAAPattern(int[] newArr) {
for (int i = 0; i < newArr.length - 2; i++) {
// 一旦有3張的狀況,必然只能是AAA類型的,其餘狀況都是ABC類型的
while (newArr[i] > 0 && newArr[i] != 3) {
newArr[i] -= 1;
if (newArr[i + 1] == 0) {
return false;
} else {
newArr[i + 1] -= 1;
}
if (newArr[i + 2] == 0) {
return false;
} else {
newArr[i + 2] -= 1;
}
}
}
// 剩下的若是每一個萬字牌的個數爲0或者3。才表示能夠聽此牌。
for (int i = 0; i < newArr.length; i++) {
if (newArr[i] != 0 && newArr[i] != 3) {
return false;
}
}
return true;
}
/** * 定義胡牌的狀況,將和聽的牌 * * @author zyq */
private class Hu {
private int jiang;
private List<Integer> tings;
// 可能聽的牌不止一張
}
}
複製代碼
麻將胡牌斷定的問題java