爱心算法学习笔记



package com.laotou99.astar;

import java.awt.Color;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Panel;
import java.awt.Point;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import java.awt.image.ImageObserver;
import java.awt.image.ImageProducer;
import java.io.Serializable;
import java.util.List;


//Java的A*寻径实现
public class Main extends Panel implements Serializable
{
 
	private static final long serialVersionUID = 1L;
	
	final static private int WIDTH = 480;
	final static private int HEIGHT = 480;
	final static private int CS = 32;
	
	private TestMap map;
	private PathFinder astar;
	// 起始坐标1,1
	private static Point START_POS = new Point(1,1);
	// 目的坐标10,13
	private static Point OBJECT_POS = new Point(7,7);
	
	private BufferedImage screen;
	private Graphics graphics;
	
	private List path;
	
	public Main(){
		setSize(WIDTH,HEIGHT);
		setFocusable(true);
		screen = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_ARGB);
		graphics = screen.getGraphics();
		
		map = new TestMap();
		 // 注入地图描述及障碍物描述
		astar = new PathFinder(TestMap.MAP, TestMap.HIT);
		// searchPath将获得两点间移动路径坐标的List集合
        // 在实际应用中,利用Thread分步处理List中坐标即可实现自动行走
		path = astar.searchPath(START_POS, OBJECT_POS);
	}

	@Override
	public void update(Graphics g) {
		paint(g);
	}
	
	@Override
	public void paint(Graphics g) {
		 // 绘制地图
		map.draw(graphics);
		graphics.setColor(Color.RED);
		graphics.fillRect(START_POS.x*CS, START_POS.y*CS, CS, CS);
		
		graphics.setColor(Color.BLUE);
		graphics.fillRect(OBJECT_POS.x*CS, OBJECT_POS.y*CS, CS, CS);
		// 绘制路径
		if(path!=null){
			graphics.setColor(Color.YELLOW);
			//遍历坐标,并一一描绘
			for(int i=0;i<path.size();i++){
				Node node = (Node)path.get(i);
				Point pos = node._pos;
				 // 描绘边框
				graphics.fillRect(pos.x*CS+7, pos.y*CS+7, CS-14,CS-14);
			}
		}
		
		g.drawImage(screen, 0, 0, this);
	}



	public static void main(String[] args) {
		Frame frame = new Frame();
		
		frame.setTitle("Java的爱心 寻径实现");
		frame.setSize(WIDTH, HEIGHT);
		frame.setResizable(false);
		frame.setLocationRelativeTo(null);
		frame.add(new Main());
		frame.setVisible(true);
		
		frame.addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent e){
				System.exit(0);
			}
		});

	}

}

package com.laotou99.astar;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;

//一个简单的地图实现
public class TestMap {

	final static private int CS = 32;
	
