#include #include #include #include #define N 3 // 拼图的维度为3 typedef struct Node { int puzzle[N][N]; struct Node* parent; int f, g, h; } Node; Node* createNode(int puzzle[N][N]) // 创建新的节点 { Node* newnode = (Node*)malloc(sizeof(Node)); memcpy(newnode->puzzle, puzzle, sizeof(int) * N * N); newnode->parent = NULL; newnode->f = newnode->g = newnode->h = 0; return newnode; } bool isSamePuzzle(int a[N][N], int b[N][N]) // 检查两个拼图状态是否相同 { for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { if (a[i][j] != b[i][j]) return false; } } return true; } void printPuzzle(int puzzle[N][N]) // 输出拼图状态 { for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { printf("%-2d", puzzle[i][j]); } printf("\n"); } printf("\n"); } int heuristic(Node* current, Node* goal) // 估计当前状态到目标状态的代价 { int h = 0; for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { if (current->puzzle[i][j] != goal->puzzle[i][j]) h++; } } return h; } Node* move(Node* current, int dir) // 生成新的拼图状态 { 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; } } } int new_x = key_x, new_y = key_y; switch (dir) // 根据移动方向移动新块的位置 { case 0: new_x--; break; case 1: new_x++; break; case 2: new_y--; break; case 3: new_y++; break; default: break; } if (new_x < 0 || new_x >= N || new_y < 0 || new_y >= N) return NULL; Node* new_node = createNode(current->puzzle); // 创建新节点,复制当前拼图状态,并交换块的位置 new_node->puzzle[key_x][key_y] = current->puzzle[new_x][new_y]; new_node->puzzle[new_x][new_y] = 0; return new_node; } Node* AStar(Node* start, Node* goal) // A*算法 { Node* OPEN[1000]; Node* CLOSED[1000]; int OPEN_SIZE = 0; int CLOSED_SIZE = 0; OPEN[0] = start; OPEN_SIZE = 1; CLOSED_SIZE = 0; while (OPEN_SIZE > 0) { int min_f = OPEN[0]->f; int min_index = 0; for (int i = 1; i < OPEN_SIZE; i++) // 查找开放列表中具有最小f值的节点 { if (OPEN[i]->f < min_f) { min_f = OPEN[i]->f; min_index = i; } } Node* current = OPEN[min_index]; if (isSamePuzzle(current->puzzle, goal->puzzle)) { return current; } OPEN_SIZE--; Node* temp = OPEN[min_index]; OPEN[min_index] = OPEN[OPEN_SIZE]; OPEN[OPEN_SIZE] = temp; CLOSED[CLOSED_SIZE++] = current; int key = 0; for (int i = 0; i < N; i++) // 查找当前节点中空白块的位置 { for (int j = 0; j < N; j++) { if (current->puzzle[i][j] == 0) { key = i * N + j; break; } } } for (int dir = 0; dir < 4; dir++) // 尝试四个方向的移动操作 { Node* new_node = move(current, dir); if (new_node != NULL && !isSamePuzzle(new_node->puzzle, current->puzzle)) { int gNew = current->g + 1; int hNew = heuristic(new_node, goal); int fNew = gNew + hNew; bool in_OPEN = false; int open_index = -1; for (int i = 0; i < OPEN_SIZE; i++) // 检查新节点是否在开放列表中 { if (isSamePuzzle(new_node->puzzle, OPEN[i]->puzzle)) { in_OPEN = true; open_index = i; break; } } 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) // 如果新节点均不满足,则将其添加到开放列表 { new_node->g = gNew; new_node->h = hNew; new_node->f = fNew; new_node->parent = current; OPEN[OPEN_SIZE++] = new_node; } else if (in_OPEN && fNew < OPEN[open_index]->f) // 如果新节点在开放列表中,但新的f值更小,更新节点信息 { OPEN[open_index]->g = gNew; OPEN[open_index]->h = hNew; OPEN[open_index]->f = fNew; OPEN[open_index]->parent = current; } } } } return NULL; } void printPath(Node* final) // 输出解路径 { if (final == NULL) { return; } printPath(final->parent); for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { printf("%-2d", final->puzzle[i][j]); } printf("\n"); }printf("------"); printf("\n"); } int main() { int start_puzzle[N][N] = { {2, 8, 3}, {1, 6, 4}, {7, 0, 5} }; int goal_puzzle[N][N] = { {1, 2, 3}, {8, 0, 4}, {7, 6, 5} }; Node* start = createNode(start_puzzle); Node* goal = createNode(goal_puzzle); Node* final = AStar(start, goal); if (final != NULL) { printf("Solution path:\n"); printPath(final); } else { printf("No solution found.\n"); } return 0; }