(dfs)mj回溯算法

HandCard.java

package com.my.mj_no_lz;

import java.util.ArrayList;

/**
 * 自己的手牌
 */
public class HandCard {
    /**
     * 自己手牌中每一张牌的张数统计
     *    如: 2代表有2张这个牌
     */
    private int[] c = new int[]{
            2, 0, 0, 0, 3, 0, 3, 0, 3,   // 万
            0, 0, 0, 0, 0, 0, 0, 1, 1,   // 饼
            0, 0, 0, 0, 0, 0, 0, 0, 0,   // 条
            0, 0, 0, 0, 0, 0, 0          // 东 西 南 北 中 发 白
                    
    };

    public ArrayList<Integer> getHuCards() {
        // TODO 调用工具函数,计算手牌
        ArrayList<Integer> huCards = Logic.cal_hu(c);
        return huCards;
    }
}

Logic.java

package com.my.mj_no_lz;

import java.util.ArrayList;

public class Logic {
    /**
     * 计算当前胡牌
     *
     * @return
     */
    public static ArrayList<Integer> cal_hu(int[] c) {
        ArrayList<Integer> ret = new ArrayList<>();

        // 每张牌挨个遍历,看是否胡这张牌
        for (int i = 0; i < 34; i++) {
            c[i]++;
            if (c[i] >= 0 && c[i] <= 4 && check(c)) {
                // TODO 胡第张牌
                ret.add(i);
            }
            c[i]--;
        }

        return ret;
    }

    /**
     * 检查当前牌手牌信息c是否胡牌
     *
     * @param c
     * @return
     */
    private static boolean check(int[] c) {
        for (int i = 0; i < 34; i++) {
            // 去掉将
            if (c[i] >= 2) {
                c[i] -= 2;
                if (search(0, c)) {
                    c[i] += 2;
                    return true;
                } else {
                    c[i] += 2;
                }
            }
        }
        return false;
    }

    /**
     * 判断当前牌能不能组成扑
     *
     * @param dep
     * @param c
     * @return
     */
    private static boolean search(int dep, int[] c) {
        for (int i = 0; i < 34; i++) {
            if (c[i] >= 3) {
                if (dep == 3) {
                    return true;
                }
                c[i] -= 3;
                if (search(dep + 1, c)) {
                    c[i] += 3;
                    return true;
                } else {
                    c[i] += 3;
                }
            }
        }

        for (int i = 0; i < 31; i++) {
            // TODO 注意连续性 9W和1饼是不能连续计算的
            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, c)) {
                    c[i]++;
                    c[i + 1]++;
                    c[i + 2]++;
                    return true;
                } else {
                    c[i]++;
                    c[i + 1]++;
                    c[i + 2]++;
                }
            }
        }

        return false;
    }
}

Main.java

package com.my.mj_no_lz;

import java.util.ArrayList;

/**
 * 不带癞子麻将胡牌算法思路:
 * 1.一个34个元素的数组,里面标记每个麻将的牌的个数
 * 2.添加一张牌
 * 3.找出将(回溯)
 * 4.找出扑(回溯)
 * 5.如果剩余牌最终为0,那么说明能胡这张牌
 */
public class Main {
    public static void main(String[] args) {
        HandCard handCard = new HandCard();

        long s = System.currentTimeMillis();

        ArrayList<Integer> huCards = handCard.getHuCards();

        long e = System.currentTimeMillis();

        System.out.println(huCards);
        System.out.println("cost=" + (e - s));
    }
}

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值