You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

250 lines
7.9 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# A8solution
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#define N 3 // <20><><EFBFBD><EFBFBD>ƴͼ<C6B4><CDBC>ά<EFBFBD>ȣ<EFBFBD><C8A3><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB>3x3<78><33>ƴͼ
typedef struct Node {
int puzzle[N][N]; // <20>洢ƴͼ״̬<D7B4><CCAC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
struct Node* parent; // ָ<>򸸽ڵ<F2B8B8BD><DAB5>ָ<EFBFBD><EFBFBD><EBA3AC><EFBFBD><EFBFBD>׷<EFBFBD><D7B7>·<EFBFBD><C2B7>
int f, g, h; // A*<2A><EFBFBD>е<EFBFBD> f, g, h ֵ
} Node;
// <20><><EFBFBD><EFBFBD><EFBFBD>µ<EFBFBD>ƴͼ<C6B4>ڵ<EFBFBD>
Node* createNode(int puzzle[N][N]) {
Node* newnode = (Node*)malloc(sizeof(Node));
//<2F><>ʵ<EFBFBD>ָú<D6B8><C3BA><EFBFBD>
for(int i=0;i<N;i++){
for(int j=0;j<N;j++){
newnode->puzzle[i][j]=puzzle[i][j];
}
}
newnode->parent=NULL;
newnode->f=0;
newnode->g=0;
newnode->h=0;
return newnode;
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƴͼ״̬<D7B4>Ƿ<EFBFBD><C7B7><EFBFBD>ͬ
bool isSamePuzzle(int a[N][N], int b[N][N]) {
//<2F><>ͬ<EFBFBD>򷵻<EFBFBD>true,<2C><><EFBFBD>򷵻<EFBFBD>false
int flag=0;
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;
}
// <EFBFBD><EFBFBD>ӡƴͼ״̬
void printPuzzle(int puzzle[N][N]) {
//˫<><CBAB>forѭ<EFBFBD><EFBFBD>ʵ<EFBFBD><EFBFBD>ƴͼ<EFBFBD>Ĵ<EFBFBD>ӡ
for(int i=0;i<N;i++){
for(int j=0;j<N;j++){
printf("%d ",puzzle[i][j]);
}
printf("\n");
}
printf("\n");
}
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>㵱ǰ״̬<EFBFBD><EFBFBD>Ŀ<EFBFBD><EFBFBD>״̬<EFBFBD>Ĺ<EFBFBD><EFBFBD>ƴ<EFBFBD><EFBFBD><EFBFBD>
int heuristic(Node* current, Node* goal) {
int h = 0;
// <EFBFBD><EFBFBD><EFBFBD>㲻ƥ<EFBFBD><EFBFBD><EFBFBD>ƴͼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
for(int i=0;i<3;i++){
for(int j=0;j<3;j++){
if((current->puzzle[i][j]!=goal->puzzle[i][j])&&i!=2&&j!=2) h++;
}
}
return h;
}
// <20>ƶ<EFBFBD><C6B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>µ<EFBFBD>ƴͼ״̬
Node* move(Node* current, int dir) {
int key_x, key_y;//<2F><>¼<EFBFBD>հ׿<D5B0><D7BF>λ<EFBFBD><CEBB>
// <20>ҵ<EFBFBD><D2B5>հ׿<D5B0><D7BF>λ<EFBFBD><CEBB>
for(int i=0;i<3;i++){
for(int j=0;j<3;j++){
if(current->puzzle[i][j]==0){
key_x=i;key_y=j;
}
}
}
int new_x,new_y;
new_x=key_x;
new_y=key_y;
//<2F><>new_x<5F><78>new_y<5F><79>ֵ
if(dir==0)new_y--;
if(dir==1)new_y++;
if(dir==2)new_x--;
if(dir==3)new_x++;
// <20><><EFBFBD><EFBFBD><EFBFBD>ƶ<EFBFBD><C6B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¿<EFBFBD><C2BF>λ<EFBFBD>ã<EFBFBD><C3A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƶ<EFBFBD>
if(new_x<0||new_x>N-1||new_y>N-1||new_y<0) return NULL;
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><EFBFBD>ڱ߽<EFBFBD><EFBFBD><EFBFBD>
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>½ڵ㣬<EFBFBD><EFBFBD><EFBFBD>Ƶ<EFBFBD>ǰƴͼ״̬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><EFBFBD>
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;
}
// A*<2A><EFBFBD><E3B7A8>Ѱ<EFBFBD><D1B0><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><C2B7>
Node* AStar(Node* start, Node* goal) {
Node* OPEN[1000]; // <20><><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ洢<DAB4><E6B4A2>̽<EFBFBD><CCBD><EFBFBD>Ľڵ<C4BD>
Node* CLOSED[1000]; // <20>ر<EFBFBD><D8B1>б<EFBFBD><D0B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ洢<DAB4><E6B4A2>̽<EFBFBD><CCBD><EFBFBD>Ľڵ<C4BD>
int OPEN_SIZE = 0; // <20><><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1>Ĵ<EFBFBD>С
int CLOSED_SIZE = 0; // <20>ر<EFBFBD><D8B1>б<EFBFBD><D0B1>Ĵ<EFBFBD>С
OPEN[0] = start; // <20><><EFBFBD><EFBFBD>ʼ<EFBFBD>ڵ<EFBFBD><DAB5><EFBFBD><EFBFBD>ӵ<EFBFBD><D3B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD>
OPEN_SIZE = 1; // <20><><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1>Ĵ<EFBFBD>С<EFBFBD><D0A1><EFBFBD><EFBFBD>Ϊ1
CLOSED_SIZE = 0; // <20>ر<EFBFBD><D8B1>б<EFBFBD><D0B1>Ĵ<EFBFBD>С<EFBFBD><D0A1><EFBFBD><EFBFBD>Ϊ0
while (OPEN_SIZE > 0) {//<2F><>open<65>б<EFBFBD><D0B1><EFBFBD><EFBFBD>в<EFBFBD><D0B2><EFBFBD>
int min_f = OPEN[0]->f;//<2F><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD>С<EFBFBD><D0A1>f
int min_index = 0;
// <20><><EFBFBD>ҿ<EFBFBD><D2BF><EFBFBD><EFBFBD>б<EFBFBD><D0B1>о<EFBFBD><D0BE><EFBFBD><EFBFBD><EFBFBD>С<66>Ľڵ<C4BD>
for(int i=0;i<OPEN_SIZE;i++){
if(min_f>OPEN[i]->f){
min_f=OPEN[i]->f;
min_index=i;
}
}
Node* current = OPEN[min_index]; // <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С<66>Ľڵ<C4BD>
// <20><><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD>ڵ<EFBFBD><DAB5><EFBFBD>Ŀ<EFBFBD><C4BF>״̬ƥ<CCAC><EFBFBD><E4A3AC>ʾ<EFBFBD>ҵ<EFBFBD><D2B5><EFBFBD>
if(isSamePuzzle(current->puzzle,goal->puzzle)==true) return current;
//<2F><><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1>Ĵ<EFBFBD>С<EFBFBD><D0A1>1<EFBFBD><31><EFBFBD><EFBFBD>ʾ<EFBFBD>ӿ<EFBFBD><D3BF><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD><EFBFBD>Ƴ<EFBFBD><C6B3><EFBFBD>һ<EFBFBD><D2BB><EFBFBD>ڵ<EFBFBD>
OPEN_SIZE--;
//<2F><><EFBFBD><EFBFBD>С f ֵ<>Ľڵ<C4BD><DAB5>Ƶ<EFBFBD><C6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD>ĩβ<C4A9><CEB2><EFBFBD>Ա<EFBFBD><D4B1>Ժ<EFBFBD><D4BA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӵ<EFBFBD><D3B5>ر<EFBFBD><D8B1>б<EFBFBD><D0B1>С<EFBFBD>
//<2F><><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD>Ż<EFBFBD><C5BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1>Ľṹ<C4BD><E1B9B9>
Node* temp = OPEN[min_index];
OPEN[min_index] = OPEN[OPEN_SIZE];
OPEN[OPEN_SIZE] = temp;
//<2F><><EFBFBD><EFBFBD>ǰ<EFBFBD>ڵ<EFBFBD><DAB5><EFBFBD><EFBFBD>ӵ<EFBFBD><D3B5>ر<EFBFBD><D8B1>б<EFBFBD><D0B1><EFBFBD><EFBFBD>ر<EFBFBD><D8B1>б<EFBFBD><D0B1><EFBFBD>С<EFBFBD><D0A1>1
CLOSED[CLOSED_SIZE]=OPEN[OPEN_SIZE];
CLOSED_SIZE++;
int key = 0;
// <20><><EFBFBD>ҵ<EFBFBD>ǰ<EFBFBD>ڵ<EFBFBD><DAB5>пհ׿<D5B0><D7BF>λ<EFBFBD><CEBB>
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;
}
}
}
// <20><><EFBFBD><EFBFBD><EFBFBD>ĸ<EFBFBD><C4B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƶ<EFBFBD><C6B6><EFBFBD><EFBFBD><EFBFBD>
for (int dir = 0; dir < 4; dir++) {
Node* new_node = move(current, dir);
if (new_node != NULL && !isSamePuzzle(new_node->puzzle, current->puzzle)) {
//<2F>õ<EFBFBD><C3B5><EFBFBD>Ӧ<EFBFBD><D3A6>g<EFBFBD><67>f<EFBFBD><66>
int gNew = current->g + 1;
int hNew = heuristic(new_node, goal);
int fNew = gNew + hNew;
bool in_OPEN = false;
int open_index = -1;
// <20><><EFBFBD><EFBFBD>½ڵ<C2BD><DAB5>Ƿ<EFBFBD><C7B7>ڿ<EFBFBD><DABF><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD>
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;
// <20><><EFBFBD><EFBFBD>½ڵ<C2BD><DAB5>Ƿ<EFBFBD><C7B7>ڹر<DAB9><D8B1>б<EFBFBD><D0B1><EFBFBD>
for (int i = 0; i < CLOSED_SIZE; i++) {
if (isSamePuzzle(new_node->puzzle, CLOSED[i]->puzzle)) {
in_CLOSED = true;
break;
}
}
//<2F><><EFBFBD>ýڵ<C3BD><DAB5><EFBFBD><EFBFBD><EFBFBD>ڿ<EFBFBD><DABF><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD>Ҳ<EFBFBD><D2B2><EFBFBD>ڹر<DAB9><D8B1>б<EFBFBD><D0B1><EFBFBD>
if (!in_OPEN && !in_CLOSED) {
//<2F><>gNew<65><77>hNew<65><77>fNew<65><77><EFBFBD><EFBFBD>new_nod<6F><64>Ӧ<EFBFBD><D3A6>g<EFBFBD><67>h<EFBFBD><68><66><D6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڵ<EFBFBD><DAB5><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA>ǰ<EFBFBD>ڵ㡣
new_node->g=gNew;
new_node->h=hNew;
new_node->f=fNew;
new_node->parent=current;
// <20><><EFBFBD><EFBFBD><EFBFBD>½ڵ<C2BD>new_node<64><65><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD>С<EFBFBD><D0A1>1
OPEN[OPEN_SIZE]=new_node;
OPEN_SIZE++;
}
//<2F><><EFBFBD><EFBFBD>½ڵ<C2BD><DAB5>Ѿ<EFBFBD><D1BE>ڿ<EFBFBD><DABF><EFBFBD><EFBFBD>б<EFBFBD><D0B1>У<EFBFBD><D0A3><EFBFBD><EFBFBD>µ<EFBFBD> f ֵ<><D6B5>С<EFBFBD><D0A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¿<EFBFBD><C2BF><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD><EFBFBD>Ѵ<EFBFBD><D1B4>ڽڵ<DABD><DAB5><EFBFBD><EFBFBD>Ϣ<EFBFBD><CFA2>
else if (in_OPEN && fNew < OPEN[open_index]->f) {
OPEN[open_index]->f=fNew;
OPEN[open_index]->h=hNew;
OPEN[open_index]->g=gNew;
OPEN[open_index]->parent=current;
}
}
}
}
return NULL; // <20>޽<EFBFBD>
}
// <20><>ӡ<EFBFBD><D3A1>·<EFBFBD><C2B7>
void printPath(Node* final) {
if (final == NULL) {
return;
}
printPath(final->parent); // <20>ݹ<EFBFBD><DDB9>ӡ·<D3A1><C2B7>
for (int i = 0; i < N; i++) {
if (i%3==0){
printf("-------\n");
}
for (int j = 0; j < N; j++) {
printf("%d ", final->puzzle[i][j]);
}
printf("\n");
}
}
int main() {
int start[N][N] = {{2, 0, 3}, {1, 8, 4}, {7, 6, 5}};
int target[N][N] = {{1, 2, 3}, {8, 0, 4}, {7, 6, 5}};
//int start[N][N] = {{2, 8, 3}, {1, 6, 4}, {7, 0, 5}};
//int target[N][N] = {{1, 2, 3}, {8, 0, 4}, {7, 6, 5}};
//int start[N][N] = {{2, 8, 3}, {1, 0, 4}, {7, 6, 5}};
//int target[N][N] = {{1, 2, 3}, {8, 0, 4}, {7, 6, 5}};
Node* init = createNode(start);
Node* goal = createNode(target);
Node* final = AStar(init, goal);
if (final) {
printf("This problem has a solution:\n");
printPath(final); // <20><>ӡ<EFBFBD><D3A1>·<EFBFBD><C2B7>
} else {
printf("This problem has no solution<6F><6E>\n");
}
return 0;
}