消消乐是个比较经典的游戏;这个过程的操作用计算机来模拟也比较简单,深度遍历即可。一般都能找到很好的解,下面通过穷举法寻找最优解。相关说明如下:
消消乐攻略;
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()+1View
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(","); } } } }
纯属娱乐;后期有优化再更新!