Giter Site home page Giter Site logo

lukeproducts / astar-pathfinding-cpp Goto Github PK

View Code? Open in Web Editor NEW
3.0 1.0 1.0 590 KB

A* Pathfinding C++ providing many additional features

License: BSD 2-Clause "Simplified" License

C++ 100.00%
astar astar-algorithm astar-pathfinding astar-pathfinder astar-search-algorithm astar-search astar-cpp lukeproducts game-pathfinding maze-solver

astar-pathfinding-cpp's Introduction

A* Pathfinding

This module was developed to determine the shortest, (i.e. the fastest) path from a to b on a two-dimensional playing field called maze. A distinction is made between walkable and non-walkable paths. For the representation of a maze a two nested vector is used.

How does the A* - Algorithm works?

It is started with the help of a specified labirynth and a start and end node, of which only the position is known at the beginning of the runtime. Now all possible paths around this node are examined, and these then again just like the start node until a node arrives at the position of the end node. Then the fastest possible way from start to end is explored, i.e. the best node to go, and then output.



why the A*-Algorithm is extremely fast:

The path problem is solved as quickly as possible by calculating a score from the estimated distance and the sum of paths already taken, which is used to prioritize the order in which the neighbor nodes are investigated. This also has the effect that A* always knows in which direction the end node is and therefore does not first examine the neighbor away from it, but first all fast paths.

The formula used for this is:

f(n) = g(n) + h(n)



n

is the Node Object itself


g(n)

Is the estimate of how far n is from the end node

(current_cell.x – goal.x)^2 + (current_cell.y – goal.y)^2


h(n) Is the number of travelled path units from the start node to the current position of n


f(n) the sum of both g(n) and h(n)

is a score value with which we select and examine from different nodes the one with the best score, with the greatest probability of being the fastest path, which makes the code much faster, because otherwise the graph would not look like above, but like this:

much slower search,
because the algorith has no clue,
in which direction to go first,
so it goes in each direction with
the same priority






Example:

############################### -----------------------------------> ###############################
#a  #   # #         #   #     # -----------------------------------> #s++#   # #++++++++#   #     #
### # ### # ####### # ### ##### -----------------------------------> ###+# ### #+#######+# ### #####
# #       # #     #     # #   # -----------------------------------> # #+++++++#+#     #+++  # #   #
# ##### # # ##### ### ### ### # -----------------------------------> # ##### #+#+##### ###+### ### #
#   # # #     #         # #   # -----------------------------------> #   # # #+++  #    +++  # #   #
### # # ### ####### ##### # ### -----------------------------------> ### # # ### #######+##### # ###
#   #   # #     #           # # -----------------------------------> #   #   # #     #  +++++++  # #
# ### ### ### # ### ##### ### # -----------------------------------> # ### ### ### # ### #####+### #
#       #   # # #   #         # -----------------------------------> #       #   # # #   #    +++  #
### ####### ### ########### # # -----------------------------------> ### ####### ### ###########+# #
#   #       # #   # # #     # # -----------------------------------> #   #       # #   # # #  +++# #
### # ### # # # ### # # # ### # -----------------------------------> ### # ### # # # ### # # #+### #
#       # # # #       # # # # # -----------------------------------> #       # # # #       # #+# # #
# # ##### # # ##### # ### # ### -----------------------------------> # # ##### # # ##### # ###+# ###
# #     # # #   #   # #   #   # -----------------------------------> # #     # # #   #   # #  +#   #
### ######### ### ####### # ### -----------------------------------> ### ######### ### #######+# ###
#   #   # #   #   #   # #     # -----------------------------------> #   #   # #   #   #   # #+++++#
# ### # # # ##### ### # ##### # -----------------------------------> # ### # # # ##### ### # #####+#
#     #         #           #b# -----------------------------------> #     #         #           #g#
############################### -----------------------------------> ###############################



included Features

AStarResult - Class


The main AStar() function returns a AStarResult class-object, which provides

  • whole path went
  • the total amount of moves done
  • print out the hole maze

// returns AStarResult Class
AStarResult result = AStar(prepare_maze(maze), start, end);
// returns min movements made to get from start_node to end_node
cout << "A* made " << result.movements << " moves to reach (" <<
end[0] << ", " << end[1] << ")"
<< " from (" << start[0] << ", " << start[1] << ")\n";
// prints out the whole maze with drawn path
result.print_maze_solution_path();
// .path_went variable contains the path went by the fastest node
vector<pos_type> went_path = result.path_went;

possible output:

A* made 64 moves to reach (19, 29) from (1, 1)
###############################
#s+++++++   # +++       #     #
#  #### +#  # +#+ #  ####  ####
#       +#  # +#++++ #        #
#  #### +#### +#  #+ #######  #
#     # +++++++#  #++++ #  #  #
######################+ #  ####
#  #                 #+       #
#  #######  ####  ####+ #  #  #
#  #     #  #        #+ #  #  #
#  #  #  #  #######  #+ #  #  #
#  #  #        #      + #  #  #
#  #  #  #######  ####++#######
#     #        #  #    ++++++ #
#  ####  #  #  #  #  #######+ #
#  #     #  #  #  #  #  #  #+ #
#  ##########  #  #  #  #  #+ #
#           #  #  #  # ++++++ #
#  #######  ########## +#######
#        #           # ++++++g#
###############################



