[编程题]雀魂启动!(java实现)

小包最近迷上了一款叫做雀魂的麻将游戏,但是这个游戏规则太复杂,小包玩了几个月了还是输多赢少。
于是生气的小包根据游戏简化了一下规则发明了一种新的麻将,只留下一种花色,并且去除了一些特殊和牌方式(例如七对子等),具体的规则如下:

总共有36张牌,每张牌是1~9。每个数字4张牌。
你手里有其中的14张牌,如果这14张牌满足如下条件,即算作和牌
14张牌中有2张相同数字的牌,称为雀头。
除去上述2张牌,剩下12张牌可以组成4个顺子或刻子。顺子的意思是递增的连续3个数字牌(例如234,567等),刻子的意思是相同数字的3个数字牌(例如111,777)

例如:

1 1 1 2 2 2 6 6 6 7 7 7 9 9 可以组成1,2,6,7的4个刻子和9的雀头,可以和牌
1 1 1 1 2 2 3 3 5 6 7 7 8 9 用1做雀头,组123,123,567,789的四个顺子,可以和牌
1 1 1 2 2 2 3 3 3 5 6 7 7 9 无论用1 2 3 7哪个做雀头,都无法组成和牌的条件。

现在,小包从36张牌中抽取了13张牌,他想知道在剩下的23张牌中,再取一张牌,取到哪几种数字牌可以和牌。

输入描述:

输入只有一行,包含13个数字,用空格分隔,每个数字在1~9之间,数据保证同种数字最多出现4次。

输出描述:

输出同样是一行,包含1个或以上的数字。代表他再取到哪些牌可以和牌。若满足条件的有多种牌,请按从小到大的顺序输出。若没有满足条件的牌,请输出一个数字0

示例1

输入
1 1 1 2 2 2 5 5 5 6 6 6 9
输出
9
说明
可以组成1,2,6,7的4个刻子和9的雀头

示例2

输入
1 1 1 1 2 2 3 3 5 6 7 8 9
输出
4 7
说明
用1做雀头,组123,123,567或456,789的四个顺子

示例3

输入
1 1 1 2 2 2 3 3 3 5 7 7 9
输出
0
说明
来任何牌都无法和牌

备注:

请不要根据自己的常识为题目增加未提及的条件

对于20%的数据,保证和牌时一定是4个刻子+雀头的形式

参考代码

package com;

import java.util.ArrayList;
import java.util.Arrays;

/**
 * @Description
 * @auther lx
 * @create 2019-06-28 11:00
 */
public class 雀魂启动 {
    //判断是否和牌
    public static boolean isHe(int[] cardList) {
        int length = cardList.length;
        if (length == 0)
            return true;
        Arrays.sort(cardList);//给数组排序
        int count0 = count(cardList);

        //第一种情况:没出现雀头,且第一个数字出现的次数 >= 2,且去掉雀头剩下的数能组成和牌
        if (length % 3 != 0 && count0 >= 2 && isHe(Arrays.copyOfRange(cardList, 2, length)) == true)
            return true;
        //第二种情况:如果第一个数字出现次数 >= 3,且去掉这个刻子后剩下的能和牌
        if (count0 >= 3 && isHe(Arrays.copyOfRange(cardList, 3, length)) == true)
            return true;
        //第三种情况:如果出现顺子,且移除顺子后剩下的能和牌
        if (contains(cardList, cardList[0] + 1) && contains(cardList, cardList[0] + 2)) {
            int[] c_cardList = Arrays.copyOfRange(cardList, 1, length);
            int[] last = remove(c_cardList, cardList[0] + 1, cardList[0] + 2);
            if (isHe(last) == true)
                return true;
        }
        return false;
    }

    //移除数组内给定的两个数
    private static int[] remove(int[] cardList, int i, int i2) {
        int[] res = new int[cardList.length - 2];
        int x = 0, times1 = 0, times2 = 0;
        for (int j = 0; j < cardList.length; j++) {
            if (cardList[j] == i && times1 == 0) {
                times1++;
                continue;
            } else if (cardList[j] == i2 && times2 == 0) {
                times2++;
                continue;
            }

            res[x++] = cardList[j];
        }
        return res;
    }

    //判断数组内是否存在该数
    private static boolean contains(int[] cardList, int i) {
        for (int j = 0; j < cardList.length; j++) {
            if (cardList[j] == i)
                return true;
        }
        return false;
    }

    //统计数组内第一个数出现的次数
    private static int count(int[] cardList) {
        int res = 1;
        for (int i = 1; i < cardList.length; i++) {
            if (cardList[i] == cardList[0])
                res++;
            else
                continue;
        }
        return res;
    }

    //统计数组内某数出现的次数
    private static int timesOfI(int[] a2, int i) {
        int res = 0;
        for (int j = 0; j < a2.length; j++) {
            if (a2[j] == i)
                res++;
        }
        return res;
    }

    public static void main(String[] args) {
//        int[] a = {1,1,1,1,2,2,3,3,5,6,7,8,9};
//        int[] a = {1,1,1,2,2,2,5,5,5,6,6,6,9};
//        int[] a = {1,1,1,1,2,2,2,5,5,5,7,7,7};
        int[] a = {1, 1, 1, 2, 2, 2, 3, 3, 3, 5, 7, 7, 9};
        ArrayList<Integer> res = new ArrayList<>();
        int[] a2 = new int[a.length + 1];

        for (int i = 1; i < 10; i++) {
            for (int j = 0; j < a.length; j++) {
                a2[j] = a[j];
            }
            if (timesOfI(a2, i) == 4) {//如果该牌出现了四次,则不添加该数
                continue;
            }
            a2[a.length] = i;

            if (isHe(a2) == true)
                res.add(i);
        }

        System.out.println(res);
    }
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值