actanble

导航

爱消除破解模拟(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(",");
				}
			}
		}
	}

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




posted on 2016-07-29 23:59  白于空  阅读(245)  评论(0编辑  收藏  举报