Next I will talk about the principle of the * algorithm I understand:
A * algorithm is A function for finding the shortest path. It is used by many real-time strategic games (maybe the author's algorithm of Large-Scale Real-Time Strategic games is better, regardless of it ). It consists of two functions. One is an evaluation function, that is, to determine that the next position of a person's movement must be closest to the target location. The more accurate the evaluation result is, the path finding speed is faster. The other is the path finding function, which responds according to the evaluation result and continues to evaluate the next position from the new position. If there is no way to go (the four sides are obstacles or something ), if you fold back to a path node and try other directions, this algorithm has a disadvantage. As the number of players in the game increases, the corresponding processing nodes increase, affecting the processing speed, it also occupies a large amount of memory.
If you are interested, you can change it to a dynamic path finding, that is, when the entrance and exit locations are changing, the path finding code is only over 200 lines.
My algorithm is not optimal yet, because the evaluation function is just a simple test of the Two-Point distance (which will lead to errors), and the direction of the nearest exit and non-obstacle is selected, move the next path node.
I hope you can use my code for your learning purpose, but I don't want to see it as a copy of it for submitting a job. I will be very sad.
/* AStar. cpp */
/* Designer: yuki */
Typedef unsigned char byte_t;
Typedef unsigned int uint_t;
/* Path node */
Typedef struct footprint {
/* Location in the array */
Uint_t pos;
/* Specify the direction semaphore */
Byte_t direct;
Struct footprint * next;
Struct footprint * prev;
} Path_t;
/*
Direction semaphores query table
0x01 (0000 0001): Top
0x02 (0000 0010): Bottom
0x04 (0000 0100): left
0x08 (0000 1000): Right
*/
Static byte_t d_signal [4] = {0x01, 0x02, 0x04, 0x08 };
/*
Direction semaphore Usage Table
If the specified direction has passed, use the "and" operation to go to this direction.
0x0E (0000 1110): Top
0x0D (0000 1101): Bottom
0x0B (0000 1011): left
0x07 (0000 0111): Right
*/
Static byte_t d_spend [4] = {0x0E, 0x0D, 0x0B, 0x07 };
/* Move the offset in the specified direction */
Static int move [4] [2] = {0,-1}, {0, 1}, {-1, 0}, {1, 0 }};
/* Print the symbols used for the maze */
Static byte_t symbolic [3] = {'#', 0x20 ,'*'};
/* Calculate the distance between two points */
Inline uint_t
Distance (uint_t pos1X, uint_t pos1Y, uint_t pos2X, uint_t pos2Y ){
Uint_t ret = 0;
/* Distance formula */
Ret = (uint_t) sqrt (pow (double) (int) pos1X-(int) pos2X), 2) + pow (double) (int) pos1Y-(int) pos2Y), 2 )));
Return ret;
}
/* Compress coordinates */
Inline uint_t
Create_pos (uint_t pX, uint_t pY ){
Uint_t ret = 0;
/* Assign pX to ret, so that the pX coordinates are at the lowest eight bits of ret */
Ret = pX;
/* Move the pX coordinates to the upper eight bits so that the lower position can store pY */
Ret <= 8;
/* Store pY in the Low eight bits of ret and keep the data of the high eight bits unchanged */
Ret | = pY;
Return ret;
}
/*
================================================ ========
-P: pointer to the currently migrated Node
-Quit_x
-Quit_y: quit_x and quit_y indicate the maze exit coordinates.
-Maze: maze Matrix
========================================================== ====================
*/
Inline path_t *
Evaluate (path_t * P, uint_t quit_x, uint_t quit_y, byte_t maze [maze_height] [maze_width]) {
Uint_t PX, Py;
/* It is used to receive the distance from the exit in four directions, so as to select the nearest direction to move */
Int dis [4];
Int mindis= 32767;
Int minid =-1;
Path_t * pnode = (path_t *) 0;
Register int I;
/* Calculate the coordinates of the current node */
Px = p-> POS> 8;
Py = p-> POS & 0x00ff;
Memset (DIS, (INT)-1, sizeof (INT) * 4 );
/* Calculate the distance from exit in each direction and store it in the dis array at a time. If there is no direction I, dis [I] will be retained-1 */
For (I = 0; I <4; ++ I ){
If (p-> direct & d_signal [I])> I = 0x01)
Dis [I] = (int) distance (pX + move [I] [0], pY + move [I] [1], quit_x, quit_y );
}
/* Obtain the shortest path */
For (I = 0; I <4; ++ I ){
If (dis [I]! =-1 & dis [I] <minDis ){
MinId = I;
MinDis = dis [I];
}
}
/* If no direction is available, the Pathfinder function is returned */
If (minId =-1)
Return (path_t *) 0;
/* Use the semaphore in the nearest distance */
P-> direct & = d_spend [minId];
/* Leave a footprint at the old location before moving to the new location */
Maze [pY] [pX] = (byte_t) PATH_FOOTPRINT;
/* Create a new path node */
Pnode = (path_t *) malloc (sizeof (path_t ));
Assert (pnode );
/* Calculate the coordinates of the next position */
PX + = move [minId] [0];
PY + = move [minId] [1];
Pnode-> pos = create_pos (pX, pY );
Pnode-> prev = p;
Pnode-> next = (path_t *) 0;
Pnode-> direct = 0;
/* Calculate the available direction of movement at the next position */
For (I = 0; I <4; ++ I ){
If (maze [pY + move [I] [1] [pX + move [I] [0]! = PATH_BLOCK & maze [pY + move [I] [1] [pX + move [I] [0]! = PATH_FOOTPRINT ){
/* If the next position of the attempt is not an obstacle or the footprint you walk through, it is regarded as an available direction to obtain the semaphore in this direction */
Pnode-> direct | = d_signal [I];
}
}
Return pnode;
}
/*
= A * algorithm path finding function ==================================== ==============
-EX
-EY: Entry Coordinate
-QX
-QY: Exit Coordinate
-Maze: maze Matrix
========================================================== ==================================
*/
Inline path_t *
AStar (uint_t eX, uint_t eY, uint_t qX, uint_t qY, byte_t maze [MAZE_HEIGHT] [MAZE_WIDTH]) {
Register int I;
/* Compress coordinates */
Uint_t quit_pos = create_pos (QX, QY );
/* Construct the entry path node, which is regarded as the path chain header */
Path_t * head = (path_t *) malloc (sizeof (path_t ));
Path_t * P = (path_t *) 0;
Path_t * back = (path_t *) 0;
Assert (head );
P = head;
P-> direct = 0;
P-> Pos = create_pos (ex, ey );
P-> next = (path_t *) 0;
P-> Prev = (path_t *) 0;
/* Create available directions for the entrance */
For (I = 0; I <4; ++ I ){
If (maze [ey + move [I] [1] [ex + move [I] [0]! = Path_block)
/* Obtain the semaphore in this direction if no obstacle exists */
P-> direct | = d_signal [I];
}
Do {
/* Get the node pointer of the next path */
Back = evaluate (p, QX, QY, maze );
If (back ){
P-> next = back;
P = p-> next;
}
/* Returns if there is no way to go */
If (p-> direct = 0 & P! = Head & P-> pos! = Quit_pos ){
Back = p-> Prev;
Back-> next = (path_t *) 0;
/* Clear footprints */
Maze [p-> pos & 0x00FF] [p-> pos> 8] = (byte_t) path_#on;
Free (p );
P = back;
}
/* If you do not walk out of the maze, you will be taken back to the entrance, and all available directions at the entrance have been tried */
If (p = head & p-> direct = 0 ){
Free (head );
Return (path_t *) 0;
}
} While (p-> pos! = Quit_pos );
/* Leave footprints at the exit to facilitate printing */
Maze [p-> pos & 0x00FF] [p-> pos> 8] = (byte_t) PATH_FOOTPRINT;
Return head;
}
/* AStar. h */
/* Designer: yuki */
# Ifndef _ ASTAR_H
# Define _ ASTAR_H
# Define MAZE_WIDTH 10/* maze width */
# Define MAZE_HEIGHT 10/* maze height */
# Define PATH_BLOCK 0/* obstacle */
# Define path_detail on 1/* Walking */
# Define PATH_FOOTPRINT 2/* footprint */
# Include "AStar. cpp"
# Endif
/* Main. cpp */
/* Designer: yuki */
# Include <stdio. h>
# Include <stdlib. h>
# Include <string. h>
# Include <conio. h>
# Include <math. h>
# Include <assert. h>
# Include "AStar. h"
Static byte_t maze [maze_height] [maze_width] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 1, 1, 0, 1, 1, 1, 0, 1, 0,
0, 1, 1, 0, 1, 1, 1, 0, 1, 0,
0, 1, 1, 1, 1, 0, 0, 0, 1, 0,
0, 1, 0, 0, 0, 1, 1, 0, 1, 0,
0, 1, 1, 1, 0, 1, 1, 0, 1, 0,
0, 1, 0, 1, 1, 1, 0, 1, 1, 0,
0, 1, 0, 0, 0, 1, 0, 0, 1, 0,
0, 0, 1, 1, 1, 1, 1, 1, 1, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
Int main (){
Register int I, j;
Path_t * pHead = AStar (uint_t) 1, (uint_t) 1, (uint_t) 2, (uint_t) 8, maze );
Path_t * p = pHead;
Path_t * bak;
If (p ){
Bak = p-> next;
Printf ("(% u, % u)", p-> pos> 8, p-> pos & 0x00FF );
Free (p );
P = bak;
While (p ){
Bak = p-> next;
Printf ("-> (% u, % u)", p-> pos> 8, p-> pos & 0x00FF );
Free (p );
P = bak;
}
Printf ("/n ");
}
Else
Printf ("No path to get out of the maze/n ");
PHead = p = bak = (path_t *) 0;
/* Print the maze */
For (I = 0; I <MAZE_HEIGHT; ++ I ){
For (j = 0; j <MAZE_WIDTH; ++ j)
Printf ("% c", symbolic [maze [I] [j]);
Printf ("/n ");
}
Getch ();
Return 0;
}