java自定义栈实现简单迷宫

本文介绍了一个Java实现的栈解决迷宫问题的程序。通过自定义的栈元素类和位置类,程序利用栈来存储迷宫路径,并通过递归回溯找到可行路径。在过程中,作者强调了理解引用类型变量的重要性,避免了因修改引用对象而导致的错误。程序通过检查当前位置是否可以通过并更新足迹图谱,判断迷宫路径的可行性。
摘要由CSDN通过智能技术生成
package stack;



import stack.sq.SqStack;
/**
 * 
 * @author 半步疯子
 * 通过迷宫求解,其中出错的问题就是对引用类型变量的理解不够深刻
 * 传值和传地址不够明确
 * 即使我的引用类型变量被压入栈中,但是我的curpos指向的同样还是对应e中的seat的对象
 * 所以这里不能在原来的nextPos方法上进行修改,修改了之后栈中前一步的position也跟着改变了
 * 如果当前步(curpos)不是可通过的区域,那么就会pop到上一步,但是上一步已经被修改到和
 * 当前位置相同的position了,所以就会造成对角线可通过的情况(因为当前是站在墙“1”上的)
 * 0 1 1 1 1 
 * 1 0 1 1 1(对角线通过,两个0通过;但是迷宫规则,对角线是不能通过的)
 */
public class StackSolveMaze {
	
	/**
	 * 位置坐标
	 * @author Administrator
	 * 
	 */
	private class Position {
		// 非静态内部类中不能放静态的字段 static x static y
		/*
		 * int x;
		 * int y;
		 * 这里的x和y与传统意义上的x和y不同
		 * 为了避免混淆,用row和loc的点定义
		 * 这里的x等价于row(行)
		 * 这里的y等价于col(列)
		 * 行号x和列号y刚好与传统的x、y相反
		 * 
		 */
		int row; 
		int col;
	}

	/**
	 * 栈中的元素类型
	 * @author Administrator
	 * 
	 */
	private class StackElem {
		int ord; // 通道块在路径上的 序号
		Position seat; // 通道块在迷宫中的 坐标位置
		int direction; // 从该通道块走向下一个通道块的 方向
	}

	/**
	 * 存放经过路径的栈
	 */
	SqStack<StackElem> stack = new SqStack<StackElem>();
	private SqStack<StackElem> getStack() {
		return stack;
	}
	
	/**
	 * 存放走过每个点的是否通过的图谱
	 */
	int[][] footPrint = new int[10][10];
	private int[][] getPrintFoot() {
		return footPrint;
	}
	
