超简洁的打印行“连连看”连通判定--栈

测试截图

超简洁的打印行“连连看”连通判定--栈


实际上,这里只是试图给出判定前后点击的两个的单元格是否可以连通的一个通用算法。
连通的要求是
1、判断是否连通的始末两个单元格均不为空且值相同(即真正实现连连看的时候图片相同)
2、连通的路径上,有图片的单元格是不能通过的
3、路径不能走回头路,也就是说在路径上节点不能重复出现
4、不可以溢出图形的边缘寻找路径

下面贴出所有所有的代码,能够直接运行测试的。
如果你想试试是不是能跑,而又不想复制粘贴下面的代码,可以直接到附件里下载。
import java.util.Random;
import java.util.Stack;

/**
 * 打印行的连连看模拟实现
 * 用到栈的FILO特性实现。
 * 
 * 模式实现说明:
 *	1、PosType类的value属性不同的值代表不同的图片,为0时表明
 * 此处的图片已经被消掉了。
 * 2、在main函数中模拟的两个例子,给出的试图用"-"来图形化显示路径,
 * 不过当路径纵向移动的时候"|"比较难给出,所以没有画出,不过一般
 * 不影响大家形象化的观察出找出的路径。
 * @author 贾懂凯
 */
public class LLKDemo {
	
	public static void main(String args[]){
		/****************************************
		 * Test1:自动生成节点值
		 * **************************************
		 */
		LLKDemo llkDemo=new LLKDemo();
		System.out.println("********************Test1:随机生成节点数据********************");
		System.out.println("初始表:");
		llkDemo.initLLKTable();
		String s=null;
		if(!llkDemo.containPath(llkDemo.llkTalbe[3][4],llkDemo.llkTalbe[3][5])){
			System.out.println("(3,4)->(3,5)没有路径可连通");
		}else{
			System.out.println("(3,4)->(3,5)"+"路径如图");
			//遍历,画出路径
			//初始化llkTable
			s=null;
			
			for(int i=0;i<llkDemo.rows;i++){
				for(int j=0;j<llkDemo.cols;j++){
					if(llkDemo.llkTalbe[i][j].getDi()==1){
						s=" "+llkDemo.llkTalbe[i][j].getSeat().getValue()+"-";
					}else if(llkDemo.llkTalbe[i][j].getDi()==3){
						s="-"+llkDemo.llkTalbe[i][j].getSeat().getValue()+" ";
					}else{
						s=" "+llkDemo.llkTalbe[i][j].getSeat().getValue()+" ";
					}
					System.out.print(s);
				}
				System.out.println();
			}
		}
		
		llkDemo=null;
		System.out.println("\r\n");
		
		
		/************************************
		 * Test2:手动配置节点值
		 * ***********************************
		 */
		llkDemo=new LLKDemo();
		System.out.println("********************Test2:手动配置节点数据********************");
		System.out.println("初始表:");
		llkDemo.imgs=4;
		llkDemo.rows=5;
		llkDemo.cols=5;
		int[][] datas={{1,3,2,1,2},
				  	{2,3,0,0,1},
				  	{3,2,0,0,0},
				  	{2,1,0,0,2},
				  	{1,3,3,1,2}};
		int[] pos=null;
		//初始化llkTable
		for(int i=0;i<llkDemo.rows;i++){
			for(int j=0;j<llkDemo.cols;j++){
				pos=new int[2];
				pos[0]=i;
				pos[1]=j;
				llkDemo.llkTalbe[i][j]=llkDemo.new Node();
				llkDemo.llkTalbe[i][j].setSeat(llkDemo.new PosType(pos,datas[i][j]));
				System.out.print(" "+llkDemo.llkTalbe[i][j].getSeat().getValue()+" ");
			}
			System.out.println();
		}
		
		
		System.out.println();
		if(!llkDemo.containPath(llkDemo.llkTalbe[1][1],llkDemo.llkTalbe[4][2])){
			System.out.println("(1,1)->(4,2)没有路径可连通");
		}else{
			System.out.println("(1,1)->(4,2)"+"路径如图");
			//遍历,画出路径
			//初始化llkTable
			s=null;
			
			for(int i=0;i<llkDemo.rows;i++){
				for(int j=0;j<llkDemo.cols;j++){
					if(llkDemo.llkTalbe[i][j].getDi()==1){
						s=" "+llkDemo.llkTalbe[i][j].getSeat().getValue()+"-";
					}else if(llkDemo.llkTalbe[i][j].getDi()==3){
						s="-"+llkDemo.llkTalbe[i][j].getSeat().getValue()+" ";
					}else{
						s=" "+llkDemo.llkTalbe[i][j].getSeat().getValue()+" ";
					}
					System.out.print(s);
				}
				System.out.println();
			}
		}
		
	}
	
