zoukankan      html  css  js  c++  java
  • 斗地主手牌最少手数的搜索

    基本思路:

            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]
    炸弹:[]
    三条:[]
    对子:[]



  • 相关阅读:
    Html禁止粘贴 复制 剪切
    表单标签
    自构BeanHandler(用BeansUtils)
    spring配置中引入properties
    How Subcontracting Cockpit ME2ON creates SD delivery?
    cascadia code一款很好看的微软字体
    How condition value calculated in sap
    Code in SAP query
    SO Pricing not updated for partial billing items
    Javascript learning
  • 原文地址:https://www.cnblogs.com/actanble/p/6713463.html
Copyright © 2011-2022 走看看