	/**
	 * 原来的迷宫的图
	 */ 
	static int[][] maze = { 
			{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
			{ 1, 0, 0, 1, 0, 0, 0, 1, 0, 1 }, 
			{ 1, 0, 0, 1, 0, 0, 0, 1, 0, 1 },
			{ 1, 0, 0, 0, 0, 1, 1, 0, 0, 1 }, 
			{ 1, 0, 1, 1, 1, 0, 0, 0, 0, 1 },
			{ 1, 0, 0, 0, 1, 0, 0, 0, 0, 1 }, 
			{ 1, 0, 1, 0, 0, 0, 1, 0, 0, 1 },
			{ 1, 0, 1, 1, 1, 0, 1, 1, 0, 1 }, 
			{ 1, 1, 0, 0, 0, 0, 0, 0, 0, 1 },
			{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, 
			};

	/**
	 * 
	 * @param pos
	 *            位置坐标对象
	 * @return 是否可以通过
	 */
	boolean Pass(Position pos) {
		// if(maze[pos.row][pos.col])
			
		/*
		 * maze中的1表示不可通过 footPrint中的1表示可以走 (1为基础值,如果通过则--,如果最后pop则+=2) 0 1 2
		 * 通过未返回 可通过 通过但是倒回
		 */
		if (maze[pos.row][pos.col] != 1 && footPrint[pos.row][pos.col] == 1)
			return true;
		return false;
	}
	
	/*
	0-------------y col(i)列
	|
	|
	|
	|
	x
	row(j)行
	*/
	Position nextPos(Position curpos, int direction) {
		/*
		 * 这里应该把向南和向向东分开到四个方向最开始的位置
		 * 因为只有向东和向南才是有效前进
		 * 这样可以达到优化
		 * 假如:
		 * 		east = 1;
		 * 		south = 2;
		 * 		west = 3; 
		 * 		north = 4;
		 * 		我当前位置的后一个位置不能通过
		 */
		final int east = 1;
		final int south = 2;
		final int west = 3;
		final int north = 4;
		/*       4        
		 *   3       1
		 *       2
		 */
		//  搞清楚向南和向东的关系
		Position pos = new Position();
		pos.col = curpos.col;
		pos.row = curpos.row;
		if (direction == east)
			pos.col++;
		if (direction == south)
			pos.row++;
		if (direction == west)
			pos.col--;
		if (direction == north)
			pos.row--;	
		return pos;
	}

	boolean mazePath(Position start, Position end) {
		Position curpos = start;
		int curstep = 1;
		SqStack<StackElem> stack = new SqStack<StackElem>();
		// int direction = 1;
		StackElem e;
		for (int i = 0; i < 10; i++)
			for (int j = 0; j < 10; j++)
				footPrint[i][j] = 1;
		do {
			// 当前的位置可以通过
			// 没有走过的位置
			if (Pass(curpos)) {
				footPrint[curpos.row][curpos.col] = 0; // 留下足迹
				e = new StackElem();
				e.ord = curstep;
				e.seat = curpos;
				e.direction = 1;
				System.out.println("第" + e.ord + "步:" + e.seat.row + "行, " + e.seat.col+"列");
				stack.push(e); // 将该点压入栈中
				if (curpos.row == end.row && curpos.col == end.col) {
					this.stack = stack;
					return true; // 若该点为终点,退出
				}

				curpos = nextPos(curpos, 1);
				/*
				 * 默认的寻找方向是向东的
				 */
				curstep++; // 探索下一步
			}else {
				if (!stack.empty()) {  
					e = stack.pop();
					// 若没有这个点,进行回溯
					while (4 == e.direction && !stack.empty()) {
						footPrint[e.seat.row][e.seat.col] = 2;
						// 留下不可通过的标记
						e = stack.pop(); // 退回一步
					}
					// 变换方向
					if (e.direction < 4) {
						e.direction++;
						stack.push(e);
						curpos = nextPos(e.seat, e.direction);
						// 更新下一个点的信息
					}
				}
			}
		} while (!stack.empty());
		return false;
	}
	
	
	public static void main(String[] args) {
		StackSolveMaze ma = new StackSolveMaze();

		StackSolveMaze.Position start = ma.new Position();
		StackSolveMaze.Position end = ma.new Position();
		start.row = 1;
		start.col = 1;
		end.row = 8;
		end.col = 8;
		if (ma.mazePath(start, end)) {
			System.out.println("迷宫可以通过");
		} else {
			System.out.println("迷宫不可通过");
		}
		System.out.println("查看路径的情况:(0表示走过,2表示走过但是不可取):");
		int[][] foot = ma.getPrintFoot();
		for (int i = 0; i < 10; i++) {
			for (int j = 0; j < 10; j++) {
				System.out.print(foot[i][j] + " ");
			}
			System.out.println();
		}

		System.out.println("迷宫图为:");
		for (int row = 0; row < 10; row++) {
			for (int loc = 0; loc < 10; loc++) {
				System.out.print(maze[row][loc] + " ");
			}
			System.out.println();
		}
		
		
		SqStack<StackElem> stack = ma.getStack();
		while (!stack.empty()) {
			StackElem e = (StackElem)stack.pop();
			System.out.println("第" + e.ord + "步:" + e.seat.row + "行, " + e.seat.col+"列");
		}

	}
}

package stack.sq;

import java.util.Arrays;

/**
 * 基于数组实现的顺序栈
 * 
 * top 永远指向栈顶元素之上的位置
 * top初始值为0    FILO
 * 
 * @author 半步疯子
 * @param <E>
 */
public class SqStack<E> {
    private Object[] data = null;
    private int stackSize = 0; // 栈容量
    private int addSize = 10; // 每次增加的基数  
    private int top = 0; // 栈顶指针(初始化为0,避免对后面造成影响)
    
    
    //--------------------------
    /**
     *	初始化栈操作
     *
     *	complete
     */
    public SqStack(){
        this(10); // 默认栈大小为10
    }
    public SqStack(int initialSize) throws RuntimeException{
        if(initialSize > 0){
            this.stackSize = initialSize;
            data = new Object[initialSize];
            top = 0;
        }else{ 
            throw new RuntimeException("初始化大小不合理:" + initialSize);
        }
    }
    //--------------------------
    /**
     * 获取SqStack的元素个数
     * @return 返回表长
     */
    public int stackLength() {
    	return top;
    }
    
    /**
     * 返回分配的存储长度
     * @return 返回表长
     */
    public int getCapacity() {
    	return stackSize;
    }
    /**
     * 当为空的时候,top为0
     * @return 空时为true  不空的时候为false
     * 
     * complete
     */
    public boolean empty(){
    	return top == 0;
        // return top == 0 ? true : false;
    }
    
    /**
     * 进栈的操作
     * @param e
     * 
     * complete
     */
    public void push(E e){
        if(top == stackSize)   myReallocated();  
            // throw new RuntimeException("栈已满,无法将元素入栈!");
    	 data[top++]=e; 
      
    }
    
    /**
     * 查看栈顶元素但不移除 
     * @return
     * 
     * complete
     */
    @SuppressWarnings("unchecked")
	public E peek() throws RuntimeException{
        if(0 == top){
            throw new RuntimeException("栈为空!");
        }else{
            return (E)data[top-1];
        }
    }
    
    /**
     * 弹出栈顶元素
     * @return
     * 
     * complete
     */
    @SuppressWarnings("unchecked")
	public E pop() throws RuntimeException{
        if(0 == top){
            throw new RuntimeException("栈为空!");
        }else{
        	E value = (E)data[top-1];
        	data[--top] = null;
            return value;
        }
    }
    
    /**
     * complete
     */
    private void myReallocated(){
    	/*
		Object[] temp = new Object[stackSize+addSize];
		stackSize = stackSize+addSize;
		System.arraycopy(data, 0, temp, 0, data.length);
		data = temp;
		*/
		if(top == stackSize){
			stackSize += addSize; //将栈容量加10  或增加到10
            data = Arrays.copyOf(data, stackSize);  //将原数组进行拷贝
        }
		
	}
    
    /**
     * complete
     */
    @SuppressWarnings("unchecked")
	public void stackPrint() {
    	for(int i=0; i<top; i++) {
    		System.out.println((E)data);
    	}
    }
 
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值