我有一个代码,应该在显示初始状态和目标状态后显示解决 15 个难题的路径。然而,虽然它确实显示了初始状态和目标状态,但它给出了分段错误而不是打印出路径。
下面是代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 4
#define NxN (N*N)
#define TRUE 1
#define FALSE 0
struct node {
int tiles[N][N];
int f, g, h;
short zero_row, zero_column;
struct node *next;
struct node *parent;
};
int goal_rows[NxN];
int goal_columns[NxN];
struct node *start,*goal;
struct node *open = NULL, *closed = NULL;
struct node *succ_nodes[4];
void print_a_node(struct node *pnode) {
int i,j;
for (i=0;i<N;i++) {
for (j=0;j<N;j++)
printf("%2d ", pnode->tiles[i][j]);
printf("\n");
}
printf("\n");
}
struct node *initialize(char **argv){
int i,j,k,index, tile;
struct node *pnode;
pnode=(struct node *) malloc(sizeof(struct node));
index = 1;
for (j=0;j<N;j++)
for (k=0;k<N;k++) {
tile=atoi(argv[index++]);
pnode->tiles[j][k]=tile;
if(tile==0) {
pnode->zero_row=j;
pnode->zero_column=k;
}
}
pnode->f=0;
pnode->g=0;
pnode->h=0;
pnode->next=NULL;
pnode->parent=NULL;
start=pnode;
printf("initial state\n");
print_a_node(start);
pnode=(struct node *) malloc(sizeof(struct node));
goal_rows[0]=3;
goal_columns[0]=3;
for(index=1; index<NxN; index++){
j=(index-1)/N;
k=(index-1)%N;
goal_rows[index]=j;
goal_columns[index]=k;
pnode->tiles[j][k]=index;
}
pnode->tiles[N-1][N-1]=0;
pnode->f=0;
pnode->g=0;
pnode->h=0;
pnode->next=NULL;
goal=pnode;
printf("goal state\n");
print_a_node(goal);
return start;
}
void merge_to_open() {
for (int i = 0; i < N; i++) {
if (succ_nodes[i] == NULL) {
continue;
}
struct node *insert_node = (struct node *) malloc(sizeof(struct node));
memcpy(insert_node->tiles, succ_nodes[i]->tiles, NxN*sizeof(int));
insert_node->f = succ_nodes[i]->f;
insert_node->g = succ_nodes[i]->g;
insert_node->h = succ_nodes[i]->h;
insert_node->zero_row = succ_nodes[i]->zero_row;
insert_node->zero_column = succ_nodes[i]->zero_column;
insert_node->parent = succ_nodes[i]->parent;
if (open == NULL) {
open = insert_node;
continue;
}
struct node *temp = open;
int status = FALSE;
while (temp != NULL && temp->next != NULL) {
if (insert_node->f < temp->next->f) {
insert_node->next = temp->next;
temp->next = insert_node;
status = TRUE;
break;
}
temp = temp->next;
}
if (status == FALSE) {
temp->next = insert_node;
}
}
}
void swap(int row1,int column1,int row2,int column2, struct node * pnode){
int tile = pnode->tiles[row1][column1];
pnode->tiles[row1][column1]=pnode->tiles[row2][column2];
pnode->tiles[row2][column2]=tile;
}
int manhattan(int entry, int row, int column) {
for (int i = 0; i < NxN; i++) {
for (int j = 0; j < NxN; j++) {
if(goal->tiles[i][j] == entry) {
return abs(row - i) + abs(column - j);
}
}
}
}
void update_fgh(int t) {
struct node *pnode = succ_nodes[t];
if (pnode -> parent != NULL) {
pnode->g = pnode->parent->g + 1;
} else {
pnode->g = 1;
}
int misplaced = 0, distance = 0, correct = 0;
for (int i = 0; i < NxN; i++) {
for (int j = 0; j < NxN; j++) {
correct++;
if (pnode->tiles[j][i] != correct) {
misplaced++;
}
if (pnode->tiles[j][i] == 0) {
distance = 0;
} else {
distance = manhattan(pnode->tiles[j][i], j, i);
}
}
}
if (misplaced > distance) {
pnode->h = misplaced;
} else {
pnode->h = distance;
}
pnode->f = pnode->g + pnode->h;
}
void move_down(struct node * pnode){
if (pnode->zero_row + 1 < N) {
swap(pnode->zero_row, pnode->zero_column, pnode->zero_row + 1, pnode->zero_column, pnode);
pnode->zero_row++;
} else {
pnode = NULL;
}
}
void move_right(struct node * pnode){
if (pnode->zero_column + 1 < N) {
swap(pnode->zero_row, pnode->zero_column, pnode->zero_row, pnode->zero_column + 1, pnode);
pnode->zero_column++;
} else {
pnode = NULL;
}
}
void move_up(struct node * pnode){
if (pnode->zero_row - 1 > -1) {
swap(pnode->zero_row, pnode->zero_column, pnode->zero_row - 1, pnode->zero_column, pnode);
pnode->zero_row--;
} else {
pnode = NULL;
}
}
void move_left(struct node * pnode){
if (pnode->zero_column - 1 > -1) {
swap(pnode->zero_row, pnode->zero_column, pnode->zero_row, pnode->zero_column - 1, pnode);
pnode->zero_column--;
} else {
pnode = NULL;
}
}
void expand(struct node *selected) {
for (int i = 0; i < N; i++) {
succ_nodes[i] = NULL;
}
move_down(succ_nodes[0]);
move_right(succ_nodes[1]);
move_up(succ_nodes[2]);
move_left(succ_nodes[3]);
for (int i = 0; i < N; i++) {
update_fgh(i);
}
}
int nodes_same(struct node *a,struct node *b) {
int flg=FALSE;
if (memcmp(a->tiles, b->tiles, sizeof(int)*NxN) == 0)
flg=TRUE;
return flg;
}
void filter(int i, struct node *pnode_list){
struct node *pnode = succ_nodes[i];
struct node *temp = pnode_list;
while (temp != NULL) {
if (nodes_same(pnode, temp)) {
pnode = NULL;
return;
}
temp = temp->next;
}
}
int main(int argc,char **argv) {
int iter,cnt;
struct node *copen, *cp, *solution_path;
int ret, i, pathlen=0, index[N-1];
solution_path=NULL;
start=initialize(argv);
open=start;
iter=0;
while (open!=NULL) {
copen=open;
open=open->next;
if(nodes_same(copen,goal)){
do{
copen->next=solution_path;
solution_path=copen;
copen=copen->parent;
pathlen++;
} while(copen!=NULL);
printf("Path (length=%d):\n", pathlen);
copen=solution_path;
break;
}
expand(copen);
for(i=0;i<4;i++){
filter(i,open);
filter(i,closed);
}
merge_to_open();
copen->next=closed;
closed=copen;
iter++;
if(iter %1000 == 0)
printf("iter %d\n", iter);
}
return 0;
}
我使用这些命令行参数来运行程序:
2 3 0 4 1 6 7 8 5 9 10 12 13 14 11 15
当我运行程序的 gdb 调试时,它会打印出以下内容(我在程序中作为 pnode 传递的值是 succ_nodes[0]):
Program received signal SIGSEGV, Segmentation fault.
0x0000555555555940 in move_down (pnode=0x0) at problem1.c:172
172 if (pnode->zero_row + 1 < N) {
我假设所有带有 pnode 语句的移动函数都会发生这种情况。你能帮我想办法解决这个问题吗?
我看到
move_down()
是从一个地方 expand()
调用的,并传入了 succ_nodes[0]
。您在对 move_down()
的调用上方看到了什么?
我看到
expand()
有一个函数未使用的输入参数。 expand()
到底应该做什么?
我认为你需要退后一步并理解这个程序应该做什么。在你理解它之前你无法“修复”它。编写程序大纲,并用散文解释要采取的步骤,然后使代码与解释相匹配。
最后,拥有更明显的名称会有所帮助。什么是“曼哈顿”?什么是“fgh”(如“update_fgh”)?