# 六边形网格A*寻路算法,JAVA实现源码

package gpp.util;

import java.util.ArrayList;
import java.util.List;

import gpp.object.Coordinate;

public class APathfindingHex {
List<Coordinate> allC;

public List<Coordinate> openList;
public List<Coordinate> closeList;

List<Coordinate> pathC;

public APathfindingHex(List<Coordinate> allC){
this.allC=new ArrayList<>();
for (Coordinate oldC : allC) {
Coordinate newC=new Coordinate(oldC.x, oldC.y);
newC.isBlock=oldC.isBlock;
newC.speed=oldC.speed;
}
}

Coordinate findC(Coordinate inC,List<Coordinate> allC) {
for (Coordinate coordinate : allC) {
if (coordinate.equals(inC)) {
return coordinate;
}
}
return null;
}

public List<Coordinate> start(Coordinate oldStartC,Coordinate oldDesC) {

Coordinate startC=findC(oldStartC,allC);
Coordinate desC=findC(oldDesC,allC);
if (findC(startC,allC)==null||findC(desC,allC)==null) {
System.out.println("起点或者终点有误");
return null;
}
if (startC.isBlock||desC.isBlock) {
System.out.println("起点或者终点无法通过");
return null;
}
openList=new ArrayList<>();
closeList=new ArrayList<>();
pathC=new ArrayList<>();

boolean isFind=makeOne(startC,desC);
long count=0;
while (isFind==false&&openList.size()>0) {
count++;
//System.out.println("第"+count+"次计算:");
Coordinate minF=findMinFinOpen();
if (minF!=null) {
isFind=makeOne(minF,desC);
}
}
System.out.println("计算量:"+count);
return pathC;
}

boolean makeOne(Coordinate curC,Coordinate desC) {
openList.remove(curC);
List<Coordinate> nearListC=curC.findNear();
for (Coordinate coordinate : nearListC) {
Coordinate temp=findC(coordinate,allC);
if (temp!=null&&temp.isBlock==false&&!closeList.contains(temp)) {
int tempG=curC.G+temp.speed;
if (tempG<temp.G||temp.parent==null) {
temp.parent=curC;
temp.G=tempG;
temp.H=calcuH(temp,desC);
temp.F=temp.G+temp.H;
}
if (!openList.contains(temp)) {
}
if (temp.equals(desC)) {
//找到目的地
return true;
}
}
}
return false;
}

private Coordinate findMinFinOpen() {
//先找最小值
int minF=Integer.MAX_VALUE;
for (int i = 0; i < openList.size(); i++) {
if (openList.get(i).F<minF) {
minF=openList.get(i).F;
}
}
for (int i = 0; i < openList.size(); i++) {
if (openList.get(i).F==minF) {
return(openList.get(i));
}
}
return null;
}

static int calcuH(Coordinate srcC,Coordinate desC) {
int srcCX=srcC.x*10;
int srcCY=-srcC.y*10;
if (srcC.x%2!=0) {
srcCY-=5;
}
int desCX=desC.x*10;
int desCY=-desC.y*10;
if (desC.x%2!=0) {
desCY-=5;
}
double _x = Math.abs(srcCX - desCX);
double _y = Math.abs(srcCY - desCY);
return (int) Math.sqrt(_x*_x+_y*_y);
}

}

Coordinate:

package gpp.object;

import java.util.ArrayList;
import java.util.List;

