"A man needs books as a sword needs a whetstone, if it is to keep its edge." --TYRION LANNISTER《Game of Thrones》
迷宫算法
迷宫算法,也就是在给定的起点和终点以及地图(数组)上,计算出起点到达终点的路径。也就是在迷宫中寻找出口的计算机算法。以下展示了基于java平台的队列迷宫算法和栈迷宫算法。其实还有一种算法叫做A*寻路算法,可以产生起点到终点的最优解,有时间,我会写一个java的类。 迷宫算法的作用,在游戏中运用的还是比较多的,大家可以想象。游戏中的人工智能也往往把这个当做基础函数来用,可以说这是游戏人工智能的基础。
基于队列的寻路算法(也称综合布线算法)##
核心代码如下: ** QueuePath.java **
package findway;
import java.util.LinkedList;
class Position { // Class Position
public int row;
public int col;
Position(int row, int col) {
this.row = row;
this.col = col;
}
public Position() {
this.row = 0;
this.col = 0;
}
public boolean IsEqual(Position x) {
if ((this.row == x.row) && (this.col == x.col))
return true;
else
return false;
}
public void add(Position x) {
this.row += x.row;
this.col += x.col;
}
}
class ERROR_STRING // Error string
{
protected final static String StartEqualFinish = "start point equal to the finish point.";
protected final static String StartOrFinishCantgo = "start point or finish point cant not go.";
}
public class QueuePath extends FindPath {
private final Position offset[] = new Position[ 4];
public QueuePath(int[][] x, int height, int width) {
super(x, height, width);
// Initialize the matrix of offset
offset[ 0] = new Position( 0, 1); // right
offset[ 1] = new Position( 1, 0); // down
offset[ 2] = new Position( 0, - 1); // left
offset[ 3] = new Position(- 1, 0); // up
}
@Override
public boolean findway(Position start_point, Position finish_point) {
// Initialize the start and end
this.start = new Position(start_point.row + 1, start_point.col + 1);
this.finish = new Position(finish_point.row + 1, finish_point.col + 1);
if ((start.row == finish.row) && (start.col == finish.col)) {
error.add(ERROR_STRING.StartEqualFinish);
return false;
}
if ((map[start.row][start.col] == Notgo)
|| (map[finish.row][finish.col] == Notgo)) {
error.add(ERROR_STRING.StartOrFinishCantgo);
return false;
}
// Reset map and value
for (int i = 1; i < m - 1; i++)
for (int j = 1; j < n - 1; j++)
if (map[i][j] != Notgo)
map[i][j] = 0;
PathLen = 0;
// End set
// Begin find path
LinkedList<Position> Q = new LinkedList<Position>();
map[start.row][start.col] = Notgo + 1; // locked
Position here = new Position(), nbr = new Position();
here.row = start.row;
here.col = start.col;
try {
do {
for (int i = 0; i < offset.length; i++) {
nbr.row = here.row + offset[i].row;
nbr.col = here.col + offset[i].col;
if (map[nbr.row][nbr.col] == Cango) {
map[nbr.row][nbr.col] = map[here.row][here.col] + 1;
if ((nbr.row == finish.row) && (nbr.col == finish.col))
break;
Q.addLast(new Position(nbr.row, nbr.col));
}
}
if ((nbr.row == finish.row) && (nbr.col == finish.col))
break;
if (Q.isEmpty())
return false;
here = Q.removeFirst();
} while (true);
} catch (Exception e) {
e.printStackTrace();
}
// End find
// Build the path of map
here = new Position(finish.row, finish.col);
PathLen = map[finish.row][finish.col] - 2;
for (int j = PathLen - 1; j >= 0; j--) {
path.add( 0, new Position(here.row, here.col));
for (int i = 0; i < offset.length; i++) {
nbr.row = here.row + offset[i].row;
nbr.col = here.col + offset[i].col;
if (map[nbr.row][nbr.col] == j + 2)
break;
}
here = new Position(nbr.row, nbr.col);
}
// End build
return true;
}
}
程序运行的结果如下:
The path results is:
(2,1) (3,1) (4,1) (5,1) (6,1) (6,2) (6,3) (7,3) (7,4) (8,4) (8,5) (8,6) (9,6) (10,6) (10,5) (10,4) (10,3) (9,3) (9,2) (9,1)
0 . 0 . . . .
. A 0 . 0 0 0
. * . . . . .
. * 0 . 0 0 .
. * . 0 . . .
. * . 0 . 0 .
0 * * * . . 0
0 . 0 * * 0 .
0 0 0 0 * * *
0 B * * 0 0 *
0 0 0 * * * *
PathLen:20
.:It can go
0:barrier
A:start point
B:finish point
*:It is the path
基于栈的普通寻路算法
核心代码如下: ** StackPath.java **
package findway;
import java.util.Stack;
class Direction {
protected int row, col;
protected String dir;
Direction(int row, int col, String dir) {
this.row = row;
this.col = col;
this.dir = dir;
}
}
class item {
int x, y, dir;
public item(int i, int j, int k) {
x = i;
y = j;
dir = k;
}
}
public class StackPath extends FindPath {
private final int SIZE = 8;
private final Direction offset[] = new Direction[SIZE];
Stack<item> S;
item originD;
int DIR_O = 0;
StackPath(int[][] x, int height, int width) {
super(x, height, width);
// Initialize the matrix of offset
offset[ 0] = new Direction(- 1, 0, "N"); // N
offset[ 4] = new Direction( 1, 0, "S"); // S
offset[ 6] = new Direction( 0, - 1, "W"); // W
offset[ 2] = new Direction( 0, 1, "E"); // E
offset[ 1] = new Direction(- 1, 1, "NE"); // NE
offset[ 5] = new Direction( 1, - 1, "SW"); // SW
offset[ 7] = new Direction(- 1, - 1, "NW"); // NW
offset[ 3] = new Direction( 1, 1, "SE"); // SE
}
public void setDir(String Dir) {
for (int i = 0; i < offset.length; i++) {
if (offset[i].dir == Dir)
DIR_O = i;
}
}
@Override
public boolean findway(Position start_point, Position finish_point) {
// Initialize the start and end
start = new Position(start_point.row + 1, start_point.col + 1);
finish = new Position(finish_point.row + 1, finish_point.col + 1);
originD = new item(start.row, start.col, DIR_O);
if ((start.row == finish.row) && (start.col == finish.col)) {
error.add(ERROR_STRING.StartEqualFinish);
return false;
}
if ((map[start.row][start.col] == Notgo)
|| (map[finish.row][finish.col] == Notgo)) {
error.add(ERROR_STRING.StartOrFinishCantgo);
return false;
}
// Reset map and value
for (int i = 1; i < m - 1; i++)
for (int j = 1; j < n - 1; j++)
if (map[i][j] != Notgo)
map[i][j] = 0;
PathLen = 0;
// End set
// Begin find path
map[start.row][start.col] = Notgo + 1; // lock
S = new Stack<item>();
int i = 0, j = 0, d = 0, g = 0, h = 0;
item temp;
S.push(new item(originD.x, originD.y, originD.dir));
while (!S.isEmpty()) {
temp = S.pop();
i = temp.x;
j = temp.y;
d = temp.dir;
while (d < offset.length) {
g = i + offset[d].row;
h = j + offset[d].col;
if ((g == finish.row) && (h == finish.col)) {
S.push(new item(i, j, d));
S.push(new item(g, h, d));
break;
}
if (map[g][h] == 0) {
map[g][h] = Notgo + 1;
S.push(new item(i, j, d));
i = g;
j = h;
d = 0;
} else
d++;
}
if ((g == finish.row) && (h == finish.col))
break;
}
// End find
if (S.isEmpty())
return false;
// Build the path of map
PathLen = S.size() - 1;
while (!S.isEmpty()) {
item cache = S.pop();
path.add( 0, new Position(cache.x, cache.y));
}
path.remove( 0);
// End build
return true;
}
}
程序运行的结果如下:
The path results is:
(2,0) (1,0) (2,1) (2,2) (1,3) (2,4) (2,5) (2,6) (3,6) (4,6) (5,6) (6,5) (7,6) (8,6) (9,6) (10,6) (10,5) (10,4) (10,3) (9,3) (9,2) (9,1)
0 . 0 . . . .
* A 0 * 0 0 0
* * * . * * *
. . 0 . 0 0 *
. . . 0 . . *
. . . 0 . 0 *
0 . . . . * 0
0 . 0 . . 0 *
0 0 0 0 . . *
0 B * * 0 0 *
0 0 0 * * * *
PathLen:22
.:It can go
0:barrier
A:start point
B:finish point
*:It is the path
其他的代码
** FindPath.java **
package findway;
import java.util.ArrayList;
public abstract class FindPath {
protected int PathLen;
protected Position start, finish;
protected ArrayList<Position> path=new ArrayList<Position>();
protected ArrayList<String> error;
protected int m;
protected int n;
protected int height;
protected int width;
protected int map[][];
protected int Cango = 0; // The block is able to go
protected int Notgo = 1; // The block is unable to go
public FindPath(int[][] x, int height, int width) {
// Initialize the value
this.height = height;
this.width = width;
this.m = height + 2;
this.n = width + 2;
this.map = new int[m][n];
error = new ArrayList<String>();
// Initialize the map
for (int i = 1; i < m - 1; i++)
for (int j = 1; j < n - 1; j++)
this.map[i][j] = x[i - 1][j - 1];
for (int p = 0; p < n; p++)
this.map[ 0][p] = Notgo;
for (int k = 0; k < n; k++)
this.map[m - 1][k] = Notgo;
for (int j = 0; j < m; j++)
this.map[j][ 0] = Notgo;
for (int i = 0; i < m; i++)
this.map[i][n - 1] = Notgo;
}
public abstract boolean findway(Position start_point, Position finish_point);
public Position getSize() // Get Path Length
{
return new Position(height, width);
}
public void printPath() // Print Standard List of Path
{
System.out.println("The path results is:");
for (Position site : path)
System.out.print("(" + (site.row - 1) + "," + (site.col - 1) + ")"
+ " ");
System.out.println();
}
public void printmapValue() // print value of map
{
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++)
System.out.printf("%d\t", map[i][j]);
System.out.println();
}
System.out.println();
}
public void printErrorImformation() // Print error information
{
if (error.size() != 0)
for (String s : error)
System.out.println(s);
}
public void print() // Print matrix path
{
char copy[][] = new char[m][n];
for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++)
if (map[i][j] != Notgo)
copy[i][j] = '.';
else
copy[i][j] = '0';
for (Position site : path)
copy[site.row][site.col] = '*';
copy[start.row][start.col] = 'A';
copy[finish.row][finish.col] = 'B';
for (int i = 1; i < m - 1; i++) {
for (int j = 1; j < n - 1; j++)
System.out.print(copy[i][j] + " ");
System.out.println();
}
System.out.println("PathLen:" + PathLen);
System.out.println(".:It can go");
System.out.println("0:barrier");
System.out.println("A:start point");
System.out.println("B:finish point");
System.out.println("*:It is the path");
}
public ArrayList<Position> getPath() // Get ArrayList of path
{
ArrayList<Position> copy = new ArrayList<Position>();
for (Position site : path)
copy.add(new Position(site.row - 1, site.col - 1));
return copy;
}
}
调用运行
** MainActivity.java **
package findway;
public class MainActivity {
public static void main(String[] args)
{
int map[][]=new int[][]{{ 1, 0, 1, 0, 0, 0, 0},
{ 0, 0, 1, 0, 1, 1, 1},
{ 0, 0, 0, 0, 0, 0, 0},
{ 0, 0, 1, 0, 1, 1, 0},
{ 0, 0, 0, 1, 0, 0, 0},
{ 0, 0, 0, 1, 0, 1, 0},
{ 1, 0, 0, 0, 0, 0, 1},
{ 1, 0, 1, 0, 0, 1, 0},
{ 1, 1, 1, 1, 0, 0, 0},
{ 1, 0, 0, 0, 1, 1, 0},
{ 1, 1, 1, 0, 0, 0, 0}};
QueuePath way=new QueuePath(map,11, 7);
way.findway(new Position( 1, 1),new Position( 9, 1));
way.printPath();
way.print();
//StackPath way=new StackPath(map,11,7);
//way.setDir("SW");
//way.findway(new Position(1,1),new Position(9,1));
//way.printPath();
//way.print();
}
}