|
|
@ -18,13 +18,13 @@ Node* createNode(int puzzle[N][N]) {
|
|
|
|
|
|
|
|
|
|
|
|
for(int i = 0; i < N; i++){
|
|
|
|
for(int i = 0; i < N; i++){
|
|
|
|
for(int j = 0; j < N; j++){
|
|
|
|
for(int j = 0; j < N; j++){
|
|
|
|
newnode.puzzle[i][j] = puzzle[i][j];
|
|
|
|
newnode->puzzle[i][j] = puzzle[i][j];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
newnode.parent = NULL;
|
|
|
|
newnode->parent = NULL;
|
|
|
|
newnode.f = 0;
|
|
|
|
newnode->f = 0;
|
|
|
|
newnode.g = 0;
|
|
|
|
newnode->g = 0;
|
|
|
|
newnode.h = 0;
|
|
|
|
newnode->h = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 检查两个拼图状态是否相同
|
|
|
|
// 检查两个拼图状态是否相同
|
|
|
@ -45,7 +45,7 @@ void printPuzzle(int puzzle[N][N]) {
|
|
|
|
for(int j = 0; j < N; j++){
|
|
|
|
for(int j = 0; j < N; j++){
|
|
|
|
printf("%d ",puzzle[i][j]);
|
|
|
|
printf("%d ",puzzle[i][j]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
printf("\n")
|
|
|
|
printf("\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -57,7 +57,7 @@ int heuristic(Node* current, Node* goal) {
|
|
|
|
|
|
|
|
|
|
|
|
for(int i = 0; i < N; i++){
|
|
|
|
for(int i = 0; i < N; i++){
|
|
|
|
for(int j = 0; j < N; j++){
|
|
|
|
for(int j = 0; j < N; j++){
|
|
|
|
if(current.puzzle[i][j] != goal.puzzle[i][j]) h++;
|
|
|
|
if(current->puzzle[i][j] != goal->puzzle[i][j]) h++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return h;
|
|
|
|
return h;
|
|
|
@ -67,13 +67,30 @@ int heuristic(Node* current, Node* goal) {
|
|
|
|
Node* move(Node* current, int dir) {
|
|
|
|
Node* move(Node* current, int dir) {
|
|
|
|
int key_x, key_y;//记录空白块的位置
|
|
|
|
int key_x, key_y;//记录空白块的位置
|
|
|
|
// 找到空白块的位置
|
|
|
|
// 找到空白块的位置
|
|
|
|
|
|
|
|
for(int i = 0; i < N; i++){
|
|
|
|
|
|
|
|
for(int j = 0; j < N; j++){
|
|
|
|
|
|
|
|
if(current->puzzle[i][j] == 0){
|
|
|
|
|
|
|
|
key_x = i;
|
|
|
|
|
|
|
|
key_y = j;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//给new_x、new_y赋值
|
|
|
|
//给new_x、new_y赋值
|
|
|
|
|
|
|
|
int new_x = key_x;
|
|
|
|
|
|
|
|
int new_y = key_y;
|
|
|
|
|
|
|
|
|
|
|
|
// 根据移动方向更新新块的位置,上下左右移动
|
|
|
|
// 根据移动方向更新新块的位置,上下左右移动
|
|
|
|
|
|
|
|
if(dir == 0) new_y--;
|
|
|
|
|
|
|
|
else if(dir == 1) new_y++;
|
|
|
|
|
|
|
|
else if(dir == 2) new_x--;
|
|
|
|
|
|
|
|
else if(dir == 3) new_x++;
|
|
|
|
|
|
|
|
|
|
|
|
// 检查新位置是否在边界内
|
|
|
|
// 检查新位置是否在边界内
|
|
|
|
|
|
|
|
if(new_x < 0 || new_x >= N || new_y < 0 || new_y >= N){
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 创建新节点,复制当前拼图状态,并交换块的位置
|
|
|
|
// 创建新节点,复制当前拼图状态,并交换块的位置
|
|
|
|
Node* new_node = createNode(current->puzzle);
|
|
|
|
Node* new_node = createNode(current->puzzle);
|
|
|
@ -97,15 +114,22 @@ Node* AStar(Node* start, Node* goal) {
|
|
|
|
int min_f = OPEN[0]->f;//初始化最小的f
|
|
|
|
int min_f = OPEN[0]->f;//初始化最小的f
|
|
|
|
int min_index = 0;
|
|
|
|
int min_index = 0;
|
|
|
|
// 查找开放列表中具有最小f值的节点
|
|
|
|
// 查找开放列表中具有最小f值的节点
|
|
|
|
|
|
|
|
for(int i = 0; i < OPEN_SIZE; i++){
|
|
|
|
|
|
|
|
if(OPEN[i]->f < min_f){
|
|
|
|
|
|
|
|
min_f = OPEN[i]->f;
|
|
|
|
|
|
|
|
min_index = i;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Node* current = OPEN[min_index]; // 获取具有最小f值的节点
|
|
|
|
Node* current = OPEN[min_index]; // 获取具有最小f值的节点
|
|
|
|
|
|
|
|
|
|
|
|
// 如果当前节点与目标状态匹配,表示找到解
|
|
|
|
// 如果当前节点与目标状态匹配,表示找到解
|
|
|
|
|
|
|
|
if(isSamePuzzle(current->puzzle,goal->puzzle)){
|
|
|
|
|
|
|
|
return current;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//开放列表的大小减1,表示从开放列表中移除了一个节点
|
|
|
|
//开放列表的大小减1,表示从开放列表中移除了一个节点
|
|
|
|
|
|
|
|
OPEN_SIZE--;
|
|
|
|
|
|
|
|
|
|
|
|
//将最小 f 值的节点移到开放列表的末尾,以便稍后将其添加到关闭列表中。
|
|
|
|
//将最小 f 值的节点移到开放列表的末尾,以便稍后将其添加到关闭列表中。
|
|
|
|
//这是为了优化开放列表的结构。
|
|
|
|
//这是为了优化开放列表的结构。
|
|
|
@ -114,7 +138,7 @@ Node* AStar(Node* start, Node* goal) {
|
|
|
|
OPEN[OPEN_SIZE] = temp;
|
|
|
|
OPEN[OPEN_SIZE] = temp;
|
|
|
|
|
|
|
|
|
|
|
|
//将当前节点添加到关闭列表,关闭列表大小加1
|
|
|
|
//将当前节点添加到关闭列表,关闭列表大小加1
|
|
|
|
|
|
|
|
CLOSED[CLOSED_SIZE++] = current;
|
|
|
|
|
|
|
|
|
|
|
|
int key = 0;
|
|
|
|
int key = 0;
|
|
|
|
// 查找当前节点中空白块的位置
|
|
|
|
// 查找当前节点中空白块的位置
|
|
|
@ -151,17 +175,31 @@ Node* AStar(Node* start, Node* goal) {
|
|
|
|
bool in_CLOSED = false;
|
|
|
|
bool in_CLOSED = false;
|
|
|
|
|
|
|
|
|
|
|
|
// 检查新节点是否在关闭列表中
|
|
|
|
// 检查新节点是否在关闭列表中
|
|
|
|
|
|
|
|
for(int i = 0; i < CLOSED_SIZE; i++){
|
|
|
|
|
|
|
|
if(isSamePuzzle(new_node->puzzle, CLOSED[i]->puzzle)){
|
|
|
|
|
|
|
|
in_CLOSED = true;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//若该节点机不在开放列表中也不在关闭列表中
|
|
|
|
//若该节点机不在开放列表中也不在关闭列表中
|
|
|
|
if (!in_OPEN && !in_CLOSED) {
|
|
|
|
if (!in_OPEN && !in_CLOSED) {
|
|
|
|
//把gNew、hNew、fNew赋给new_nod对应的g、h、f值,并将其父节点设置为当前节点。
|
|
|
|
//把gNew、hNew、fNew赋给new_nod对应的g、h、f值,并将其父节点设置为当前节点。
|
|
|
|
|
|
|
|
new_node->g = gNew;
|
|
|
|
|
|
|
|
new_node->h = hNew;
|
|
|
|
|
|
|
|
new_node->f = fNew;
|
|
|
|
|
|
|
|
new_node->parent = current;
|
|
|
|
|
|
|
|
|
|
|
|
// 添加新节点new_node到开放列表,开放列表大小加1
|
|
|
|
// 添加新节点new_node到开放列表,开放列表大小加1
|
|
|
|
|
|
|
|
OPEN[OPEN_SIZE++] = new_node;
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//如果新节点已经在开放列表中,但新的 f 值更小,将更新开放列表中已存在节点的信息。
|
|
|
|
//如果新节点已经在开放列表中,但新的 f 值更小,将更新开放列表中已存在节点的信息。
|
|
|
|
else if (in_OPEN && fNew < OPEN[open_index]->f) {
|
|
|
|
else if (in_OPEN && fNew < OPEN[open_index]->f) {
|
|
|
|
|
|
|
|
OPEN[open_index]->g = gNew;
|
|
|
|
|
|
|
|
OPEN[open_index]->h = hNew;
|
|
|
|
|
|
|
|
OPEN[open_index]->f = fNew;
|
|
|
|
|
|
|
|
OPEN[open_index]->parent = current;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|