【Android】A星算法演示代码(自定义view方便查看效果)
来源:互联网 发布:nginx error log 关闭 编辑:程序博客网 时间:2024/06/11 01:53
本博客所有文章皆为原创,欢迎转载,转载请注明出处,谢谢合作!
http://blog.csdn.net/shinnwxwx/article/details/50833150
以下代码需要理解A星算法,如果您还不了解什么是A星算法,可以前往此链接学习一下。
http://blog.csdn.net/shinnwxwx/article/details/50835517
介绍:本代码是A星算法的演示代码,使用自定义view实现效果,直接在android layout里引用即可查看效果,无需新建工程,一个类搞定a星。
你可以根据代码注释,灵活修改参数进行预览,【起】点和【终】点可以通过点击屏幕中的方块随意修改。
效果图:
不废话,直接上能用的源码,拉进工程里就能用啦!
public class ViewForCircle extends View { int rect[][] = new int[20][40];// 地图矩阵 x , y int nowx = 2;// 起点x int nowy = 2;// 起点y int endx = rect.length - 3;// 终点x int endy = rect[0].length - 3;// 终点y List<Point> list_open = new ArrayList<Point>();// 保存开放列表 List<Point> list_close = new ArrayList<Point>();// 保存关闭列表 List<Point> list_result = new ArrayList<Point>();// 保存最终路径列表 float paddingframe;// 与屏幕边缘的距离 float view_width;// 显示的宽度 float view_height;// 显示的高度 float every_width;// 每个方块的宽度 float every_height;// 每个方块的高度 Paint p; int press_flag = 0; FontMetrics fm; Context context; boolean isLoading = false; boolean isPlaying = false; int animNum = 0;// 动画步数 int speed = 100;// 动画速度 public class Point { public int x;// x坐标 public int y;// y坐标 public int g;// 移动权重 public int h;// 目标权重 public int f;// 总权重 public Point fatherpoint;// 父节点 public Point(int x, int y, int g, int h, int f, Point fatherPoint) { this.x = x; this.y = y; this.g = g; this.h = h; this.f = f; this.fatherpoint = fatherPoint; } } public ViewForCircle(Context context) { super(context); this.context = context; } public ViewForCircle(Context context, AttributeSet attrs) { super(context, attrs); this.context = context; } public ViewForCircle(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); this.context = context; } protected void onSizeChanged(int w, int h, int oldw, int oldh) { init(); } public boolean onTouchEvent(MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_UP) { if (event.getX() - paddingframe < 0 || event.getY() - paddingframe < 0 || event.getX() - (paddingframe + view_width) > 0 || event.getY() - (paddingframe + view_height) > 0 || isPlaying || isLoading) return true; int x = (int) ((event.getX() - paddingframe) / view_width * rect.length); int y = (int) ((event.getY() - paddingframe) / view_height * rect[0].length); if (isCanMove(x, y) == false) return true; press_flag++; if (press_flag % 2 == 1) { nowx = x; nowy = y; } else if (press_flag % 2 == 0) { endx = x; endy = y; } updateRun(); } return true; } public void init() { // 初始化属性 p = new Paint(); p.setTextAlign(Paint.Align.CENTER); p.setTextSize(40); p.setStyle(Paint.Style.FILL); p.setAntiAlias(true); fm = p.getFontMetrics(); paddingframe = 50; view_width = getWidth() - paddingframe * 2; every_width = view_width / rect.length; view_height = getHeight() - paddingframe * 2; every_height = view_height / rect[0].length; // 创建障碍 updateObject(rect[0].length * rect.length / 4); // 寻路 updateRun(); } public void updateObject(int randomnum) { Random rd = new Random(); List<Integer> list_object = new ArrayList<Integer>(); for (int i = 0; i < rect.length * rect[0].length; i++) { if (i == nowy * rect.length + nowx) continue; else if (i == endy * rect.length + endx) continue; list_object.add(i); } for (int i = 0; i < randomnum; i++) { int index = (rd.nextInt() >>> 1) % list_object.size(); int result = list_object.get(index); rect[result % rect.length][result / rect.length] = 1; list_object.remove(index); } } public void updateRun() { new Thread() { public void run() { handler.sendEmptyMessage(0); list_result.clear(); list_open.clear(); list_close.clear(); // 将起点加入到关闭列表中 list_close.add(new Point(nowx, nowy, 0, Math.abs(nowx - endx) + Math.abs(nowy - endy), Math.abs(nowx - endx) + Math.abs(nowy - endy), null)); boolean isLooper = true; while (isinEnd() == false && isLooper) { // 将符合条件的节点加入开放列表 for (int i = 0; i < list_close.size(); i++) { addPoint(list_close.get(i)); } // 更新关闭列表和开放列表中的节点 if (updatePoint() == false) { list_result.clear(); list_open.clear(); list_close.clear(); isLooper = false; } } // 将最终结果筛选,并保存到最终路径列表中 refreshPoint(); handler.sendEmptyMessage(1); } }.start(); } Handler handler = new Handler() { public void handleMessage(Message msg) { if (msg.what == 0) { // 显示loading isLoading = true; } else if (msg.what == 1) { // 隐藏loading isLoading = false; } else if (msg.what == 2) { // 刷新步数 if (animNum == list_result.size()) { isPlaying = false; } else { animNum++; } } invalidate(); } }; public boolean updatePoint() { Point minPoint = null; for (int i = 0; i < list_open.size(); i++) { if (minPoint == null) minPoint = list_open.get(i); else { if (minPoint.f >= list_open.get(i).f) minPoint = list_open.get(i); } } if (minPoint != null) { list_close.add(new Point(minPoint.x, minPoint.y, minPoint.g, minPoint.h, minPoint.f, minPoint.fatherpoint)); list_open.remove(minPoint); return true; } else { return false; } } public void refreshPoint() { // 获得最终路径列表 if (list_close.size() != 0) { Point endPoint = list_close.get(list_close.size() - 1); while (endPoint != null) { list_result.add(0, endPoint); endPoint = endPoint.fatherpoint; } animNum = 0; isPlaying = true; } } // 检查当前节点周围节点 public void addPoint(Point p) { int arrow_up = 0; int arrow_down = 0; int arrow_left = 0; int arrow_right = 0; // 判断是否越界 if (isOut(p.x, p.y - 1) || isCanMove(p.x, p.y - 1) == false) arrow_up = 1; if (isOut(p.x, p.y + 1) || isCanMove(p.x, p.y + 1) == false) arrow_down = 1; if (isOut(p.x - 1, p.y) || isCanMove(p.x - 1, p.y) == false) arrow_left = 1; if (isOut(p.x + 1, p.y) || isCanMove(p.x + 1, p.y) == false) arrow_right = 1; // 如果arrow方向所对应的值仍然为0,那么判断节点是否在关闭列表中 for (int i = 0; i < list_close.size(); i++) { int tempx = list_close.get(i).x; int tempy = list_close.get(i).y; if (arrow_up == 0 && tempx == p.x && tempy == p.y - 1) { arrow_up = 1; } else if (arrow_down == 0 && tempx == p.x && tempy == p.y + 1) { arrow_down = 1; } else if (arrow_left == 0 && tempx == p.x - 1 && tempy == p.y) { arrow_left = 1; } else if (arrow_right == 0 && tempx == p.x + 1 && tempy == p.y) { arrow_right = 1; } } // 如果arrow方向所对应的值仍然为0,那么判断节点是否在开放列表中 for (int i = 0; i < list_open.size(); i++) { int tempx = list_open.get(i).x; int tempy = list_open.get(i).y; if (arrow_up == 0 && tempx == p.x && tempy == p.y - 1) { arrow_up = 1; } else if (arrow_down == 0 && tempx == p.x && tempy == p.y + 1) { arrow_down = 1; } else if (arrow_left == 0 && tempx == p.x - 1 && tempy == p.y) { arrow_left = 1; } else if (arrow_right == 0 && tempx == p.x + 1 && tempy == p.y) { arrow_right = 1; } } // 将符合条件的节点加入开放列表中 if (arrow_up == 0) { list_open.add(new Point(p.x, p.y - 1, p.g + 1, Math.abs(p.x - endx) + Math.abs(p.y - 1 - endy), p.g + 1 + Math.abs(p.x - endx) + Math.abs(p.y - 1 - endy), p)); } if (arrow_down == 0) { list_open.add(new Point(p.x, p.y + 1, p.g + 1, Math.abs(p.x - endx) + Math.abs(p.y + 1 - endy), p.g + 1 + Math.abs(p.x - endx) + Math.abs(p.y + 1 - endy), p)); } if (arrow_left == 0) { list_open.add(new Point(p.x - 1, p.y, p.g + 1, Math.abs(p.x - 1 - endx) + Math.abs(p.y - endy), p.g + 1 + Math.abs(p.x - 1 - endx) + Math.abs(p.y - endy), p)); } if (arrow_right == 0) { list_open.add(new Point(p.x + 1, p.y, p.g + 1, Math.abs(p.x + 1 - endx) + Math.abs(p.y - endy), p.g + 1 + Math.abs(p.x + 1 - endx) + Math.abs(p.y - endy), p)); } } // x,y是否可以移动 private boolean isCanMove(int x, int y) { if (rect[x][y] == 1) return false; return true; } // x,y是否出界 private boolean isOut(int x, int y) { if (x < 0 || x >= rect.length || y < 0 || y >= rect[0].length) return true; else return false; } // 终点x,y是否在关闭列表中 public boolean isinEnd() { for (int i = 0; i < list_close.size(); i++) { int tempx = list_close.get(i).x; int tempy = list_close.get(i).y; if (tempx == endx && tempy == endy) { return true; } } return false; } protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.drawRGB(255, 255, 255); // 显示障碍 p.setColor(Color.parseColor("#cccccc")); for (int i = 0; i < rect.length; i++) { for (int j = 0; j < rect[i].length; j++) { if (rect[i][j] == 1) canvas.drawRect(paddingframe + every_width * i, paddingframe + every_height * j, paddingframe + every_width * (i + 1), paddingframe + every_height * (j + 1), p); } } // 显示路径 p.setColor(Color.parseColor("#ff9912")); for (int i = 0; i < list_result.size(); i++) { if (i <= animNum) { canvas.drawRect(paddingframe + (every_width * list_result.get(i).x), paddingframe + (every_height * list_result.get(i).y), paddingframe + (every_width * (list_result.get(i).x + 1)), paddingframe + (every_height * (list_result.get(i).y + 1)), p); } } if (animNum == list_result.size()) { isPlaying = false; } else { new Thread() { public void run() { try { Thread.sleep(speed); handler.sendEmptyMessage(2); } catch (InterruptedException e) { e.printStackTrace(); } } }.start(); } // 显示地图表格 p.setColor(Color.parseColor("#666666")); for (int i = 0; i < rect[0].length + 1; i++) { canvas.drawLine(paddingframe, paddingframe + every_height * i, paddingframe + view_width, paddingframe + every_height * i, p); } for (int i = 0; i < rect.length + 1; i++) { canvas.drawLine(paddingframe + every_width * i, paddingframe, paddingframe + every_width * i, paddingframe + view_height, p); } // 显示起点,终点 canvas.drawText("起", paddingframe + every_width * nowx + every_width / 2, paddingframe + every_height * nowy + every_height / 2 + (fm.descent - fm.ascent) / 2 - fm.descent, p); canvas.drawText("终", paddingframe + every_width * endx + every_width / 2, paddingframe + every_height * endy + every_height / 2 + (fm.descent - fm.ascent) / 2 - fm.descent, p); if (isLoading) { p.setColor(Color.parseColor("#ff0000")); canvas.drawText("寻路中...请稍后...", getWidth() / 2, getHeight() / 2 + (fm.descent - fm.ascent) / 2 - fm.descent, p); } }}
具体功能性函数已经写好注释,大家可以直接在自己的layout里引用这个自定义的View设置好宽高位置即可,附上例子layout代码
<这里写上你的包名.ViewForCircle android:id="@+id/circleview" android:layout_width="fill_parent" android:layout_height="fill_parent" />
只要这些步骤,你就可以在自己的项目里预览A星算法的全部过程,代码已经经过优化修改,注释写的比较完整,如果你还有什么问题,可以再此留言,我们一起交流与学习!
0 0
- 【Android】A星算法演示代码(自定义view方便查看效果)
- Android 自定义View 时钟效果
- Android自定义View时钟效果
- android自定义view锯齿状效果
- Android自定义View-刮刮卡效果
- 心电图效果View Android自定义View
- Android自定义view代码步骤
- Android开发-自定义View-AndroidStudio(二十一)onDraw的演示
- android自定义view实现progressbar的效果
- Android 自定义view实现水波纹效果
- android:模拟水波效果的自定义View
- Android 自定义View 实现刮刮卡效果
- Android:自定义View实现水波进度效果
- android 自定义view实现水波纹效果
- Android 自定义view实现水波纹效果
- android正在加载效果(自定义view)
- android自定义view实现5.0 Ripple效果
- Android 自定义view实现水波纹效果
- Android Studio简单设置
- 如何删除注册表Key值的Value
- store.js - 轻松实现本地存储(LocalStorage)
- 一篇文章读懂开源web引擎Crosswalk
- HashMap实现原理分析
- 【Android】A星算法演示代码(自定义view方便查看效果)
- 中科院计算所培训中心二季度公开课安排
- __FILE__和$_SERVER["PHP_SELF"]的区别
- iOS开发有关二维码的介绍
- [Android]Activity的创建
- 让「快速添加」更快、更简单
- Android Xutils 框架
- oracle 的安装和完全卸载
- 干货:结合Scikit-learn介绍几种常用的特征选择方法