基本思路:

1) 先确定火箭:判断是否有大小王。 
2) 再确定炸弹:判明是否有四头。 
        3) 再确定三条和三顺:在已经确定的三条中判断是否包含相邻的三条,如果有,则将其组成三顺。注意,应该使三顺的数量尽可能大。
即如果有444555666,则将其合成一个三顺,而不是分成444555一个三顺和666一个三条。 
        4) 再确定单顺:判断单顺时必须去除四个2以外的所有炸弹。
首先判断是否存在除了三条牌(这里的三条是指所有的三条)以外的连牌。
if(havaNext)则将其提取出来。then,将剩余的牌与每一个三条(不包含三顺)进行试组合,
if能够重新组成单顺和对子,则将原有的三条取消,重新组合成连牌和单顺
        5) 再确定双顺:首先,如果两单顺牌完全重合,则将其重新组合成双顺。
其次,在除炸弹、三顺、三条、单顺以外的牌中检测是否包含双顺。如果有,将其提取出来。 
        6 再确定对子:在炸弹、三顺、三条、连牌、双顺以外的牌中检测是否存在对子,如果存在将其提取出来。 
        7) 再确定单牌:除了炸弹、三顺、三条、连牌、双顺、对子以外的所有牌张都是单牌。 
补充:
很显然,单顺和三条炸弹等的处理最追求最少手数的基础上是非常麻烦的;一种方法是穷举,二种方法是字典法,方法三就是dp问题的形式求解。
上面的4)是一种方法,另一种方法在放弃除去2王炸弹的情况下,我们可以实现的最少手数依次和放弃三条的情况下的手数做比较,最终选择其中手数最少的一种。
打分系统:并将各个牌的情况打分。这个打分系统将后面再说。

中心程序

