学自《ANDROID_2.0游戏开发实战宝典》
深度优先路径搜索
深度优先搜索DFS在搜索过程中不考虑各个边的开销,只考虑路径的选择。其思路是站在一个连通图的点上,然后尽可能沿着一条边深入,当遇到死胡同就进行回溯,然后继续搜索,直到找到目标为止。
直接上例子,例子中注释有详细说明:
MapList.java
package com.liangbinny.my;
public class MapList {
public static int[] source={1,1};//出发点
public static int[][] target={//目标点坐标数组
{5,4}
};
public static int[][] map = new int[][] //地图数组 , 1表示不可达区域
{
{1,1,1,1,1,1,1},
{1,0,0,0,0,0,1},
{1,1,0,1,1,0,1},
{1,1,0,0,1,0,1},
{1,1,1,1,0,0,1},
{1,1,1,1,0,1,1},
{1,1,1,1,1,1,1}
};
}
深搜例子DFS.java
package com.liangbinny.my;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Stack;
/**
* <p><b>
* 深度优先搜索算法 (depth first search)
* 算法原理是:从原点出发,尽可能沿着一条边深入,
* 当遇到叶子结点(顶结点)就进行回溯,然后继续搜索,直到找到目标为止
* 主要利用栈(Stack),利用栈的先进后出的原理,深度依次搜索,利用栈来存储待访问的边
* </b></p>
*/
public class DFS {
int[] source = MapList.source; //出发点
int[] target = MapList.target[0]; //目标点
Stack<int[][]> stack = new Stack<int[][]>(); //深度优先所用栈,栈里存放的是边,两相邻点作为一条边
int[][] visited = new int[MapList.map.length][MapList.map[0].length];
ArrayList<int[][]> searchProcess=new ArrayList<int[][]>();//搜索过程
HashMap<String,int[][]> hm=new HashMap<String,int[][]>();//结果路径记录
//这个就是记录一个点的8个方向的点
int[][] sequence={
{0,1},{0,-1},
{-1,0},{1,0},
{-1,1},{-1,-1},
{1,-1},{1,1}
};
int[][] map = MapList.map;
public void calcDFS(){ //深度优先算法
int[][] start = { //开始状态
{source[0],source[1]},
{source[0],source[1]}
};
stack.push(start);
while(true){
int[][] currentEdge = stack.pop(); //从栈顶取出边
int[] tempTarget = currentEdge[1]; //取该边的终点(起点在之前循环已经处理了,或者是原点,无须再处理)
//判断目的点是否去过,若去过则直接进入下次循环
if (visited[tempTarget[1]][tempTarget[0]]==1) { //(2,3)的点,3相当于数组的行,2相当于数组的列,行列要倒置来看,要小心
continue;
}
visited[tempTarget[1]][tempTarget[0]]=1;//标识目的点为访问过
//将临时目的点加入搜索过程中,表示曾经搜索过这个点,这条边
searchProcess.add(currentEdge);
//记录此临时目的点的父节点,存储这条边
//最终搜索到显示时,就是根据这个hashmap,从目标点出发,一直往回找寻经过的点
hm.put(tempTarget[0]+":"+tempTarget[1], new int[][]{currentEdge[1],currentEdge[0]});
//找到目标点
if (tempTarget[0]==target[0]&&tempTarget[1]==target[1]) {
break;
}
//将所有可能的边入栈.无非就是这个点的8个方向的点(sequence取),只要不是不可到达的区域(1),就都放入栈中
//对于一个坐标指向数组,比如(13,2),x坐标13是数组里的列,y坐标2是数组里的行
int currCol=tempTarget[0];
int currRow=tempTarget[1];
for(int[] rc:sequence){ //循环遍历它的8个点
int i = rc[1];
int j = rc[0];
if(i==0&&j==0){continue;} //表示无位移
if (currRow+i>=0&&currRow+i<map.length&&currCol+j>=0&&currCol+j<map[0].length&&map[currRow+i][currCol+j]!=1) {
int[][] tempEdge={
{tempTarget[0],tempTarget[1]},
{currCol+j,currRow+i}
};
//因为是栈,所以是后处理,所以8个方向的点的进栈顺序是{0,1},{0,-1}...{1,-1},{1,1}
//但处理顺序是后处理,所以处理顺序是{1,1},{1,-1}...{0,-1},{0,1}
stack.push(tempEdge);
}
}
}
}
public static void main(String[] args) {
DFS dfs = new DFS();
dfs.calcDFS(); //搜索
System.out.println("====================深度搜索过程=========================");
//打印搜索过程路径
ArrayList<int[][]> list = dfs.searchProcess;
for (int[][] is : list) {
System.out.println("start:"+is[0][0]+","+is[0][1]+";end:"+is[1][0]+","+is[1][1]);
}
System.out.println("====================最终路径=========================");
//打印最终的结果路径
//本质是根据搜索路径过程,原着目标点反序,只需要依次找父结点,最后得到的是原点即可
int[] temp=dfs.target;
while(true){
int[][] tempA=dfs.hm.get(temp[0]+":"+temp[1]);
System.out.println("start:"+tempA[0][0]+","+tempA[0][1]+";end:"+tempA[1][0]+","+tempA[1][1]);
if(tempA[1][0]==dfs.source[0]&&tempA[1][1]==dfs.source[1]){//判断有否到出发点
break;
}
temp=tempA[1];
}
}
}