|
|
|
|
#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>룬<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><EFBFBD>ƴͼ״̬<D7B4>Ƿ<EFBFBD><C7B7><EFBFBD>ͬ
|
|
|
|
|
bool isSamePuzzle(int a[N][N], int b[N][N]) {
|
|
|
|
|
//<2F><>ͬ<EFBFBD><EFBFBD>true,<2C><><EFBFBD><EFBFBD>false
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// <20><>ӡƴͼ״̬
|
|
|
|
|
void printPuzzle(int puzzle[N][N]) {
|
|
|
|
|
//˫<><CBAB>forѭ<72><D1AD>ʵ<EFBFBD><CAB5>ƴͼ<C6B4>Ĵ<EFBFBD>ӡ
|
|
|
|
|
for (int i=0;i<N;i++)
|
|
|
|
|
{
|
|
|
|
|
for (int j=0;j<N;j++) printf("%d ",puzzle[i][j]);
|
|
|
|
|
printf("\n");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>㵱ǰ״̬<D7B4><CCAC>Ŀ<EFBFBD><C4BF>״̬<D7B4>Ĺ<EFBFBD><C4B9>ƴ<EFBFBD><C6B4><EFBFBD>
|
|
|
|
|
int heuristic(Node* current, Node* goal) {
|
|
|
|
|
int h = 0;
|
|
|
|
|
// <20><><EFBFBD>㲻ƥ<E3B2BB><C6A5><EFBFBD><EFBFBD>ƴͼ<C6B4><CDBC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// <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>λ<EFBFBD><CEBB>
|
|
|
|
|
// <20>ҵ<EFBFBD><D2B5>հ<D5B0><D7BF><EFBFBD>λ<EFBFBD><CEBB>
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
//<2F><>new_x<5F><78>new_y<5F><79>ֵ
|
|
|
|
|
int way[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD>ƶ<EFBFBD><C6B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¿<EFBFBD><C2BF><EFBFBD>λ<EFBFBD>ã<EFBFBD><C3A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƶ<EFBFBD>
|
|
|
|
|
int new_x=key_x+way[dir][0];
|
|
|
|
|
int new_y=key_y+way[dir][1];
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><CEBB><EFBFBD>Ƿ<EFBFBD><C7B7>ڱ߽<DAB1><DFBD><EFBFBD>
|
|
|
|
|
if (0>new_x || new_x>=N || 0>new_y || new_y>=N) return NULL;
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD>½ڵ㣬<DAB5><E3A3AC><EFBFBD>Ƶ<EFBFBD>ǰƴͼ״̬<D7B4><CCAC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><CEBB>
|
|
|
|
|
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>·<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>Сfֵ<66>Ľڵ<C4BD>
|
|
|
|
|
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]; // <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Сfֵ<66>Ľڵ<C4BD>
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD>ڵ<EFBFBD><DAB5><EFBFBD>Ŀ<EFBFBD><C4BF>״̬ƥ<CCAC>䣬<EFBFBD><E4A3AC>ʾ<EFBFBD>ҵ<EFBFBD><D2B5><EFBFBD>
|
|
|
|
|
if (isSamePuzzle(current->puzzle, goal->puzzle)) 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><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;
|
|
|
|
|
//printPuzzle(current->puzzle);
|
|
|
|
|
//printf("%d\n\n",min_f);
|
|
|
|
|
//<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++] = current;
|
|
|
|
|
|
|
|
|
|
int key = 0;
|
|
|
|
|
// <20><><EFBFBD>ҵ<EFBFBD>ǰ<EFBFBD>ڵ<EFBFBD><DAB5>пհ<D5B0><D7BF><EFBFBD>λ<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>ƶ<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>hֵ
|
|
|
|
|
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><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><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>ڿ<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>fֵ<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;
|
|
|
|
|
}
|
|
|
|
|
//<2F><><EFBFBD><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>Ϣ<EFBFBD><CFA2>
|
|
|
|
|
else if (in_OPEN && fNew < OPEN[open_index]->f) {
|
|
|
|
|
OPEN[open_index] = new_node;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL; // <20><EFBFBD>
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// <20><>ӡ<EFBFBD><D3A1>·<EFBFBD><C2B7>
|
|
|
|
|
void printPath(Node* final) {
|
|
|
|
|
if (final == NULL) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
printPath(final->parent); // <20>ݹ<EFBFBD><DDB9><EFBFBD>ӡ·<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);
|
|
|
|
|
init->h=heuristic(init, goal);
|
|
|
|
|
init->f=init->h;
|
|
|
|
|
|
|
|
|
|
Node* final = AStar(init, goal);
|
|
|
|
|
if (final) {
|
|
|
|
|
printf("This problem has a solution:\n");
|
|
|
|
|
//printPuzzle((final->parent)->puzzle);
|
|
|
|
|
printPath(final); // <20><>ӡ<EFBFBD><D3A1>·<EFBFBD><C2B7>
|
|
|
|
|
} else {
|
|
|
|
|
printf("This problem has no solution<6F><6E>\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|