游戏设计迷进——欢迎调试高手一起调试A*算法程序——100分
在游戏设计中,人物行走设计是不可缺少的一环,如何使主角由一点走到另外一点,而且路程最短,而且要绕过中间的障碍物和游戏中的其他人物,例如:在一般的RPG游戏中,用鼠标在屏幕上轻轻一点,主角就可以从当前位置按照最佳路径走到目的地,使不少游戏都不可不考虑。一般用A*算法来设计,我近期写课程论文,以此为切入口,算法都已经完成,但是具体程序调试老是出错,我用VC6编程,源码如下:
//#define NDEBUG
#include <stdio.h>
#include <conio.h>
#include <assert.h>
#include <stdlib.h>
//#include <mem.h>
#define tile_num(x,y) (y*map_w+x) //将 x,y 坐标转换为地图上块的编号
#define tile_x(n) (n%map_w) //由块编号得出 x,y 坐标
#define tile_y(n) (n/map_w)
#define MAPMAXSIZE 180 //地图面积最大为 180x180,如果没有64K内存限制可以更大
#define MAXINT 32767
//树结构, 比较特殊, 是从叶节点向根节点反向链接,方便从叶节点找到根节点
typedef struct tree_node *TREE;
struct tree_node {
int h; //节点所在的高度,表示从起始点到该节点所有的步数
int tile; //该节点的位置
TREE father; //该节点的上一步
};
//链接结构,用于保存处理过的和没有处理过的结点
typedef struct link_node *LINK;
struct link_node {
TREE node;
int f;
LINK next;
};
LINK sort_queue; // 保存没有处理的行走方法的节点
LINK store_queue; // 保存已经处理过的节点 (搜索完后释放)
char * map; //地图数据
//unsigned int * dis_map; //保存搜索路径时,中间目标地最优解
int * dis_map; //保存搜索路径时,中间目标地最优解
int map_w,map_h; //地图宽和高
int start_x,start_y,end_x,end_y; //地点,终点坐标
// 初始化队列
void init_queue()
{
sort_queue=(LINK)malloc(sizeof(*sort_queue));
sort_queue->node=NULL;
sort_queue->f=-1;
sort_queue->next=(LINK)malloc(sizeof(*sort_queue));
sort_queue->next->node=NULL;
sort_queue->next->f=MAXINT;
sort_queue->next->next=NULL;
store_queue=(LINK)malloc(sizeof(*store_queue));
store_queue->node=NULL;
store_queue->f=-1;
store_queue->next=NULL;
}
// 待处理节点入队列, 依靠对目的地估价距离插入排序
void enter_queue(TREE node,int f)
{
LINK p=sort_queue,father,q;
while(f>p->f) { //sort队列按照从小到大排序,寻找f的最佳插入位置
father=p;
p=p->next;
assert(p);
}
q=(LINK)malloc(sizeof(*q)); //找到后生成sort队列节点
assert(sort_queue);
q->f=f,q->node=node,q->next=p; //进队列并修改指针
father->next=q;
}
// 将离目的地估计最近的方案出队列
TREE get_from_queue()
{
LINK bestchoice=sort_queue->next;//因为sort数组已经排序,所以第一个节点就是最佳节点
LINK next=sort_queue->next->next;
sort_queue->next=next; //删除第一个节点
bestchoice->next=store_queue->next; //把最佳节点插入store数组。
store_queue->next=bestchoice;
return bestchoice->node; //返回最佳节点
}
// 释放栈顶节点
void pop_stack() //释放store数组的第一个节点
{
LINK s=store_queue->next;
assert(s);
store_queue->next=store_queue->next->next;
free(s->node); //删除树上的节点
free(s); //删除链表节点
}
// 释放申请过的所有节点
void freetree()
{
//int i;
LINK p;
while(store_queue){ //删除store数组
p=store_queue;
free(p->node);//删除树上的节点
store_queue=store_queue->next;//修改store数组
free(p);//删除链表节点
}
while (sort_queue) { //删除sort数组
p=sort_queue;
free(p->node);//删除树上的节点
sort_queue=sort_queue->next;//修改store数组
free(p);//删除链表节点
}
}