• 斗地主手牌最少手数的搜索


    基本思路:

            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;
    	}
    	@Override
    	public String toString() {
    		// TODO Auto-generated method stub
    		return 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]
    炸弹:[]
    三条:[]
    对子:[]



  • 相关阅读:
    linux安装kibana
    linux安装6.5.3版本elastic search
    linux非root用户安装nginx
    linux非root用户安装ncurses-devel依赖
    linux无网络情况下安装rpm包
    linux非root用户安装rabbitmq
    linux非root用户安装4.0.14版本redis
    (初)Knockout 监控属性(Observables)
    ECMAScript6
    SonarLint 代码质量管理
  • 原文地址:https://www.cnblogs.com/actanble/p/6713463.html
Copyright © 2020-2023  润新知