public class Coordinate {
public int x;
public int y;
public boolean isBlock;

public Coordinate parent;
public int speed;
public int F;
public int G;
public int H;

public Coordinate(int x, int y) {
this.x = x;
this.y = y;
isBlock=false;
}

Coordinate findUp() {
return new Coordinate(x, y-1);
}

Coordinate findDown() {
return new Coordinate(x, y+1);
}

Coordinate findUpL() {
if (x%2==0) {
return new Coordinate(x-1, y-1);
}else {
return new Coordinate(x-1, y);
}
}

Coordinate findUpR() {
if (x%2==0) {
return new Coordinate(x+1, y-1);
}else {
return new Coordinate(x+1, y);
}
}

Coordinate findDownL() {
if (x%2==0) {
return new Coordinate(x-1, y);
}else {
return new Coordinate(x-1, y+1);
}
}

Coordinate findDownR() {
if (x%2==0) {
return new Coordinate(x+1, y);
}else {
return new Coordinate(x+1, y+1);
}
}

public List<Coordinate> findNear(){
ArrayList<Coordinate> res=new ArrayList<>();
return res;
}

@Override
public boolean equals(Object obj) {
Coordinate inC=(Coordinate)obj;
if (inC.x==x&&inC.y==y) {
return true;
}
return false;
}

//	public int getPG() {
//		int sum=0;
//		if (parent!=null) {
//			sum=parent.G;
//		}
//		return sum;
//	}

if (parent!=null) {
}
}

}

HexagonMapGUI:

package gpp.wuxia.world;

import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.GeneralPath;
import java.awt.geom.Line2D;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JFrame;
import javax.swing.JPanel;

import com.alibaba.fastjson.JSON;

import gpp.object.Coordinate;
import gpp.util.APathfindingHex;
import gpp.util.RandomUtil;
import javax.swing.JButton;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;

public class HexagonMapGUI {

private JFrame frame;
private JPanel canvas;

/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
HexagonMapGUI window = new HexagonMapGUI();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}

/**
* Create the application.
*/
public HexagonMapGUI() {
initialize();
}

/**
* Initialize the contents of the frame.
*/
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 800, 800);
frame.setSize(885, 899);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(null);

canvas = new Canvas();
canvas.setBounds(30, 30, 800, 800);
canvas.setBackground(new Color(244, 244, 244));

JButton btnNewButton = new JButton("刷新");
public void actionPerformed(ActionEvent e) {
canvas.repaint();
}
});
btnNewButton.setBounds(10, 10, 93, 23);

}

public class Canvas extends JPanel {
double outR = 3;
double innerR = outR / 2 * Math.sqrt(3);

public Canvas() {
// repaint();
}

public void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(new Color(0, 0, 0));// 边线颜色

List<Coordinate> totalC = new ArrayList<>();

int sizeX = 150;
int sizeY = 150;

for (int i = 0; i < sizeX; i++) {
for (int j = 0; j < sizeY; j++) {
Coordinate temp = new Coordinate(i, j);
temp.speed = 10;
}
}

// 画地图
for (Coordinate coordinate : totalC) {
drawByIndex(g2d, coordinate, new Color(255, 255, 0));
}

// 随机障碍物
for (Coordinate coordinate : totalC) {
if (RandomUtil.getFloat() < 0.2) {
coordinate.isBlock = true;
drawByIndex(g2d, coordinate, new Color(255, 0, 0));
}
}

// 随机森林
for (Coordinate coordinate : totalC) {
if (RandomUtil.getFloat() < 0.4) {
coordinate.speed=15;
coordinate.isBlock=false;
drawByIndex(g2d, coordinate, new Color(0, 255, 0));
}
}

int rany1=RandomUtil.getIndex(sizeY);
int rany2=RandomUtil.getIndex(sizeY);
int rany3=RandomUtil.getIndex(sizeY);

// 随机高速公路
for (Coordinate coordinate : totalC) {
if (coordinate.y==rany1||coordinate.x==rany1) {
coordinate.speed=5;
coordinate.isBlock=false;
drawByIndex(g2d, coordinate, new Color(222, 255, 222));
}

if (coordinate.y==rany2||coordinate.x==rany2) {
coordinate.speed=5;
coordinate.isBlock=false;
drawByIndex(g2d, coordinate, new Color(222, 255, 222));
}

if (coordinate.y==rany3) {
coordinate.speed=5;
coordinate.isBlock=false;
drawByIndex(g2d, coordinate, new Color(222, 255, 222));
}
}

System.out.println("啦啦啦,画好啦~");
// Coordinate c=new Coordinate(14, 9);
// drawByIndex(g2d,c,new Color(0,255,225));
// List<Coordinate> listC=c.findNear();
// for (Coordinate tempC : listC) {
// drawByIndex(g2d,tempC,new Color(0,255,225));
// }

APathfindingHex apath = new APathfindingHex(totalC);
List<Coordinate> path = apath.start(new Coordinate(0, 0), new Coordinate(140, 140));
if (path != null) {
// for (Coordinate coordinate : apath.openList) {
// drawByIndex(g2d,coordinate,new Color(155,233,188));
// }
//				for (Coordinate coordinate : apath.closeList) {
//					drawByIndex(g2d, coordinate, new Color(123, 70, 188));
//				}
for (Coordinate coordinate : path) {
drawByIndex(g2d, coordinate, new Color(100, 50, 255));
}
}
}

