/* -*- C -*- * * 8_number.c - 8数码码问题,采用A*算法,调试了5个小时左右,相当的痛苦!还是要多编程才行啊!又见指针忽悠我! * * Author : heixia * Created On : Tue Mar 18 10:04:05 2008 * */
#include <stdio.h> #include <stdlib.h>
#define N 3 #define MAX 5000 //寻找的最大步数,有些可能找不到结果
typedef struct num * Num; struct num{ int depth; int cost; int direction; //0:up,1:down,2:left,3:right.
int i,j; //indicate the position of the blank.
int a[ N ][ N ]; Num pre; Num father; };
Num goal;
int n = 0;
int search(Num start); int check( Num now,Num tobe ); void Print( Num to ); Num creatNum( Num now,int direction ); Num update( Num toupdate,Num new_num );
//main
int main( ){ int i,j; Num start; start = ( Num )malloc( sizeof( *start ) ); goal = ( Num )malloc( sizeof( *goal ) );
if( start == NULL || goal == NULL ){ printf( "Memory overflow.\n" ); return 0; }
start->depth = 0; start->direction = -1; start->pre = NULL; start->father = NULL; // printf( "please input the inital state:\n" );
for(i = 0;i < N; i ++ ) for( j = 0; j < N; j ++ ){ scanf( "%d",&start->a[ i ][ j ] ); if( start->a[ i ][ j ] == -1 ){ start->i = i; start->j = j; } }
// printf( "\nNow you can input the goal:\n" );
for(i = 0;i < N; i ++ ) for( j = 0; j < N; j ++ ){ scanf( "%d",&goal->a[ i ][ j ] ); }
search( start ); return 0; }
int search(Num start){ Num current = NULL; Num toVisit = start,new_num; int i; int step = 0;
while( toVisit ){ step ++; if( step > MAX ){ printf( "Sorry,I have done what I can do.\n"); break; } current = toVisit; // pr( current );
toVisit = toVisit->pre; // pop( toVisit );
if( check( current,goal ) ){ Print( current ); return 0; } else { for( i = 0; i < 4; i ++ ){ if( current->direction != i ){ new_num = creatNum( current,i ); if( new_num != NULL ){ // pr( new_num );
toVisit = update( toVisit,new_num ); // Print( toVisit );
} } } } }
//释放内存
current = toVisit; while( current ){ toVisit = toVisit->pre; free( current ); current = toVisit; } } /*This is wrong!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! void pop( Num toVisit ){ toVisit = toVisit->pre; }*/
int check( Num now,Num tobe ){
// ==> 08.11.8 change // int **b,**c;
// ==>
int (*b)[N],(*c)[N];
// <== int i,j; b = now->a; c = tobe->a;
for( i = 0; i < N ;i ++ ) for( j = 0; j < N ; j ++ ){ if( now->a[ i ][ j ] != tobe->a[ i ][ j ]) return 0; }
return 1; }
void Print( Num to ){ int i,j; if( to->father != NULL ){ Print( to->father ); }
for( i = 0; i < N; i ++ ){ for( j = 0; j < N ; j ++ ){ if( to->a[ i ][ j ] != -1) printf( "%4d" ,to->a[ i ][ j ]); else printf( " " ); } printf( "\n" ); } printf( "\n" ); }
/* just for debug void pr( Num to ){ int i,j;
for( i = 0; i < N; i ++ ){ for( j = 0; j < N ; j ++ ){ if( to->a[ i ][ j ] != -1) printf( "%4d" ,to->a[ i ][ j ]); else printf( " " ); } printf( "\n" ); } printf( "\n" ); } */
Num creatNum( Num now,int direction ){ Num new_num; int i,i_old,j,j_old,h,k,cost = 0; int n1 = 0,n2 = 0; i = i_old = now->i; j = j_old = now->j;
new_num = ( Num )malloc( sizeof( *new_num ) ); switch( direction ){ case 0:i--; new_num->direction = 1; break; case 1:i++; new_num->direction = 0; break; case 2:j--; new_num->direction = 3; break; case 3:j++; new_num->direction = 2; break; default: printf( "error direction.\n" ); return NULL; }
if( i < 0 || i >= N || j < 0 || j >= N ){ free( new_num ); return NULL; }
for( h = 0; h < N; h ++ ) for( k = 0 ; k < N ;k ++ ){ new_num->a[ h ][ k ] = now->a[ h ][ k ]; }
new_num->a[ i_old ][ j_old ] = now->a[ i ][ j ]; new_num->a[ i ][ j ] = -1;
new_num->depth = now->depth + 1;
new_num->i = i; new_num->j = j; /* for( h = 0; h < N; h ++ ) for( k = 0 ; k < N ;k ++ ){ if( new_num->a[ h ][ k ] != goal->a[ h ][ k ]) new_num->cost ++; } */ if( now->a[ i_old ][ j_old ] != goal->a[ i_old ][ j_old ] ) n1++; if( now->a[ i ][ j ] != goal->a[ i ][ j ] ) n1++; if( new_num->a[ i_old ][ j_old ] != goal->a[ i_old ][ j_old ] ) n2++; if( new_num->a[ i ][ j ] != goal->a[ i ][ j ] ) n2++;
new_num->cost = now->cost + ( n2 - n1 ) + 1; //+1 is because new_num->depth = now->depth + 1;
new_num->pre = NULL; new_num->father = now; return new_num; }
Num update( Num toupdate,Num new_num ){ Num temp,p;
// temp = ( Num )malloc( sizeof( *temp ) ); 不需要!
// p = ( Num )malloc( sizeof( *p ) );
p = temp = toupdate;
if( toupdate != NULL ){ while( temp != NULL && temp->cost < new_num->cost ){ p = temp; temp = temp->pre; } if( toupdate->cost >= new_num->cost ){ new_num->pre = toupdate; toupdate = new_num; } else { p->pre = new_num; new_num->pre = temp; } } else{ toupdate = new_num; } return toupdate; }
|