Skip to content
Permalink
master
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Go to file
Latest commit 243b938 Mar 22, 2018 History
2 contributors

Users who have contributed to this file

@jansonsa @issakas
#ifndef CORDINATE_H
#define CORDINATE_H
#pragma once
#include <stack>
#include <vector>
#include <array>
#define X_MAX 1000
#define X_STEP 20
#define Y_MAX 500
#define Y_STEP 20
struct Node
{
int y;
int x;
int parentX;
int parentY;
float gCost;
float hCost;
float fCost;
};
inline bool operator < (const Node& lhs, const Node& rhs)
{//We need to overload "<" to put our struct into a set
return lhs.fCost < rhs.fCost;
}
class Cordinate {
public:
static bool isValid(int x, int y) { //If our Node is an obstacle it is not valid
int id = x + y * (X_MAX / X_STEP);
if (world.obstacles.count(id) == 0) {
if (x < 0 || y < 0 || x >= (X_MAX / X_STEP) || y >= (Y_MAX / Y_STEP)) {
return false;
}
return true;
}
return false;
}
static bool isDestination(int x, int y, Node dest) {
if (x == dest.x && y == dest.y) {
return true;
}
return false;
}
static double calculateH(int x, int y, Node dest) {
double H = (sqrt((x - dest.x)*(x - dest.x)
+ (y - dest.y)*(y - dest.y)));
return H;
}
static vector<Node> makePath(array<array<Node, (Y_MAX / Y_STEP)>, (X_MAX / X_STEP)> map, Node dest) {
try {
cout << "Found a path" << endl;
int x = dest.x;
int y = dest.y;
stack<Node> path;
vector<Node> usablePath;
while (!(map[x][y].parentX == x && map[x][y].parentY == y)
&& map[x][y].x != -1 && map[x][y].y != -1)
{
path.push(map[x][y]);
int tempX = map[x][y].parentX;
int tempY = map[x][y].parentY;
x = tempX;
y = tempY;
}
path.push(map[x][y]);
while (!path.empty()) {
Node top = path.top();
path.pop();
//cout << top.x << " " << top.y << endl;
usablePath.emplace_back(top);
}
return usablePath;
}
catch(const exception& e){
cout << e.what() << endl;
}
}
static vector<Node> aStar(Node player, Node dest) {
vector<Node> empty;
if (isValid(dest.x, dest.y) == false) {
cout << "Destination is an obstacle" << endl;
return empty;
//Destination is invalid
}
if (isDestination(player.x, player.y, dest)) {
cout << "You are the destination" << endl;
return empty;
//You clicked on yourself
}
bool closedList[(X_MAX / X_STEP)][(Y_MAX / Y_STEP)];
//Initialize whole map
//Node allMap[50][25];
array<array < Node, (Y_MAX / Y_STEP)>, (X_MAX / X_STEP)> allMap;
for (int x = 0; x < (X_MAX / X_STEP); x++) {
for (int y = 0; y < (Y_MAX / Y_STEP); y++) {
allMap[x][y].fCost = FLT_MAX;
allMap[x][y].gCost = FLT_MAX;
allMap[x][y].hCost = FLT_MAX;
allMap[x][y].parentX = -1;
allMap[x][y].parentY = -1;
allMap[x][y].x = x;
allMap[x][y].y = y;
closedList[x][y] = false;
}
}
//Initialize our starting list
int x = player.x;
int y = player.y;
allMap[x][y].fCost = 0.0;
allMap[x][y].gCost = 0.0;
allMap[x][y].hCost = 0.0;
allMap[x][y].parentX = x;
allMap[x][y].parentY = y;
vector<Node> openList;
openList.emplace_back(allMap[x][y]);
bool destinationFound = false;
while (!openList.empty()&&openList.size()<(X_MAX / X_STEP)*(Y_MAX / Y_STEP)) {
Node node;
do {
//This do-while loop could be replaced with extracting the first
//element from a set, but you'd have to make the openList a set.
//To be completely honest, I don't remember the reason why I do
//it with a vector, but for now it's still an option, although
//not as good as a set performance wise.
float temp = FLT_MAX;
vector<Node>::iterator itNode;
for (vector<Node>::iterator it = openList.begin();
it != openList.end(); it = next(it)) {
Node n = *it;
if (n.fCost < temp) {
temp = n.fCost;
itNode = it;
}
}
node = *itNode;
openList.erase(itNode);
} while (isValid(node.x, node.y) == false);
x = node.x;
y = node.y;
closedList[x][y] = true;
//For each neighbour starting from North-West to South-East
for (int newX = -1; newX <= 1; newX++) {
for (int newY = -1; newY <= 1; newY++) {
double gNew, hNew, fNew;
if (isValid(x + newX, y + newY)) {
if (isDestination(x + newX, y + newY, dest))
{
//Destination found - make path
allMap[x + newX][y + newY].parentX = x;
allMap[x + newX][y + newY].parentY = y;
destinationFound = true;
return makePath(allMap, dest);
}
else if (closedList[x + newX][y + newY] == false)
{
gNew = node.gCost + 1.0;
hNew = calculateH(x + newX, y + newY, dest);
fNew = gNew + hNew;
// Check if this path is better than the one already present
if (allMap[x + newX][y + newY].fCost == FLT_MAX ||
allMap[x + newX][y + newY].fCost > fNew)
{
// Update the details of this neighbour node
allMap[x + newX][y + newY].fCost = fNew;
allMap[x + newX][y + newY].gCost = gNew;
allMap[x + newX][y + newY].hCost = hNew;
allMap[x + newX][y + newY].parentX = x;
allMap[x + newX][y + newY].parentY = y;
openList.emplace_back(allMap[x + newX][y + newY]);
}
}
}
}
}
}
if (destinationFound == false) {
cout << "Destination not found" << endl;
return empty;
}
}
};
#endif