⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 astar.c

📁 此代码效率非常高。此代码实现最短路径的搜索。
💻 C
字号:
/*****************************************************************/
/*函数名称: GPS_Navigation.c                                    */
/*函数功能: 小车导航,实现最短路径                              */      
/*有无返回: 无                                                  */
/*修改记录: 无修改记录                                          */
/*编写作者: t483-4-19chenyong                                   */
/*编写日期: 2008-3-12                                           */
/*****************************************************************/


#include "common.h"                    
#include "TS12864A.h"
#include "navigation.h "
#include "delay.h" 
#include "map.h"  
#include "key.h"
#include "astar.h"
#include "window.h"

/*****************************************************************/
/*
				   /----------GPS导航电子地图(测试版本)
				  /
			  	 /-------------------------------------------
                |       S,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,	 |
				|	    *,*,*,*,*,B,*,*,*,*,*,*,*,*,*,*,	 | 
                |       *,*,*,*,*,*,*,*,*,*,*,*,*,*,E,*,	 | 
				|	    *,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,	 | 
				|	    *,*,*,A,*,*,*,*,*,*,*,*,*,*,*,*,	 |
				|	    *,*,*,*,*,*,*,*,*,*,C,*,*,*,*,*,	 | 
				|	    *,*,*,*,*,*,F,*,*,*,*,*,*,*,*,*,	 | 
				|	    *,*,*,*,*,*,*,*,*,*,*,*,*,*,D,*,	 |
			   	 -------------------------------------------
说明: A,B,C,D,E,F为用户要到达的终点,S为起点。通过按键盘上的按键
       实现小车的最短路径搜索,并通过液晶显示行驶的步数。

*/


struct 	MapData 
              {
			        unsigned char Gps_Map_Length[Map_Length];
              		unsigned char Gps_Map_Width[Map_Width];	  			  
			  };

xdata   struct  MapData;
extern unsigned char key;
extern unsigned int  Position;

byte_t    maze[MAZE_HEIGHT][MAZE_WIDTH] = {
                0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
                1,0,1,0,1,1,1,0,1,1,1,0,0,1,0,1,
                0,0,1,0,1,0,0,1,1,0,1,1,0,1,1,1,
                1,0,1,1,1,1,1,1,1,1,1,1,1,0,1,1,
                1,1,1,1,0,1,1,0,1,0,1,0,1,1,1,1,
                1,1,0,1,1,1,1,1,1,0,1,0,1,1,0,0,
                0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,
                0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
};
byte_t    maze0[MAZE_HEIGHT][MAZE_WIDTH] = {
                0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
                1,0,1,0,1,1,1,0,1,1,1,0,0,1,0,1,
                0,0,1,0,1,0,0,1,1,0,1,1,0,1,1,1,
                1,0,1,1,1,1,1,1,1,1,1,1,1,0,1,1,
                1,1,1,1,0,1,1,0,1,0,1,0,1,1,1,1,
                1,1,0,1,1,1,1,1,1,0,1,0,1,1,0,0,
                0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,
                0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
};

/*
    方向信号量查询表
    0x01(0000 0001) : 上
    0x02(0000 0010) : 下
    0x04(0000 0100) : 左
    0x08(0000 1000) : 右
*/

byte_t d_signal[4]  = {0x01, 0x02, 0x04, 0x08};

/*
    方向信号量使用表
    如果指定方向已经走过,那么使用“与”运算去处该方向
    0x0E(0000 1110) : 上
    0x0D(0000 1101) : 下
    0x0B(0000 1011) : 左
    0x07(0000 0111) : 右
*/

byte_t d_spend[4]   = {0x0E, 0x0D, 0x0B, 0x07};

/* 指定方向移动偏量 */
int      move[4][2]   = { {0, -1}, {0, 1}, {-1, 0}, {1, 0} };

/* 打印迷宫用的符号 */
byte_t symbol[3]   = {0,1,2};

/* 求两点间的距离 */

uint_t distance( uint_t pos1X, uint_t pos1Y, uint_t pos2X, uint_t pos2Y ) {

    uint_t    ret = 0;

    /* 距离公式 */
    ret = (uint_t)sqrt((pow((double)((int)pos1X - (int)pos2X),2) + pow((double)((int)pos1Y - (int)pos2Y),2)));

    return ret;

}

/* 压缩坐标 */
uint_t create_pos( uint_t pX, uint_t pY ) {
    uint_t ret = 0;
    /* 将pX赋给ret,这样pX坐标在ret的低八位 */
    ret = pX;

    /* 将pX坐标移到高八位去,这样低位就能存放pY */
    ret <<= 8;
    /* 将pY存放放到ret的低八位,并保持高八位的数据不变 */
    ret  |= pY;

    return ret;
}