prepare_maze - function


The prepare function converts a maze consisting out of
barriers (f.ex. '#') and walkable terrain (f.ex. ' ')
is converted to a maze out of zeroes and ones,
the ones represent the not walkable terrain and the zeroes the walkable terrain by default.

All this settings could be adjusted in the #define statements at the beginning of this package.

This is because AStar() needs this 2-dimensional vector
to figure out wheather its a walkable or not walkable terrain.

prepare_maze() can handle a vector<string> or vector<vector<char>>

vector<string> maze = {
"###############################",
"#a # # #",
"# #### # # # # #### ####",
"# # # # # #",
"# #### #### # # ####### #",
"# # # # # # #",
"###################### # ####",
"# # # #",
"# ####### #### #### # # #",
"# # # # # # # #",
"# # # # ####### # # # #",
"# # # # # # #",
"# # # ####### #### #######",
"# # # # #",
"# #### # # # # ####### #",
"# # # # # # # # # #",
"# ########## # # # # # #",
"# # # # # #",
"# ####### ########## #######",
"# # # b#",
"###############################"
};
// prepare maze to be able to pass it into AStar()
vector<vector<int>> prepared_maze = prepare_maze(maze);

what happens:

########## -----> 1111111111
#        # -----> 1000000001
# ##### ## -----> 1011111011
# ##    ## -----> 1011000011
# ##  #### -----> 1011001111
# ###    # -----> 1011100001
#  #  ## # -----> 1001001101
###  ##  # -----> 1110011001
##  ##  ## -----> 1100110011
########## -----> 1111111111

find_obj - function

find_obj finds an character out of a maze in ascii format,
such as vector<string> or vector<vector<char>>
and returns a vector<int> with the (x, y) position of the character into the maze.

This is usefull to figure out the start and ends position in your maze,
so that you can pass this info into Astar(), which needs the position
of the start and end node at second and third position like findobj() returns it for you.

vector<int> start = findobj(maze, 'a');
vector<int> end = findobj(maze, 'b');
// returns AStarResult Class
AStarResult result = AStar(prepare_maze(maze), start, end);


readmaze - function

readmaze reads in a maze from the consoles cin stream,
the first line must consist of two integers that indicate the height and width of the mazes to be read in.
In the following you can pass in the maze like this:

    10 10        // first 10 = m = rows, second 10 = n = columns
    ##########
    #        #
    # ##### ##
    # ##    ##
    # ##  ####
    # ###    #
    #  #  ## #
    ###  ##  #
    ##  ##  ##
    ##########

readmaze converts this directly to the maze format by calling the prepare_maze - function,
which AStar() needs,
so in the numeric one:

    1111111111
    1000000001
    1011111011
    1011000011
    1011001111
    1011100001
    1001001101
    1110011001
    1100110011
    1111111111

so you can pass in the return value vector<vector<int>> directly into the AStar - function:

// read in maze from the console
vector<vector<int>> maze = readmaze();
// returns AStarResult Class
AStarResult result = AStar(maze, pos_type{1, 1}, pos_type{5, 5});

the disatvantage here is, that because readmaze converts the ascii maze into a numeric one at one time,
you must know the start and end position before,
you would hardcode them,
but that's probably not, what you want.

So theres the pardon readunpreparedmaze presented in the following.


readunpreparedmaze - function

readunpreparedmaze does the same thing like readmaze in general,
but does not already convert it into a numeric vector,
but into a ascii one.

you'll get returned the following:

    ##########
    #a       #
    # ##### ##
    # ##    ##
    # ##  ####
    # ###    #
    #  #  ## #
    ###  ##  #
    ##  ## b##
    ##########

which makes it possible to find objects into this vector<srting> which is returned with the findobj - function, like shown here:

// read in maze from the console, but not directly convert it into a numeric maze
vector<vector<int>> maze = readunpreparedmaze();
/* because it's not already been converted into a numeric maze,
* you can get the position by finding chars here and don't need to know (and hardcode)
* the start and end position before
* */
pos_type start_pos = findobj(maze, 'a');
pos_type end_pos = findobj(maze, 'b');
// returns AStarResult Class
AStarResult result = AStar(prepare_maze(maze), start_pos, end_pos);

note, that you need to convert this maze with prepared_maze() manully, before passing it into AStar()


With that being said, have fun with it!



LP_Logo

© Copyright by LukeProducts

astar-pathfinding-cpp's People

Contributors

lukeproducts avatar

Stargazers

 avatar  avatar  avatar

Watchers

 avatar

Forkers

wuguanxi

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.