void drawByIndex(Graphics2D g2d, Coordinate coordinate, Color color) {
double x = outR + coordinate.x * (outR * 1.5);
double y = outR + coordinate.y * (innerR * 2);
if (coordinate.x % 2 == 1) {
y += innerR;
}
drawHexSolid(g2d, new Point(x, y), color);
Font font = new Font("Courier", Font.PLAIN, (int) (outR / 2));
g2d.setFont(font);
g2d.drawString("(" + coordinate.x + "," + coordinate.y + ")", (int) (x - outR / 1.5), (int) (y + outR / 4));
g2d.drawString(coordinate.F + "-" + coordinate.G + "-" + coordinate.H, (int) (x - outR / 1.5),
(int) (y + outR / 1.5));
}

// 画边
void drawHexSide(Graphics2D g2d, Point mid) {
Point point1 = new Point(mid.x + (outR / 2), mid.y + innerR);
Point point2 = new Point(mid.x + outR, mid.y);
Point point3 = new Point(mid.x + (outR / 2), mid.y - innerR);
Point point4 = new Point(mid.x - (outR / 2), mid.y - innerR);
Point point5 = new Point(mid.x - outR, mid.y);
Point point6 = new Point(mid.x - (outR / 2), mid.y + innerR);

g2d.drawLine(point1.getIntX(), point1.getIntY(), point2.getIntX(), point2.getIntY());
g2d.drawLine(point2.getIntX(), point2.getIntY(), point3.getIntX(), point3.getIntY());
g2d.drawLine(point3.getIntX(), point3.getIntY(), point4.getIntX(), point4.getIntY());
g2d.drawLine(point4.getIntX(), point4.getIntY(), point5.getIntX(), point5.getIntY());
g2d.drawLine(point5.getIntX(), point5.getIntY(), point6.getIntX(), point6.getIntY());
g2d.drawLine(point6.getIntX(), point6.getIntY(), point1.getIntX(), point1.getIntY());

}

// 画实心
void drawHexSolid(Graphics2D g2d, Point mid, Color color) {
Point point1 = new Point(mid.x + (outR / 2), mid.y + innerR);
Point point2 = new Point(mid.x + outR, mid.y);
Point point3 = new Point(mid.x + (outR / 2), mid.y - innerR);
Point point4 = new Point(mid.x - (outR / 2), mid.y - innerR);
Point point5 = new Point(mid.x - outR, mid.y);
Point point6 = new Point(mid.x - (outR / 2), mid.y + innerR);

GeneralPath gp = new GeneralPath(); // shape的子类，表示一个形状
gp.append(new Line2D.Double(point1.x, point1.y, point2.x, point2.y), true); // 在形状中添加一条线，即Line2D
gp.lineTo(point3.x, point3.y); // 添加一个点,并和之前的线段相连
gp.lineTo(point4.x, point4.y); // 同上
gp.lineTo(point5.x, point5.y); // 同上
gp.lineTo(point6.x, point6.y); // 同上
gp.closePath(); // 关闭形状创建

Color temp = g2d.getColor();
g2d.setColor(color);
g2d.fill(gp);
g2d.setColor(temp);
g2d.draw(gp);

}

}

public class Point {
public double x;
public double y;

Point(double x, double y) {
this.x = x;
this.y = y;
}

public int getIntX() {
return (int) Math.round(x);
}

public int getIntY() {
return (int) Math.round(y);
}
}
}