通过Astar算法实现8数码问题(C语言)

来源:互联网 发布:吉林省网络培训学院 编辑:程序博客网 时间:2024/06/14 21:00

    关于A*(Astar)算法的介绍可以参考另一篇博文: A*(Astar)搜索算法的实现(C语言)

    1.问题描述

        在3×3的棋盘,摆有八个棋子,每个棋子上标有1至8的某一数字,不同棋子上标的数字不相同。棋盘上还有一个空格,与空格相邻的棋子可以移到空格中。要求解决的问题是:给出一个初始状态和一个目标状态,找出一种从初始转变成目标状态的移动棋子步数最少的移动步骤。

    2.问题可解性

        八数码问题的一个状态实际上是0~9的一个排列,对于任意给定的初始状态和目标,不一定有解,也就是说从初始状态不一定能到达目标状态。因为排列有奇排列和偶排列两类,从奇排列不能转化成偶排列或相反。
        如果一个数字0~8的随机排列871526340,用F(X)表示数字X前面比它小的数的个数,全部数字的F(X)之和为Y=∑(F(X)),如果Y为奇数则称原数字的排列是奇排列,如果Y为偶数则称原数字的排列是偶排列。
        例如871526340这个排列的
        Y=0+0+0+1+1+3+2+3+0=10
        10是偶数,所以他偶排列。871625340
        Y=0+0+0+1+1+2+2+3+0=9
        9是奇数,所以他奇排列。
        因此,可以在运行程序前检查初始状态和目标状态的窘是否相同,相同则问题可解,应当能搜索到路径。否则无解。

    3.求解步骤

        1)建立一个队列,计算初始结点的估价函数f,并将初始结点入队,设置队列头和尾指针。
        2)取出队列头(队列头指针所指)的结点,如果该结点是目标结点,则输出路径,程序结束。否则对结点进行扩展。
        3)检查扩展出的新结点是否与队列中的结点重复,若与不能再扩展的结点重复(位于队列头指针之前),则将它抛弃;若新结点与待扩展的结点重复(位于队列头指针之后),则比较两个结点的估价函数中g的大小,保留较小g值的结点。跳至第五步。
        4)如果扩展出的新结点与队列中的结点不重复,则按照它的估价函数f大小将它插入队列中的头结点后待扩展结点的适当位置,使它们按从小到大的顺序排列,最后更新队列尾指针。
        5)如果队列头的结点还可以扩展,直接返回第二步。否则将队列头指针指向下一结点,再返回第二步。
        

    4.代码实现

        二叉堆代码就不贴出来了,在另一篇博文 A*(Astar)搜索算法的实现(C语言) 中已经给出,在本文最后有资源下载的链接。可以拿到完整的代码

astar_8.h
/** author:Atom* date:2012/12/04* file:astar_8.h*/#ifndef ASTAR_8_H#define ASTAR_8_H#include "bheap.h"#define MALLOC(type,n)  (type *)malloc((n)*sizeof(type))#define MAX(a,b) ((a)>(b))?(a):(b)#define UP  -3#define RIGHT 1#define DOWN3#define LEFT-1int node_distance[9][9];struct step_node{int step_status[9];int f;int g;int h;struct step_node* parent;};int _comp(struct Bheap_node* n1, struct Bheap_node* n2);int _eq(struct Bheap_node* n1, struct Bheap_node* n2);void astar_8(int start[9], int end[9]);static int calc_distance(int step_status[9], int end[9]);static int arr_idx(int n, int step_status[9]);static void init_node_distance(int node_distance[9][9]);static int is_end(int step_status[9], int end[9]);static int is_reachable(int space_idx, int flag);static int move_space(int step_status[9], int flag);static void print_step_status(int step_status[9]);static int check_whether_reach(int start[9], int end[9]);#endif

