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.

247 lines
6.6 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.

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#define N 3 // ???????????????????3x3????
int i,j;
typedef struct Node {
int puzzle[N][N]; // ?洢??????????
struct Node* parent; // ?????????????????·??
int f, g, h; // A*???е? f, g, h ?
} Node;
// ?????μ??????
Node* createNode(int puzzle[N][N]) {
Node* newnode = (Node*)malloc(sizeof(Node));
for(i=0;i<N;i++){
for(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;
}
// ?????????????????
bool isSamePuzzle(int a[N][N], int b[N][N]) {
//相同则返回true,否则返回false
int flag=0;
for(i=0;i<N;i++){
for(j=0;j<N;j++){
if(a[i][j]!=b[i][j]){
return false;
}
}
}
return true;
}
void printPuzzle(int puzzle[N][N]) {
for (i = 0; i < N; i++) {
for (j = 0; j < N; j++) {
printf("%d ", puzzle[i][j]);
}
printf("\n");
}
}
int heuristic(Node* current, Node* goal) {
int h = 0;
for (i = 0; i < N; i++) {
for (j = 0; j < N; j++) {
if (current->puzzle[i][j] != goal->puzzle[i][j] && current->puzzle[i][j] != 0) {
h++;
}
}
}
return h;
}
// ??????????????μ?????
Node* move(Node* current, int dir) {
int key_x, key_y;
for (i = 0; i < N; i++) {
for (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;
if (dir == 0) {
new_x--;
} else if (dir == 1) {
new_x++;
} else if (dir == 2) {
new_y--;
} else if (dir == 3) {
new_y++;
}
if (new_x < 0 || new_x >= N || new_y < 0 || new_y >= N) {
return NULL;
}
Node* newnode = createNode(current->puzzle);
newnode->puzzle[key_x][key_y] = current->puzzle[new_x][new_y];
newnode->puzzle[new_x][new_y] = 0;
return newnode;
}
// A*??????????·??
Node* AStar(Node* start, Node* goal) {
Node* OPEN[1000]; // ?????б???????洢?????????
Node* CLOSED[1000]; // ????б???????洢?????????
int OPEN_SIZE = 0; // ?????б????С
int CLOSED_SIZE = 0; // ????б????С
OPEN[0] = start; // ??????????????????б?
OPEN_SIZE = 1; // ?????б????С?????1
CLOSED_SIZE = 0; // ????б????С?????0
while (OPEN_SIZE > 0) {//??open?б????в???
int min_f = OPEN[0]->f;//???????С??f
int min_index = 0;
// ????????б??о?????Сf?????
for(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?????
if(isSamePuzzle(current->puzzle,goal->puzzle))
{
return current;
}
// ???????????????????????????
OPEN_SIZE--;
//?????б????С??1???????????б??????????????
//????С f ?????????????б????β???????????????????б??С?
//???????????????б??????
Node* temp = OPEN[min_index];
OPEN[min_index] = OPEN[OPEN_SIZE];
OPEN[OPEN_SIZE] = temp;
//?????????????????б???????б???С??1
CLOSED[CLOSED_SIZE]=current;
CLOSED_SIZE++;
int key = 0;
// ??????????п????λ??
for (i = 0; i < N; i++) {
for (j = 0; j < N; j++) {
if (current->puzzle[i][j] == 0) {
key = i * N + j;
break;
}
}
}
// ???????????????????
int dir;
for (dir = 0; dir < 4; dir++) {
Node* new_node = move(current, dir);
if (new_node != NULL && !isSamePuzzle(new_node->puzzle, current->puzzle)) {
//????????g??f??h?
int gNew = current->g + 1;
int hNew = heuristic(new_node, goal);
int fNew = gNew + hNew;
bool in_OPEN = false;
int open_index = -1;
// ????????????????б???
int i1;
for (i1 = 0; i1 < OPEN_SIZE; i1++) {
if (isSamePuzzle(new_node->puzzle, OPEN[i1]->puzzle)) {
in_OPEN = true;
open_index = i1;
break;
}
}
bool in_CLOSED = false;
int i2;
for (i2 = 0; i2 < CLOSED_SIZE; i2++) {
if (isSamePuzzle(new_node->puzzle, CLOSED[i2]->puzzle)) {
in_CLOSED = true;
break;
}
}
//???y???????????б???????????б???
if (!in_OPEN && !in_CLOSED) {
//??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
OPEN[OPEN_SIZE]=new_node;
OPEN_SIZE++;
//printf("1");
}
//????????????????б??У????μ? f ???С????????????б????????????????
else if (in_OPEN && fNew < OPEN[open_index]->f) {
OPEN[open_index]=current;
}
}
}
}
return NULL; // ???
}
// ?????·??
void printPath(Node* final) {
if (final == NULL) {
return;
}
printPath(final->parent); // ?????·??
for (i = 0; i < N; i++) {
if (i%3==0){
printf("-------\n");
}
for (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); // ?????·??
} else {
printf("This problem has no solution??\n");
}
return 0;
}