	//节点(即连连看中的一个单元格)的数据结构
	private   class Node{
		private PosType seat;//坐标
		private int di=0;//下一次探索的方向标记
		public PosType getSeat() {
			return seat;
		}
		public void setSeat(PosType seat) {
			this.seat = seat;
		}
		public int getDi() {
			return di;
		}
		public void setDi(int di) {
			this.di = di;
		}
		public void incDi(){
			this.di++;
		}
	}
	//节点内部
	private  class PosType{
		public PosType(int[] pos,int v){
			this.pos=pos;
			this.value=v;
		}
		private int[] pos;//表明节点索引位置(i,j)=(pos[0],pos[1])
		public int[] getPos() {
			return pos;
		}
		public void setPos(int[] pos) {
			this.pos = pos;
		}
		public int getValue() {
			return value;
		}
		public void setValue(int value) {
			this.value = value;
		}

		private int value=0;
	}
	private int rows=8;//初始的行列数
	private int cols=8;
	private int imgs=2;//imgs-1为图片种类
	private Node[][] llkTalbe=new Node[rows][cols];
	private Stack<Node> stack=new Stack<Node>();
	
	public void initLLKTable(){
		int[] pos=null;
		Random ran=new Random();
		//初始化llkTable
		for(int i=0;i<rows;i++){
			for(int j=0;j<cols;j++){
				pos=new int[2];
				pos[0]=i;
				pos[1]=j;
				llkTalbe[i][j]=new Node();
				llkTalbe[i][j].setSeat(new PosType(pos,ran.nextInt(imgs)));
				System.out.print(" "+llkTalbe[i][j].getSeat().getValue()+" ");
			}
			System.out.println();
		}
	}
	
	/**
	 * 判断两个结点是否有路径连通
	 * @param n1
	 * @param n2
	 * @return
	 */
	public boolean containPath(Node n1,Node n2){
		this.stack=new Stack<Node>();//新的栈
		if(n1.getSeat().getValue() 
			!=  n2.getSeat().getValue() 
			|| (n1.getSeat().getValue()==0 
					&& n2.getSeat().getValue()==0)){//结点值不等,即图片不同
			return false;
		}
		
		Node curNode=n1;
		Node nextNode=null;
		curNode.incDi();//下一个探索方向
		this.stack.push(curNode);
		nextNode=this.nextPos(curNode);
		do{
			if(nextNode!=null && (nextNode==n2 || nextNode.equals(n2))){
				//到达终点
				return true;
			}
			if(pass(nextNode)){//下一个节点可以通过
				stack.push(nextNode);
				
				curNode=nextNode;
				curNode.incDi();//下一个探索方向
				nextNode=this.nextPos(curNode);
			}else{
				if(!stack.isEmpty()){
					while(curNode.getDi()==4){
						stack.pop();
						if(stack.isEmpty()){return false;}
						curNode=stack.peek();
					}
					curNode.incDi();//下一个探索方向
					nextNode=this.nextPos(curNode);
				}
			}
		}while(!this.stack.isEmpty());//空说明探索结束,没有合适路径
		
		return false;
	}
	
	private boolean pass(Node n){
		if(n==null){return false;}
		if(stack.contains(n)){return false;}
		if(n.getSeat().getValue()!=0){return false;}
		if(n.getDi()==4){return false;}
		return true;
	}
	private Node nextPos(Node n){
		int r=n.getSeat().getPos()[0];
		int c=n.getSeat().getPos()[1];
		if(r==0 || r>=rows-1 || c==0 || c>=cols-1){
			return null;
		}
		switch(n.getDi()){
			case 1://东方,列增1
				return this.llkTalbe[r][c+1];
			case 2://南方,行增1
				return this.llkTalbe[r+1][c];
			case 3://西方,列减1
				return this.llkTalbe[r][c-1];
			case 4://北方,行减1
				return this.llkTalbe[r-1][c];
		}
		return null;
	}
	
	
}

你可能感兴趣的:(C++,c,C#,单元测试,ITeye)