	// 地图描述
    final static public int[][] MAP = {
            { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
            { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
            { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
            { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
            { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
            { 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1 },
            { 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1 },
            { 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1 },
            { 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1 },
            { 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1 },
            { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
            { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
            { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
            { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
            { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } };
    // 无法移动区域
    final static public int[] HIT={1};
    // 设定背景方格默认行数
    final static private int ROW = 15;
    // 设定背景方格默认列数
    final static private int COL = 15;
    
    
    public TestMap(){ }
    
	public void draw(Graphics g){
		
		for(int i=0;i<ROW;i++){
			for(int j=0;j<COL;j++){
				switch(MAP[i][j]){
				case 0:
					g.setColor(Color.WHITE);
					g.fillRect(j*CS, i*CS, CS, CS);
					break;
				case 1:
					g.setColor(Color.BLACK);
					g.fillRect(j*CS, i*CS, CS, CS);
					break;
				}
			}
		}
	}
}



package com.laotou99.astar;

import java.awt.Point;
import java.io.Serializable;
import java.util.LinkedList;
import java.util.List;


//A*寻径处理用类(此类为演示用,并不意味着算法是最佳实现)
public class PathFinder {
	// 路径优先等级list(此示例中为内部方法)
	private LevelList _leveList;
	// 已完成路径的list
	private LinkedList _closedList;
	// 地图描述
	private int[][] _map;
	// 行走区域限制
	private int[] _limit;
	
	// 以注入地图的2维数组及限制点描述初始化此类
	public PathFinder(int[][] map, int[] limit) {
		_map = map;
		_limit = limit;
		_leveList = new LevelList();
		_closedList = new LinkedList();
	}

	// A*方式寻径,注入开始坐标及目标坐标后运算,返回可行路径的List
	public List searchPath(Point startPos,Point objectPos){
		// 初始化起始节点与目标节点
		Node startNode = new Node(startPos);
		Node objectNode = new Node(objectPos);
		// 设定起始节点参数
		startNode._costFromStart = 0;
		startNode._costToObject=startNode.getCost(objectNode);
		startNode._parentNode=null;
		// 加入运算等级序列
		_leveList.add(startNode);
		// 当运算等级序列中存在数据时,循环处理寻径,直到levelList为空
		while(!_leveList.isEmpty()){
			// 取出并删除最初的元素
			Node firstNode = (Node)_leveList.removeFirst();
			// 判定是否和目标node坐标相等
			if(firstNode.equals(objectNode)){
				 // 是的话即可构建出整个行走路线图,运算完毕
				return makePath(firstNode);
			}
			else
			{ 
                // 否则  加入已验证List
				_closedList.add(firstNode);
				 // 获得firstNode的移动区域
				LinkedList _limit = firstNode.getLimit();
				 // 遍历
				for(int i=0;i<_limit.size();i++){
					  //获得相邻节点
					Node neighborNode = (Node)_limit.get(i);
					//获得是否满足等级条件
					boolean isOpen = _leveList.contains(neighborNode);
					 //获得是否已行走
					boolean isClosed = _closedList.contains(neighborNode);
					 //判断是否无法通行
					boolean isHit = isHit(neighborNode._pos.x,neighborNode._pos.y);
					 //当三则判定皆非时
					if(!isOpen && !isClosed && !isHit){
						 //设定costFromStart
						neighborNode._costFromStart = firstNode._costFromStart+1;
						 //设定costToObject  
						neighborNode._costToObject = neighborNode.getCost(objectNode);
						 //改变neighborNode父节点
						neighborNode._parentNode=firstNode;
						//加入level 
						_leveList.add(neighborNode);
					}
				}		
			}
		}
		 //清空数据
		_leveList.clear();
		_closedList.clear();
		 //当while无法运行时,将返回null
		return null;
	}

	//* 判定是否为可通行区域  *
	private boolean isHit(int x,int y){
		
		for(int i=0;i<_limit.length;i++){
			if(_map[y][x]==_limit[i]){
				return true;
			}
		}
		
		return false;
	}
	
	//通过Node制造行走路径
	private LinkedList makePath(Node node){
		LinkedList path = new LinkedList();
		// 当上级节点存在时
		while(node._parentNode!=null){
			// 在第一个元素处添加
			path.addFirst(node);
			 // 将node赋值为parent node
			node = node._parentNode;
		}
		// 在第一个元素处添加
		path.addFirst(node);
		return path;
	}

	private class LevelList extends LinkedList implements Serializable{

		private static final long serialVersionUID = 1L;
		//增加一个node
		public void add(Node node){
			for(int i=0;i<size();i++){
				if(node.compareTo(get(i))<=0){
					add(i,node);
					return;
				}
			}
			addLast(node);
		}
		
	}

}


package com.laotou99.astar;

import java.awt.Point;
import java.util.LinkedList;

//描述路径节点用类

public class Node implements Comparable {

	public Point _pos;			  // 坐标
	
	public int _costFromStart;	  // 开始地点数值
	
	public int _costToObject;	  // 目标地点数值
	
	public Node _parentNode;	  // 父节点
	
	private Node() {	}
	// 以注入坐标点方式初始化Node
	public Node(Point _pos){
		this._pos=_pos;
	}
	
	// 返回路径成本
	public int getCost(Node node){
		 // 获得坐标点间差值 公式:(x1, y1)-(x2, y2)
		int m = node._pos.x - _pos.x;
		int n = node._pos.y - _pos.y;
		 // 取两节点间欧几理德距离(直线距离)做为估价值,用以获得成本
		return (int)Math.sqrt(m*m+n*n);
	}
	//检查node对象是否和验证对象一致
	@Override
	public boolean equals(Object node) {
		
		if(_pos.x==((Node)node)._pos.x &&
			_pos.y==((Node)node)._pos.y)
		{
			return true;
		}		
		return false;
	}
	
	//--比较两点以获得最小成本对象
	@Override
	public int compareTo(Object node) {
		int a1 = _costFromStart + _costToObject;
		int a2 = ((Node)node)._costFromStart+((Node)node)._costToObject;
		if(a1<a2)
		{
			return -1;
		}
		else if(a1==a2)
		{
			return 0;
		}
		else
		{
			return 1;
		}
	}

	//--获得上下左右各点间移动限制区域
	public LinkedList getLimit(){
		
		LinkedList limit = new LinkedList<>();
		int x = _pos.x;
		int y = _pos.y;
		//上下左右各点间移动区域(对于斜视地图,可以开启注释的偏移部分,此时将评估8个方位)
		
		//上
		limit.add(new Node(new Point(x,y-1)));
		
		//右上
		//limit.add(new Node(new Point(x+1,y-1)));
		
		//右
		limit.add(new Node(new Point(x+1,y)));
		
		//右下
		//limit.add(new Node(new Point(x+1,y+1)));
		
		//下
		limit.add(new Node(new Point(x, y+1)));
		
		//左下
		//limit.add(new Node(new Point(x-1,y+1)));
		
		//左
		limit.add(new Node(new Point(x-1,y)));
		
		//左上
		//limit.add(new Node(new Point(x-1, y-1)));
		
		return limit;
	}
}







  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值