astar_8.c
/** author:Atom* date:2012/12/04* file:astar_8.c*/#include "astar_8.h"int main(int argc, char* argv[]){int i,j;init_node_distance(node_distance);int start[] = {2,3,4,1,8,5,0,7,6};int end[] = {1,2,3,8,0,4,7,6,5};#if 1if(check_whether_reach(start, end)){printf("sorry,No solution!\n");}elseastar_8(start, end);#elseastar_8(start, end);#endifreturn (0);}static int check_whether_reach(int start[9], int end[9]){int re_st = 0, re_end = 0;int tmp = 0;int i, j;for (i = 0; i < 9; i++){for(j = 0; j < i; j++)if (start[i] > start[j])re_st++;}for (i = 0; i < 9; i++){for(j = 0; j < i; j++)if (end[i] > end[j])re_end++;}return ((re_st^re_end)&0x01);}void astar_8(int start[9], int end[9]){int space_idx;int* tmp_step = NULL;struct Bheap *o_heap = NULL, *c_heap = NULL;struct Bheap_node *inode = NULL, *onode = NULL;struct step_node *fnode = NULL;struct step_node *omnode = NULL;struct Bheap_node *exist_node = NULL;size_t idx;o_heap = Bheap_create(128, BHEAP_TYPE_SMALL);c_heap = Bheap_create(128, BHEAP_TYPE_SMALL);/* 第一步判断可否由start状态到end状态 *//* 将起始点入open heap */if (NULL == (fnode = MALLOC(struct step_node, 1))){fprintf(stderr, "malloc fnode error!\n");return;}if (NULL == (inode = MALLOC(struct Bheap_node, 1))){fprintf(stderr, "malloc inode error!\n");return;}if (NULL == (tmp_step = MALLOC(int, 9))){fprintf(stderr, "malloc tmp_step error!\n");return;}memset(fnode, 0x00, sizeof(struct step_node));memset(inode, 0x00, sizeof(struct Bheap_node));memset(tmp_step, 0x00, sizeof(int) * 9);memcpy(fnode->step_status, start, sizeof(int) * 9);fnode->g = 0;fnode->h = calc_distance(fnode->step_status, end);fnode->f = fnode->g + fnode->h;fnode->parent = NULL;inode->value = fnode;Bheap_push(o_heap, inode, _comp);for ( ; ; ){omnode = NULL;if (NULL == (onode = Bheap_pop(o_heap, _comp))){break;}else{omnode = (struct step_node*)onode->value;if (is_end(omnode->step_status, end))break;Bheap_push(c_heap, onode, _comp);memset(tmp_step, 0x00, sizeof(int) * 9);memcpy(tmp_step, omnode->step_status, sizeof(int) * 9);space_idx = arr_idx(0, tmp_step);/* 上 */if (is_reachable(space_idx, (UP))){fnode = NULL;inode = NULL;if (NULL == (fnode = MALLOC(struct step_node, 1))){fprintf(stderr, "malloc fnode error!\n");return;}if (NULL == (inode = MALLOC(struct Bheap_node, 1))){fprintf(stderr, "malloc inode error!\n");return;}move_space(tmp_step, (UP));memcpy(fnode->step_status, tmp_step, sizeof(int) * 9);fnode->g = omnode->g + 1;fnode->h = calc_distance(tmp_step, end);fnode->f = fnode->g + fnode->h;fnode->parent = omnode;inode->value = fnode;/* 不在open heap和closed heap 中 */if (-1 == is_Bheap_contain(o_heap, inode, _eq) && -1 == is_Bheap_contain(c_heap, inode, _eq)){Bheap_push(o_heap, inode, _comp);if (is_end(tmp_step, end))continue;}else if(-1 != (idx = is_Bheap_contain(o_heap, inode, _eq))){/* 在open heap 中*/if (NULL != (exist_node = Bheap_get(o_heap, idx))){if (fnode->f < ((struct step_node *)exist_node->value)->f){((struct step_node *)(exist_node->value))->f = fnode->f;((struct step_node*)(exist_node->value))->parent = fnode->parent;}}free(fnode);free(inode);}else{free(fnode);free(inode);}Bheap_push(c_heap, onode, _comp);}memset(tmp_step, 0x00, sizeof(int) * 9);memcpy(tmp_step, omnode->step_status, sizeof(int) * 9);space_idx = arr_idx(0, tmp_step);/* 下 */if (is_reachable(space_idx, (DOWN))){fnode = NULL;inode = NULL;if (NULL == (fnode = MALLOC(struct step_node, 1))){fprintf(stderr, "malloc fnode error!\n");return;}if (NULL == (inode = MALLOC(struct Bheap_node, 1))){fprintf(stderr, "malloc inode error!\n");return;}move_space(tmp_step, (DOWN));memcpy(fnode->step_status, tmp_step, sizeof(int) * 9);fnode->g = omnode->g + 1;fnode->h = calc_distance(tmp_step, end);fnode->f = fnode->g + fnode->h;fnode->parent = omnode;inode->value = fnode;/* 不在open heap和closed heap 中 */if (-1 == is_Bheap_contain(o_heap, inode, _eq) && -1 == is_Bheap_contain(c_heap, inode, _eq)){Bheap_push(o_heap, inode, _comp);if (is_end(tmp_step, end))continue;}else if(-1 != (idx = is_Bheap_contain(o_heap, inode, _eq))){/* 在open heap 中*/if (NULL != (exist_node = Bheap_get(o_heap, idx))){if (fnode->f < ((struct step_node *)exist_node->value)->f){((struct step_node *)(exist_node->value))->f = fnode->f;((struct step_node*)(exist_node->value))->parent = fnode->parent;}}free(fnode);free(inode);}else{free(fnode);free(inode);}Bheap_push(c_heap, onode, _comp);}memset(tmp_step, 0x00, sizeof(int) * 9);memcpy(tmp_step, omnode->step_status, sizeof(int) * 9);space_idx = arr_idx(0, tmp_step);/* 左 */if (is_reachable(space_idx, (LEFT))){fnode = NULL;inode = NULL;if (NULL == (fnode = MALLOC(struct step_node, 1))){fprintf(stderr, "malloc fnode error!\n");return;}if (NULL == (inode = MALLOC(struct Bheap_node, 1))){fprintf(stderr, "malloc inode error!\n");return;}move_space(tmp_step, (LEFT));memcpy(fnode->step_status, tmp_step, sizeof(int) * 9);fnode->g = omnode->g + 1;fnode->h = calc_distance(tmp_step, end);fnode->f = fnode->g + fnode->h;fnode->parent = omnode;inode->value = fnode;/* 不在open heap和closed heap 中 */if (-1 == is_Bheap_contain(o_heap, inode, _eq) && -1 == is_Bheap_contain(c_heap, inode, _eq)){Bheap_push(o_heap, inode, _comp);if (is_end(tmp_step, end))continue;}else if(-1 != (idx = is_Bheap_contain(o_heap, inode, _eq))){/* 在open heap 中*/if (NULL != (exist_node = Bheap_get(o_heap, idx))){if (fnode->f < ((struct step_node *)exist_node->value)->f){((struct step_node *)(exist_node->value))->f = fnode->f;((struct step_node*)(exist_node->value))->parent = fnode->parent;}}free(fnode);free(inode);}else{free(fnode);free(inode);}Bheap_push(c_heap, onode, _comp);}memset(tmp_step, 0x00, sizeof(int) * 9);memcpy(tmp_step, omnode->step_status, sizeof(int) * 9);space_idx = arr_idx(0, tmp_step);/* 右 */if (is_reachable(space_idx, (RIGHT))){fnode = NULL;inode = NULL;if (NULL == (fnode = MALLOC(struct step_node, 1))){fprintf(stderr, "malloc fnode error!\n");return;}if (NULL == (inode = MALLOC(struct Bheap_node, 1))){fprintf(stderr, "malloc inode error!\n");return;}move_space(tmp_step, (RIGHT));memcpy(fnode->step_status, tmp_step, sizeof(int) * 9);fnode->g = omnode->g + 1;fnode->h = calc_distance(tmp_step, end);fnode->f = fnode->g + fnode->h;fnode->parent = omnode;inode->value = fnode;/* 不在open heap和closed heap 中 */if (-1 == is_Bheap_contain(o_heap, inode, _eq) && -1 == is_Bheap_contain(c_heap, inode, _eq)){Bheap_push(o_heap, inode, _comp);if (is_end(tmp_step, end))continue;}else if(-1 != (idx = is_Bheap_contain(o_heap, inode, _eq))){/* 在open heap 中*/if (NULL != (exist_node = Bheap_get(o_heap, idx))){if (fnode->f < ((struct step_node *)exist_node->value)->f){((struct step_node *)(exist_node->value))->f = fnode->f;((struct step_node*)(exist_node->value))->parent = fnode->parent;}}free(fnode);free(inode);}else{free(fnode);free(inode);}Bheap_push(c_heap, onode, _comp);}}}if (NULL == omnode){printf("not found!\n");}else{while(NULL != omnode){print_step_status(omnode->step_status);printf("\n");omnode = omnode->parent;}}}static int arr_idx(int n, int step_status[9]){int cnt;for(cnt = 0; cnt < 9; cnt++)if (n == step_status[cnt])return cnt;return (-1);}static void init_node_distance(int node_distance[9][9]){int i, j, val;for (i = 0; i < 9; i++){for (j = 0; j < 9; j++){val = abs(i - j);node_distance[i][j] = (int)val/3 + val%3;}}}static int calc_distance(int step_status[9], int end[9]){int i, tmp, ret_val = 0;for (i = 0; i < 9; i++)if (-1 != (tmp = arr_idx(step_status[i], end)))ret_val += node_distance[i][tmp];return (ret_val);}static int is_end(int step_status[9], int end[9]){int i;for (i = 0; i < 9; i++)if (step_status[i] != end[i])return (0);return (1);}static int is_reachable(int space_idx, int flag){int x,y;x = space_idx/3;y = space_idx%3;if(((UP) == flag) && (x > 0))return (1);else if (((DOWN) == flag) && (x < 2))return (1);else if (((LEFT) == flag) && (y > 0))return (1);else if(((RIGHT) == flag) && (y < 2))return (1);elsereturn (0);}static int move_space(int step_status[9], int flag){int zero_idx, tmp;zero_idx = arr_idx(0, step_status);tmp = step_status[zero_idx];/* 交换空格的位置 */if (((UP) == flag) || ((DOWN) == flag) || ((LEFT) == flag) || ((RIGHT) == flag)){step_status[zero_idx] = step_status[zero_idx + flag];step_status[zero_idx + flag] = tmp;return (0);}return (-1);}static void print_step_status(int step_status[9]){int i;for(i = 0; i < 9; i++){printf("%d ", step_status[i]);if (0 == ((i+1)%3) && (i != 0))printf("\n");}}/* Bheap_compare_t 函数实现 */int _comp(struct Bheap_node* n1, struct Bheap_node* n2){struct step_node *sn1 = NULL, *sn2 = NULL;if ((NULL != n1) && (NULL != n2)){sn1 = (struct step_node*)n1->value;sn2 = (struct step_node*)n2->value;if (sn1->f > sn2->f)return (1);else if(sn1->f == sn2->f)return (0);elsereturn (-1);}elsereturn (0);}/* Bheap_equal_t 函数实现 */int _eq(struct Bheap_node* n1, struct Bheap_node* n2){struct step_node *sn1 = NULL, *sn2 = NULL;if ((NULL != n1) && (NULL != n2)){sn1 = (struct step_node*)(n1->value);sn2 = (struct step_node*)(n2->value);return calc_distance(sn1->step_status, sn2->step_status);}elsereturn (0);}


执行结果:



代码包下载:八数码问题实现(C语言)




        
原创粉丝点击