zoukankan      html  css  js  c++  java
  • 爱消除破解模拟(NP法求解)[1]

    消消乐是个比较经典的游戏;这个过程的操作用计算机来模拟也比较简单,深度遍历即可。一般都能找到很好的解,下面通过穷举法寻找最优解。相关说明如下:

    消消乐攻略;

    1,对于5种颜色初始分别用1,2,3,4,5表示出来,这里用int和String都是一样,例子用int;当该块中的单元格被消除则该格消失。
    两个出发点,<1>根据格的属性出发,每个格看做是唯一的;一个个的进行周边匹配;遍历过程后。
    <2>常规解答---就是我们人工消消乐的解答过程
    2,解答思路;
    对于这样的一个二维矩阵;
    Class——Node生成一个类记录单元格Node
    单元格
    格属性:颜色,位置,是否被占有;
    Class——Pile我们生成一个类专门来存储块[上下左右],分为5中颜色的各个位置的块,不能分的记为
    块属性:Zip()的编号,首次遍历的位置[m,n],当前块的颜色[数字‘’],当前块的个数,消除后的得分块数的平方;块编号
    当前块的个数>1 称为有效块;
    个数 = 1 称为无效块
    Class——Zip对应的是界面的变化View类;补充:后面用View代替了,功能和思想没变;
    对于每一步的消除都会重新产生一个界面,称之为簇<由块形成>;
    簇属性:当前步数,当前分数,当前界面矩阵,已经点击过的消除块[,]集合
    ----------------------<类定义说明完毕>--------------
    访问路线:
    首先访问每个单元格;对应单元格的类进行上下左右的匹配进行分块,横向遍历,上下左右匹配,直到上下左右界都是别的颜色为止。记录出块Zip;
    若该单元格已被块占有,则跳过继续进行访问产生新的zip直到访问单元格从00->NN结束;
    ----------------------<Pile生成完毕>------------------
    3,解答过程
    消除攻略
    遍历法,对每个zip进行访问,当对应编号的zip进行消除时,挪动;产生新的团。再进行分Pile生成new Zip继续
    直到有效块的个数为0结束。
       -------------穷举解答完毕----------------------------

    程序流程
    <1>---个体_包------生成三个类----------

    <2>-----操作_包 ----操作类-------
    分块方法<计算机识别,穷举>
    消除方法:<消除之后进入下个状态>zip1 -> zip2
    afterClick<zip, int(pile的编号)> == new Zip->setElectedPiles ArrayList<Pile > --- 若size>0继续细分;否则-|return;
    //中间对Zip进行分块是否有有效块,就是有效块的个数>0;
    <Pile 的位置和得分记录下来>---------每次进行迭代遍历的时候,预计点击哪一个块的时候,记录其Pile.local,个数;局数;返回各个状态下的得分
    ---------<优化前>-------------
    对每一个待消除块进行访问,若被消除,则上面的下移即可。
    ----------<消除过程优化>------------
    当要消除一堆时;解决思路;就是对格中的纵轴进行访问;若格的下方还有格的话<列相同>,一起消;用集合来表示;
    <3>---最后一个Test类——————————

    生成Pile类的方法;

    其中Node

    int value;//颜色,对应的数值
    	int local;//位置,用代号表示;0-99
    	boolean used;//主要是在下一列的遍历中捕捉有没有被占用过

    Pile

    	Zip zip;//传递个View进来;zip_num==开始了几次消除==这是单局中的第几次视图==初始可以设为0;往后++
    	ArrayList<Node> pileLocalAl;//块里面存储的位置集合
    	int local_;//块的位置;即在遍历过程中块的代表位置,例如一排选取第一个;
    	int count; //块的个数;------->对应块的个数的平方为分数
    	int num_pile;//块的编号
    	//ps这里块的个数 == 块的编号 == 块的pileLocalAl.size()+1
    View

    	int[][] arr2;
    	ArrayList<Pile>  pile;
    	int num;
    	
    Zip ___本来设置了,但是仔细想了下,没必要,所以用View代替了;还方面输出结果

    int num_zip = 0;//初始为0,当进行了操作,消除操作,自动重新set++;
    	ArrayList<Node> view;//后续处理中所有的view都是zip的view
    	int grade = 0;
    	ArrayList<Integer> al_local;//已经点击过得local集合

    基本类处理的程序;Sheel类;对对象进行相应的处理便于后期的操作;

    package com.xiaoxiaole.Name;
    /**
     * 消消看  <生成阵>
     * -------------工具类----------------
     */
    import java.util.ArrayList;
    import java.util.HashMap;
    
    import com.xiaoxiaole.Test.Data;
    
    //建立一个sheel,对每一个数字建立一个新的Node/sheel
    
    //Note,当调用一个setNode的时候,其他的几个也要同时调用,这是一个界面需要的全部数据的操作
    	
    public class Sheel {
    	static int val;
    	public static boolean flag = true;
    	
    	//对于每一个视图都有一个sheel阵;阵里面包含所有的初始信息;zip[0]
    	public static ArrayList<Node> setNode() {
    		int[][] array2 = Data.setArray2(10);
    		ArrayList<Node> al = new ArrayList<>();
    		for (int i = 0; i < array2.length; i++) {
    			for (int j = 0; j < array2.length; j++) {
    				Node node = new Node();
    				node.setValue(array2[i][j]);
    				node.setUsed(false);
    				node.setLocal(10*i + j);
    				al.add(node);
    			}
    		}
    		return al;
    	}
    	
    	//重新建立一个HashSet能够根据local控制对象的变化。
    	public static HashMap<Integer, Node> getHsNode(ArrayList<Node> al2){
    		HashMap<Integer,Node> hm = new HashMap<>();
    		for (Node node : al2) {
    			hm.put(node.getLocal(), node);
    		}
    		return hm;
    	}
    	
    	
    	//遍历每一个Node阵;分出我们想要的块出来,,,这个Pile是个小Pile;仅仅作用于当前的zip下《这里也可以传进来一个Zip》
    	public static ArrayList<Pile> setPiles(ArrayList<Node> view){
    		System.out.println("====开始建立View下的Piles集合====");
    		ArrayList<Pile> alp = new ArrayList<>();
    		int jj = 0;
    		for (int i = 0; i < 100; i++) {
    			ArrayList<Node> al_demo = new ArrayList<Node>();//需要用到和需要返回
    			Pile pile = new Pile();
    			setPile(pile, al_demo,i, view,true);
    			if(!flag){//判断是否为有效块;若是,则添加到块集合Piles中,flag =false,表示最少有2个一起的
    				pile.setNum_pile(jj);
    				alp.add(pile);
    				jj++;
    			}
    			al_demo = null;//初始化全局变量,便于函数再次引用
    			flag = true;
    		}
    		return alp;
    	}
    	
    	public static void setPile(Pile pile,ArrayList<Node> al_demo,int local_, ArrayList<Node> view, boolean flag2){
    		Node node = view.get(local_);
    		if(node.used == true) return;
    		al_demo.add(node);//在Pile原本为空的node集合中添加Node;
    		node.setUsed(true);
    		if (flag2) {
    			val = node.value;
    			pile.setLocal_(local_);
    		}
    		int i = node.local/10;
    		int j = node.local%10;
    		int[] local_ar1 = set4cell(i, j);
    		for (int k = 0; k < local_ar1.length; k++) {
    			if (isUsual(local_ar1[k])) {
    				if(val == view.get(local_ar1[k]).value && !view.get(local_ar1[k]).used){
    					flag = false;
    					setPile(pile, al_demo,local_ar1[k], view, false);
    				}
    			}
    		}
    		pile.setPileLocalAl(al_demo);
    	}
    	
    	
    	//判断下标是在界内,专门为Pile的遍历下标预备的————这里的9是对应10*10的9;
    	public static boolean isUsual(int k){
    		if (k>=0 && k<=99) return true;
    		return false;
    	}
    	
    	public static int[] set4cell(int i,int j){
    		int[] arr1 = new int[4];
    		arr1[0] = 10*(i-1) + j;
    		arr1[1] = 10*(i+1) + j;
    		arr1[2] = 10*i + j-1;
    		arr1[3] = 10*i + j+1;
    		return arr1;
    	}
    	//setView建立View函数;
    	public static ArrayList<Node> setView(int[][] array2){
    			ArrayList<Node> view = new ArrayList<>();
    			for (int i = 0; i < array2.length; i++) {
    				for (int j = 0; j < array2.length; j++) {
    					Node node = new Node();
    					node.setValue(array2[i][j]);
    					node.setUsed(false);
    					node.setLocal(10*i + j);
    					view.add(node);
    				}
    			}
    			return view;
    	}
    }
    
    关于工具类的处理方法:

    这里有待优化,正在努力中。一般通过看程序内容就能知道具体编译的类是什么结构;所以不详述,需要优化的结构有很多,同样对于程序,我们可以不尝试用Np用其他遍历方法或者经典想法的方案也不错。

    package com.xiaoxiaole.Opreate;
    
    import java.util.ArrayList;
    
    import com.xiaoxiaole.Name.Node;
    import com.xiaoxiaole.Name.Pile;
    import com.xiaoxiaole.Name.Sheel;
    import com.xiaoxiaole.Name.View;
    import com.xiaoxiaole.Name.Zip;
    import com.xiaoxiaole.Test.Test;
    
    public class Tool {
    	public static ArrayList<Pile> piles;
    	//传递进来的是块local_,也就是可以对应点击的local,现在改local_对应的Pile要消失了
    	public static View xiaochu(View view,int num){
    		View view2 = new View();
    		ArrayList<Node> nodes = exchangeView(Sheel.setView(view.getArr2()), view.getPile().get(num));
    		view2.setNum(view.getNum()+1);
    		view2.setArr2(ExchangeNodeToArray.exchangeNodeToArray(nodes));
    		view2.setPile(Sheel.setPiles(nodes));
    		return view2;
    	}
    	//传进来的是一个pile对象和前视图;Pile为View的一个取个元素 
    	public static ArrayList<Node> exchangeView(ArrayList<Node> view1, Pile pile){
    		int[] arr = new int[10];//10列;0-9,数组值为块中对应列的待消除数
    		int[] hang_mins = new int[10];
    		for (int i = 0; i < hang_mins.length; i++) {
    			hang_mins[i] = 10;//初始化hang最下值
    		}
     		ArrayList<Node> al = pile.getPileLocalAl();
     		for (Node node : al) {//在这里多遍历了集合,应该发现一个,就删除一个
    			int hang = node.getLocal()/10;
    			int lie = node.getValue()%10;
    			for (int i = 0; i < arr.length; i++) {
    				if(hang <= hang_mins[i]){
    					hang_mins[i] = hang;
    				}
    				if(i==lie){
    					arr[lie] = arr[lie] + 1;
    				}
    			}
    		}
     		for (int i = 0; i < hang_mins.length; i++) {
     			lieXiaoChu(view1,i, arr[i], hang_mins[i]);
    		}
    		System.out.println("消除了一个Pile,产生新的视图");
    		return view1;
    	}
    	//传递进来Node视图,列lie,列中行的个数arr[lie];最小行min_hang
    	public static void lieXiaoChu(ArrayList<Node> view,int lie, int lie_count, int min_hang){
    		//消除lie_count列;所以把上方的下移 hang+lie_count -1 个单位,再把本身Node的value置为0;
    		for(int hang = 0; hang< min_hang ;hang++){
    			view.get(10*hang + lie + 10*lie_count).setValue(view.get(hang).getValue());
    		}
    		for (int hang = 0; hang < lie_count; hang++) {
    			view.get(10*hang + lie).setValue(0);
    		}
    	}
    	//传进来的是一个pile对象和前视图;还可以优化做其他的操作;
    	public static ArrayList<Node> exchangeView1(ArrayList<Node> view1, Pile pile){
    		int[] arr = new int[10];//10列;0-9,数组值为块中对应列的待消除数
    		for (int i = 0; i < arr.length; i++) {
    			int min_hang = 100;
    			int lie = 0;
    			for (Node node : pile.getPileLocalAl()) {
    				lie = node.getLocal()%10;
    				int hang = node.getLocal()/10;
    				arr[lie] = arr[lie] + 1;
    				if (hang <= min_hang) {
    					min_hang = hang;
    				}
    			}
    			lieXiaoChu(view1, lie, arr[lie], min_hang);
    		}
    		System.out.println("消除了一个Pile,产生新的视图");
    		return view1;
    	}
    }
    

    Data类;10X10消消乐随机建成;setArray2(10);附带提供一个打印二维数组的小方法。

    	public static int[][] setArray2(int n){
    		//生成5个特征元素组成的数组;
    		int[][] arr2 = new int[n][];
    		for (int i = 0; i < n; i++) {
    			arr2[i] = new int[n];
    			for (int j = 0; j < n; j++) {
    				double k = Math.random();
    				arr2[i][j] = (int)( 5* k) + 1;
    			}
    		}
    		return arr2;
    	}
    	
    	public static void printArray2(int[][] arr2){
    		System.out.print("打印型号 "+arr2.length +"X"+ arr2.length +" 的二维数组");
    		for (int i = 0; i < arr2.length; i++) {
    			System.out.println();
    			for (int j = 0; j < arr2.length; j++) {
    				System.out.print(arr2[i][j]);
    				if (j<arr2.length - 1) {
    					System.out.print(",");
    				}
    			}
    		}
    	}

    纯属娱乐;后期有优化再更新!




  • 相关阅读:
    平时代码中用不到设计模式?Are you kidding me?
    关于kubernetes我们还有什么可做的?
    R语言︱文本挖掘——词云wordcloud2包
    描述性统计分析-用脚本将统计量函数批量化&分步骤逐一写出
    R语言读写中文编码方式
    R画图中英文字体完美解决方案
    Python 和 R 数据分析/挖掘工具互查
    关于ř与tableau的集成---- k均值聚类
    tableau 连接R语言
    小识Tableau
  • 原文地址:https://www.cnblogs.com/actanble/p/6713458.html
Copyright © 2011-2022 走看看