/*
== 估计函数 ===========================================
-p            : 当前移动到的节点指针
-quit_x
-quit_y        : quit_x 和 quit_y表示迷宫出口坐标
-maze       : 迷宫矩阵
=======================================================
*/
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;

    /* 用于接收四个方向离开出口的距离,以便选择最近的方向移动 */
    int    dis[4];
    int minDis = 32767;
    int minId  = -1;

    path_t *pnode = (path_t *)0;

    register int i;

    /* 计算当前节点的坐标 */
    pX = p->pos >> 8;
    pY = p->pos & 0x00FF;

    memset(dis, (int)-1, sizeof(int)*4);

    /* 计算每个方向离开出口的距离,一次存放到dis数组,若没有i方向,则dis[i]任保留-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);
    }

    /* 获得最短距离的方向 */
    for(i = 0; i < 4; ++i) {
        if(dis[i] != -1 && dis[i] < minDis) {
            minId = i;
            minDis = dis[i];
        }
    }

    /* 若没有可用的方向,则通知寻径函数折回 */
    if(minId == -1)
        return (path_t *)0;

    /* 用去最近距离方向的信号量 */
    p->direct &= d_spend[minId];
    /* 在移动到新位置之前,在旧位置处留下足迹 */
    maze[pY][pX] = (byte_t)PATH_FOOTPRINT;

    /* 构建新的路径节点 */
    pnode = (path_t *)malloc(sizeof(path_t));
    assert(pnode);

    /* 计算下一个位置的坐标 */
    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;

    /* 在新位置处,计算下一个位置可用的移动方向 */
    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) {
            /* 若尝试的下一个位置不是障碍物或自己走过的足迹,则视为可用方向,获得该方向的信号量 */
                pnode->direct |= d_signal[i];
        }
    }

    return pnode;

}

/*
== A*算法寻径函数 ===========================================
-eX
-eY                  :入口坐标
-qX
-qY                  :出口坐标
-maze              :迷宫矩阵
=============================================================
*/

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;


    /* 压缩坐标 */
    uint_t quit_pos = create_pos(qX, qY);

    /* 构建入口路径节点,视为路径链的头 */
    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;

    /* 创建入口处的可用方向 */
    for(i = 0; i < 4; ++i) {
        if(maze[eY + move[i][1]][eX + move[i][0]] != PATH_BLOCK)
            /* 若无障碍物则获得该方向的信号量 */
            p->direct |= d_signal[i];
    }

    do {

        /* 获得下个路径的节点指针 */
        back = evaluate(p, qX, qY, maze);
        if(back) {
            p->next = back;
            p = p->next;
        }

        /* 无路可走则折回 */
        if(p->direct == 0 && p != head && p->pos != quit_pos) {
            back = p->prev;
            back->next = (path_t *)0;

            /* 清楚脚印 */
            maze[p->pos & 0x00FF][p->pos >> 8] = (byte_t)PATH_WALKON;

            free(p);
            p = back;
        }

        /* 若走不出迷宫,即折回到入口,且入口处的可用方向全部尝试过 */
        if(p == head && p->direct == 0) {
            free(head);
            return (path_t *)0;
        }

    } while( p->pos != quit_pos );

    /* 在出口处留下脚印,便于打印 */
    maze[p->pos & 0x00FF][p->pos >> 8] = (byte_t)PATH_FOOTPRINT;

    return head;

}
/*****************************************************************/


/*****************************************************************/
/*函数名称: show_menu_DaoHang.c                                 */
/*函数功能: GPS导航                                             */      
/*有无返回: 无                                                  */
/*修改记录: 无修改记录                                          */
/*入口参数: 
             start_x------------------------------------起点x坐标
			 start_y------------------------------------起点y坐标
			 end_x  ------------------------------------终点x坐标
			 end_y  ------------------------------------终点y坐标
			                                                     */
/*编写日期: 2008-5-01                                           */
/*****************************************************************/

//void show_menu_DaoHang(unsigned char start_x,unsigned char start_y,unsigned char end_x,unsigned char end_y)
void show_menu_DaoHang()
 {
     register unsigned char  i=0,j=0; 
	 path_t *pHead;
 	 byte_t    mazetemp[MAZE_HEIGHT][MAZE_WIDTH]={0};

	 for(i = 0; i < MAZE_HEIGHT; ++i) 
	 {
        for(j = 0; j < MAZE_WIDTH; ++j)
	    mazetemp[i][j]=maze[i][j];
     
	 } 
     pHead=AStar((uint_t)(Position/1000),(uint_t)(Position%1000/100),(uint_t)(Position%100/10),(uint_t)(Position%10),mazetemp);
  
    
    /* 打印地图 */
 
     for(i = 0; i < MAZE_HEIGHT; ++i) 
	 {
        for(j = 0; j < MAZE_WIDTH; ++j)
        Display_Point(j,i,symbol[mazetemp[i][j]]);
		/*
			  j-------代表x方向
			  i-------代表y方向
			  symbolic-路径显示	    
		*/

     }
 
}
 
void Show_Map()
{

	 register unsigned char point_x=0,point_y=0;
     for(point_y = 0; point_y < MAZE_HEIGHT; ++point_y) 
	 {
        for(point_x = 0; point_x < MAZE_WIDTH; ++point_x)

//         Display_Point(point_x,point_y,symbol[maze[point_y][point_x]]);
		   Display_Point(point_x,point_y,symbol[maze0[point_y][point_x]]);
		
			/*	  i-------代表y方向													
	        	  j-------代表x方向
			     symbolic-路径显示	    
		    */

     }

}
  
    

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -