A*自动寻路算法—java版(八方向版)

上一篇博客分享了Java版的自动寻路,但是只是上下左右四个方向的,今天把八方向的也分享出来。


既然四方向的已经成功了,那么改进成八方向的,只要注意两个地方就可以了,一个是获取四周方块的时候,一个是移动的时候。


一、获取四周方块

在autofindway.java中添加静态变量,用来标识上下左右四个方向是否可通过。

//在获取上下左右四个方块的时候,判断各个方块是否满足条件(比如:只有右边和下边的方块都可通过的时候,才能去判断右下方的方块是否满足条件,否则就是穿墙了)
	private static boolean top = false;
	private static boolean down = false;
	private static boolean left = false;
	private static boolean right = false;

在获取四周方块的方法aroundFk中,考虑左上、右上、右下、左下四个方块的判断。

其中,上下左右四个方块的判断中,如果可以通过,则将对应的方向(top/down/left/right)标识为true。只有在左边和上边方块都是true的时候,才能去判断左上方方块是否满足条件,否则就存在穿墙现象。


比如下图的四种情况,红点想要移动到左上方的绿点,只有左边和上边(①)都可穿过的时候才能正常移动过去。像图②③④这三种情况如果直接移动,都存在穿墙的现象。



代码如下:只要替换掉四方向版本中的aroundFk就可以了。

/**
	 * 获取周围方块
	 * ①判断是否超越边界
	 * ②判断是否是障碍物/已计算过的方块
	 * @param fk	中心方块 
	 * @return	周围方块结集合
	 */
	public List<FangKuaiPosition> aroundFk(FangKuaiPosition fk){
		//重置
		top = false;
		down = false;
		left = false;
		right = false;
		List<FangKuaiPosition> list = new ArrayList<FangKuaiPosition>();
		//判断上面的方块是否符合条件
		//判断是否超过越边界
		if(fk.getY() - 1 >= 0){
			FangKuaiPosition tmpFk = new FangKuaiPosition(fk.getX(), fk.getY() - 1, fk);
			//判断是否是障碍物/已计算过的方块
			if(!BasePanel.zhangaiList.contains(tmpFk) 
					&& !BasePanel.closedList.contains(tmpFk)){
				list.add(tmpFk);
				top = true;//上方方块符合条件
			}
		}
		
		//判断下面的方块是否符合条件
		if(fk.getY() + 1 < BasePanel.heightLength){
			FangKuaiPosition tmpFk = new FangKuaiPosition(fk.getX(), fk.getY() + 1, fk);
			if(!BasePanel.zhangaiList.contains(tmpFk) 
					&& !BasePanel.closedList.contains(tmpFk)){
				list.add(tmpFk);
				down = true;//下方方块符合条件
			}
		}
		
		//判断左面的方块是否符合条件
		if(fk.getX() - 1 >= 0){
			FangKuaiPosition tmpFk = new FangKuaiPosition(fk.getX() - 1, fk.getY(), fk);
			if(!BasePanel.zhangaiList.contains(tmpFk) 
					&& !BasePanel.closedList.contains(tmpFk)){
				list.add(tmpFk);
				left = true;//左方方块符合条件
			}
		}
		//判断右面的方块是否符合条件
		if(fk.getX() + 1 < BasePanel.widthLength){
			FangKuaiPosition tmpFk = new FangKuaiPosition(fk.getX() + 1, fk.getY(), fk);
			if(!BasePanel.zhangaiList.contains(tmpFk) 
					&& !BasePanel.closedList.contains(tmpFk)){
				list.add(tmpFk);
				right = true;//右方方块符合条件
			}
		}
		
		//左上方方块校验(左移一格不超过边界&&上移一格不超过边界&&左边方块符合条件&&上边方块符合条件,下面的类似原理)
		if(fk.getX() - 1 >= 0 && fk.getY() - 1 >= 0 && left && top){
			FangKuaiPosition tmpFk = new FangKuaiPosition(fk.getX() - 1, fk.getY() - 1, fk);
			//判断是否是障碍物/已计算过的方块
			if(!BasePanel.zhangaiList.contains(tmpFk) 
					&& !BasePanel.closedList.contains(tmpFk)){
				list.add(tmpFk);
			}
		}
		
		//右上方方块校验
		if(fk.getX() + 1 < BasePanel.widthLength && fk.getY() - 1 >= 0 && right && top){
			FangKuaiPosition tmpFk = new FangKuaiPosition(fk.getX() + 1, fk.getY() - 1, fk);
			//判断是否是障碍物/已计算过的方块
			if(!BasePanel.zhangaiList.contains(tmpFk) 
					&& !BasePanel.closedList.contains(tmpFk)){
				list.add(tmpFk);
			}
		}
		
		//右下方方块校验
		if(fk.getX() + 1 < BasePanel.widthLength && fk.getY() + 1 < BasePanel.heightLength && right && down){
			FangKuaiPosition tmpFk = new FangKuaiPosition(fk.getX() + 1, fk.getY() + 1, fk);
			//判断是否是障碍物/已计算过的方块
			if(!BasePanel.zhangaiList.contains(tmpFk) 
					&& !BasePanel.closedList.contains(tmpFk)){
				list.add(tmpFk);
			}
		}
		
		//左下方方块校验
		if(fk.getX() - 1 >= 0 && fk.getY() + 1 < BasePanel.heightLength && left && down){
			FangKuaiPosition tmpFk = new FangKuaiPosition(fk.getX() + 1, fk.getY() + 1, fk);
			//判断是否是障碍物/已计算过的方块
			if(!BasePanel.zhangaiList.contains(tmpFk) 
					&& !BasePanel.closedList.contains(tmpFk)){
				list.add(tmpFk);
			}
		}
		//将中心方块添加到已处理过的集合中
		BasePanel.closedList.add(fk);
		getFGH(list,fk);
		return list;
	}

二、移动

在basepanel.java中的movePanel方法里面,四方向的版本只做了上下左右四个方向的移动判断,所以这里需要将左上、右上、右下、左下的移动判断添加进来。同样,也是替换掉四方向版本中的这个movePanel方法就可以了。


/**
	 * 方块移动
	 * @param wayList	移动路线
	 * @throws InterruptedException
	 */
	public void movePanel(List<FangKuaiPosition> wayList) throws InterruptedException{
		
		if(wayList == null || wayList.size() == 0){
			System.out.println("无法 到达终点 !");
			return;
		}
		
		for(int i = wayList.size() - 2; i >= 0; i--){
			FangKuaiPosition fk = wayList.get(i);
			
			//向左上移动
			while(cat.getY() > fk.getY() * MyPanel.size && cat.getX() > fk.getX() * MyPanel.size){
				cat.setBounds(cat.getX() - 2, cat.getY() - 2, MyPanel.size, MyPanel.size);
				Thread.sleep(sleepTime);
			}
			
			//向右上移动
			while(cat.getY() > fk.getY() * MyPanel.size && cat.getX() < fk.getX() * MyPanel.size){
				cat.setBounds(cat.getX() + 2, cat.getY() - 2, MyPanel.size, MyPanel.size);
				Thread.sleep(sleepTime);
			}
			
			//向右下移动
			while(cat.getY() < fk.getY() * MyPanel.size && cat.getX() < fk.getX() * MyPanel.size){
				cat.setBounds(cat.getX() + 2, cat.getY() + 2, MyPanel.size, MyPanel.size);
				Thread.sleep(sleepTime);
			}
			
			//向左下移动
			while(cat.getY() < fk.getY() * MyPanel.size && cat.getX() > fk.getX() * MyPanel.size){
				cat.setBounds(cat.getX() - 2, cat.getY() + 2, MyPanel.size, MyPanel.size);
				Thread.sleep(sleepTime);
			}
			
			//向上
			while(cat.getY() > fk.getY() * MyPanel.size && cat.getX() == fk.getX() * MyPanel.size){
				cat.setBounds(cat.getX(), cat.getY() - 2, MyPanel.size, MyPanel.size);
				Thread.sleep(sleepTime);
			}
			
			//向下
			while(cat.getY() < fk.getY() * MyPanel.size && cat.getX() == fk.getX() * MyPanel.size){
				cat.setBounds(cat.getX(), cat.getY() + 2, MyPanel.size, MyPanel.size);
				Thread.sleep(sleepTime);
			}
			
			//向左
			while(cat.getX() > fk.getX() * MyPanel.size && cat.getY() == fk.getY() * MyPanel.size){
				cat.setBounds(cat.getX() - 2, cat.getY(), MyPanel.size, MyPanel.size);
				Thread.sleep(sleepTime);
			}
			
			//向右
			while(cat.getX() < fk.getX() * MyPanel.size && cat.getY() == fk.getY() * MyPanel.size){
				cat.setBounds(cat.getX() + 2, cat.getY(), MyPanel.size, MyPanel.size);
				Thread.sleep(sleepTime);
			}
			
		}
		System.out.println("寻路结束!");
	}


好了,给大家展示一下结果:


  • 0
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值