package com.byk.play;import java.util.ArrayList;
import com.byk.ddz.PaixDic;
import com.byk.ddz.XuanPai;public class CopareShouPaiShuLiang {static int[] arr1 = XuanPai.set17Pai();static int[] arr  = new int[]{3,4,5,6,7,8,9,10,11,12,13,14,16,20,30};public static void main(String[] args) {ArrayList<PaixDic> alp1 = new ArrayList<>();ArrayList<PaixDic> alp = new ArrayList<>();int b = fangfa2(alp1);int a = fangfa1(alp);if(a>b){System.out.println("决定选择的方法"+alp);}else if(a<b){System.out.println("决定选择的方法"+alp1);}else{System.out.println("两种方法可以酌情考虑");}}public static int fangfa2(ArrayList<PaixDic> alp1) {ArrayList<Integer> alr2= new ArrayList<>();for(int i=0;i<arr1.length;i++){alr2.add(arr1[i]);}//将数组转到集合中if(pdHuoJian(alr2)){//判断火箭ArrayList<Integer> alk  = new ArrayList<>();alk.add(20);alk.add(30);removeAll(alr2, alk);PaixDic  pxdic= new PaixDic("火箭",alk);  alp1.add(pxdic);}ArrayList<PaixDic> alpk = new ArrayList<>();returnShunZi(alpk, alr2);//顺子处理alp1.addAll(alpk);returnAfterRemove(alpk,alr2);ArrayList<PaixDic> ack = returnZhaDan(alr2);//炸弹处理alp1.addAll(ack);//[炸弹,null]returnAfterRemove(ack,alr2);ArrayList<PaixDic> ack1 = return3Tiao(alr2);//三条处理alp1.addAll(ack1);returnAfterRemove(ack1,alr2);ArrayList<PaixDic> ack2 = returnDuiZi(alr2);//对子处理alp1.addAll(ack2);returnAfterRemove(ack2,alr2);ArrayList<PaixDic> alpd = returnDanZhi(alr2);//单牌处理alp1.addAll(alpd);for(PaixDic ap:alp1){System.out.println(ap);}int num  = comuShouShu(alp1);System.out.println("[火箭->顺子->炸弹->三带->对子->单牌]这样的手牌数为:"+num);return num;}public static int fangfa1(ArrayList<PaixDic> alp){ArrayList<Integer> alr2= new ArrayList<>();    for(int i=0;i<arr1.length;i++){alr2.add(arr1[i]);}//将数组转到集合中if(pdHuoJian(alr2)){//判断火箭ArrayList<Integer> alk  = new ArrayList<>();alk.add(20);alk.add(30);removeAll(alr2, alk);PaixDic  pxdic= new PaixDic("火箭",alk); alp.add(pxdic);}ArrayList<PaixDic> ack = returnZhaDan(alr2);//炸弹处理alp.addAll(ack);//[炸弹,null]returnAfterRemove(ack,alr2);ArrayList<PaixDic> ack1 = return3Tiao(alr2);//三条处理alp.addAll(ack1);returnAfterRemove(ack1,alr2);ArrayList<PaixDic> alpk = new ArrayList<>();//顺子需要自己建立一个中间字典returnShunZi(alpk, alr2);//顺子处理alp.addAll(alpk);returnAfterRemove(alpk,alr2);ArrayList<PaixDic> ack2 = returnDuiZi(alr2);//对子处理alp.addAll(ack2);returnAfterRemove(ack2,alr2);ArrayList<PaixDic> alpd = returnDanZhi(alr2);//单排处理alp.addAll(alpd);for(PaixDic ap:alp){System.out.println(ap);}int num  = comuShouShu(alp);System.out.println("[炸弹->三带->火箭->顺子->对子->个]这样的手牌数为:"+num);return num;}//在原集合中删除字典集合中出现过的元素;输入字典集合和原始整数集合。public static void returnAfterRemove(ArrayList<PaixDic> alpd,ArrayList<Integer> al){if(alpd.get(0).getAlr().isEmpty()){return;}else{for(int i=0;i<alpd.size();i++){ArrayList<Integer> alr = alpd.get(i).getAlr();//          al.removeAll(alr);removeAll(al, alr);}}}public static boolean pdHuoJian(ArrayList<Integer> alr) {int count=0;for(int i=0;i<alr.size();i++){if(alr.get(i) == 20 || alr.get(i) == 30){count++;}}if(count>1){return true;}else{return false;}}//判断炸弹并返回炸弹的个数,ps炸弹,三顺,对子都可以抽象为一个方法,略。public static ArrayList<PaixDic> returnZhaDan(ArrayList<Integer> alr){ArrayList<PaixDic> alk = new ArrayList<>();boolean flag=false;for(int i=0;i<13;i++){int count = 0;for(int j=0;j<alr.size();j++){if(alr.get(j)==arr[i]){count++;}}ArrayList<Integer>  al2= new ArrayList<>();if(count==4){flag = true;for(int k=0;k<4;k++){al2.add(arr[i]);}PaixDic pxdic = new PaixDic("炸弹",al2);alk.add(pxdic); }}if(!flag){PaixDic pxdic = new PaixDic("炸弹",new ArrayList<Integer>());alk.add(pxdic); }return alk;}//判断是否存在三条;无视d):将三条弄到一起出;判断手数的时候再判断三顺。public static ArrayList<PaixDic> return3Tiao(ArrayList<Integer> alr){ArrayList<PaixDic> alk = new ArrayList<>();boolean flag=false;for(int i=0;i<13;i++){int count = 0;for(int j=0;j<alr.size();j++){if(alr.get(j)==arr[i]){count++;}}ArrayList<Integer>  al2= new ArrayList<>();if(count==3){flag = true;for(int k=0;k<3;k++){al2.add(arr[i]);}PaixDic pxdic = new PaixDic("三条",al2);alk.add(pxdic); }}if(!flag){PaixDic pxdic = new PaixDic("三条",new ArrayList<Integer>());alk.add(pxdic); }return alk;}//逼近最后阶段,判断完单顺和双顺就基本结束了。public static void returnShunZi(ArrayList<PaixDic> alpk,ArrayList<Integer> alr){
//      ArrayList<PaixDic> alpp = new ArrayList<>();for(int i=0;i<8;i++){ArrayList<Integer> ar = new ArrayList<>();for(int j=arr[i];j<arr[i]+5;j++){ar.add(j);}//for里面装的一个5连集合。if(alr.containsAll(ar)){PaixDic pdc = new PaixDic("单顺",ar);alpk.add(pdc);removeAll(alr, ar);
//              System.out.println(alr);returnShunZi(alpk,alr);}}if(alpk.isEmpty()){PaixDic pxdic = new PaixDic("顺子",new ArrayList<Integer>());alpk.add(pxdic); return;}//在进入穷举前需要对alr自动排序;但是递归过程中会逐步遍历
//      System.out.println(alr);for(Integer i:alr){for(PaixDic pdc:alpk){//遍历每一个独立出来的元素;寻找是否存在在一个Dic的Al后添加上来if(i==(pdc.getAlr().get(pdc.getAlr().size()-1)+1)){pdc.getAlr().add(i);}}}}//建立一个自己的remove函数,只删除一套元素.public static void removeAll(ArrayList<Integer> alr,ArrayList<Integer> ar){a:for(int i=0;i<ar.size();i++){for(int j=0;j<alr.size();j++){if(ar.get(i)==alr.get(j)){alr.remove(j);continue a;}}}}//判断对子;并返回有对子的字典。public static ArrayList<PaixDic> returnDuiZi(ArrayList<Integer> alr){ArrayList<PaixDic> ald = new ArrayList<>();boolean flag=false;for(int i=0;i<13;i++){int count = 0;for(int j=0;j<alr.size();j++){if(alr.get(j)==arr[i]){count++;}}ArrayList<Integer>  al2= new ArrayList<>();if(count==2){flag = true;for(int k=0;k<2;k++){al2.add(arr[i]);}PaixDic pxdic = new PaixDic("对子",al2);ald.add(pxdic); }}if(!flag){PaixDic pxdic = new PaixDic("对子",new ArrayList<Integer>());ald.add(pxdic); }return ald;}//判断对子;并返回有对子的字典。public static ArrayList<PaixDic> returnDanZhi(ArrayList<Integer> alr){ArrayList<PaixDic> aldz = new ArrayList<>();for(int i=0;i<alr.size();i++){ArrayList<Integer> aldr = new ArrayList<>();aldr.add(alr.get(i));aldz.add(new PaixDic("单牌",aldr));}return aldz;}public static int comuShouShu(ArrayList<PaixDic> alp){int num=0;for(PaixDic dic:alp){if(!dic.getAlr().isEmpty()){num += 1;}if(dic.getPaixing().equals("三条") && !dic.getAlr().isEmpty()){num-=1;}if(dic.getPaixing().equals("炸弹") && !dic.getAlr().isEmpty()){num -= 2;}if(dic.getPaixing().equals("火箭") && !dic.getAlr().isEmpty()){num -= 2;}//因为绝对手牌的原因}return num;}
}

工具类和便于手牌类型统计建立的集合类附上。

package com.byk.ddz;import java.util.ArrayList;
/** 在54张牌中随机选出17张用数组记录*/
public class XuanPai {static int[] arr  = new int[]{3,4,5,6,7,8,9,10,11,12,13,14,16,20,30};//核心函数。10行的样子public static int[] set17Pai(){ArrayList<Integer> alr= new ArrayList<>(); for(int i=0;i<arr.length-2;i++){for(int j=0;j<4;j++){alr.add(arr[i]);}}alr.add(20);alr.add(30);int[] arr2 = new int[17];int i=0;while(i<17){int k = (int) (alr.size()*Math.random());arr2[i] = alr.get(k);alr.remove((Integer)arr2[i]);i++;}return arr2;}
}package com.byk.ddz;import java.util.ArrayList;public class PaixDic {String paixing;ArrayList<Integer> alr;public PaixDic(String paixing, ArrayList<Integer> alr) {super();this.paixing = paixing;this.alr = alr;}public PaixDic() {// TODO Auto-generated constructor stub}public String getPaixing() {return paixing;}public void setPaixing(String paixing) {this.paixing = paixing;}public ArrayList<Integer> getAlr() {return alr;}public void setAlr(ArrayList<Integer> alr) {this.alr = alr;}@Overridepublic String toString() {// TODO Auto-generated method stubreturn paixing+":"+alr;}}

给出一个执行结果:

单顺:[4, 5, 6, 7, 8, 9, 10]
单顺:[8, 9, 10, 11, 12, 13, 14]
炸弹:[]
三条:[]
对子:[]
[火箭->顺子->炸弹->三带->对子->单牌]这样的手牌数为:2
炸弹:[]
三条:[8, 8, 8]
单顺:[9, 10, 11, 12, 13, 14]
对子:[4, 4]
单牌:[5]
单牌:[7]
单牌:[6]
[炸弹->三带->火箭->顺子->对子->个]这样的手牌数为:5
决定选择的方法:
单顺:[4, 5, 6, 7, 8, 9, 10]
单顺:[8, 9, 10, 11, 12, 13, 14]
炸弹:[]
三条:[]
对子:[]

斗地主手牌最少手数的搜索相关推荐

  1. Python 三人斗地主手牌生成

    #三人斗地主手牌生成 import randomlst = list(range(2,11))+['J','Q','K','A'] colors = ['♥', '♦', '♣', '♠'] joke ...

  2. 斗地主手牌(水贴ψ(*`ー´)ψ)

    扑克牌 斗地主手牌 斗地主手牌 代码实现: //创建一副牌 ArrayList<String> list = new ArrayList<>();String[] colors ...

  3. DFS+DP搜索斗地主玩家手牌最少出牌次数

    最近在做一个炸弹斗地主的项目,需要搭建一个离线牌库,筛牌就成为了重点.其实别的部门有这块的功能代码,但是时间充裕,自己做做,效率不行的话,再想办法拿人家的代码吧... 与普通斗地主的出牌规则一致: 牌 ...

  4. 斗地主农民手牌的58684015种可能性

    # -*- coding: utf-8 -*-''' 计算斗地主一手牌的所有可能组合数原创算法 '''#计算Cn x 组合数 def get_combinations(n , x) :t1 = n - ...

  5. 斗地主发牌器,并对玩家手牌进行从大到小的排序C++

    因为我想要按照斗地主的规则对用户手牌进行排序,我直接用一个string数组hand[]来储存所有的牌,并从大到小排序,接下来我只需要保存每一个用户所拥有的hand数组的下标,并将下标由大到小排序,输出 ...

  6. python斗地主出牌算法_斗地主之用蚁群算法整理牌型:如何进行牌力估计

    我们在前面讲到过,各牌手的牌力估计就是我们在用蚁群算法构造最优牌型时的启发性知识.启发性知识其实就是我们利用自己的经验对事物做出的判优性评估,或者说就是对事物价值的判断. 原则上,应用蚁群算法需要用到 ...

  7. rust原地复活_植物大战僵尸英雄锈铁螺栓新手卡组推荐 rustbolt多手牌陷阱恢复后期流卡组...

    今天Remilia为大家带来的是植物大战僵尸英雄电磁舞王新手卡组,这套卡组全部使用基础卡牌组成,并且拥有超强的战斗力,不会组卡牌的小伙伴来跟着Remilia一起看看吧! ▍新手卡组推荐 [陷阱卡牌]横 ...

  8. rust石墙掉耐久_植物大战僵尸英雄锈铁螺栓新手卡组推荐 rustbolt多手牌陷阱恢复后期流卡组...

    今天Remilia为大家带来的是植物大战僵尸英雄电磁舞王新手卡组,这套卡组全部使用基础卡牌组成,并且拥有超强的战斗力,不会组卡牌的小伙伴来跟着Remilia一起看看吧! ▍新手卡组推荐 [陷阱卡牌]横 ...

  9. 基于opencv2的斗地主记牌器(python)

    一.开发该系统软件环境及使用的技术说明 开发环境:JetBrains PyCharm Community Edition 2019.2.5 x64 远端仓库:GitHub 语言版本:python3.7 ...

最新文章

  1. SQL 利用merge 同步数据库之间表的数据
  2. Wireless-N Configuration
  3. 对话中小企业信息化甲乙方(2)
  4. 怎么通过华为三层交换机实现VLAN间通信?
  5. 【杂谈】从医学专业转行到AI,独立完成项目到获得加州理工大学读研推荐,我如何与有三AI结缘...
  6. Service Request Account field in CRM and C4C
  7. Go语言开发环境配置
  8. work节点使用外部包_AFLSmart工具简单分析及使用介绍
  9. 无心剑随感《最完美的图形——圆》
  10. 遥感数字图像处理——第三章——空间域处理方法
  11. python 序列去重并保持原始顺序
  12. mysql 基础 红黑联盟_[转载]mysql日期加减 – mysql数据库栏目 – 红黑联盟
  13. ubuntu16 坚果云不能打开
  14. 中国BBS社区前10名
  15. 趋势 | 极简再见,极繁回潮
  16. 解决Win10锁屏超1分钟,显示器关闭问题
  17. 字母概率C语言,从26个英文字母中任意选一个,是C或D的概率是()。
  18. Shell - mkdir
  19. 【洛谷P2357】守墓人【线段树】
  20. 机器学习吃瓜(西瓜、南瓜书)笔记 task03-第四章决策树

热门文章

  1. pc端和移动端两套样式在vue中的切换
  2. 仿QQ设置头像(拍照/选择照片)
  3. 中学-综合素质【8】
  4. 阳光保险港交所上市:年营收1200亿 市值超600亿港元
  5. h5中performance.timing轻松获取网页各个数据 如dom加载时间 渲染时长 加载完触发时间...
  6. 使用springboot写一个记事小账本
  7. 新浪天气预报代码及城市代码
  8. 你的Android手机能投屏到电脑上吗?方法我都给你列出来了
  9. FontStruct——制作你自己的个性化字体
  10. windows10怎么用cmd编译C语言,win10怎么样使用cmd来运行程序