/*2x2x2のルービックキューブを解くCプログラム。この場合、探索空間が3x3x3に比べてかなり小さくて、どんな状態からでも解ける。アルゴリズムや入力データなどは昨日のと同じ考え方。実行結果はまたこんど。*/
ソースはこちら
/*続く*/
ソースはこちら
#include <math.h> #include <stdio.h> #include <stdlib.h> #define D 2 /*2x2x2のルービックキューブ。ここを4にしても4x4x4が解けるわけじゃない*/ struct node{ char surface[6][D][D]; /*ルービックキューブ各面の情報*/ unsigned int cost; /*今の状態に何手で来たかを各ノードに記憶*/ unsigned int heuristic; /*このノードのヒューリスティック値*/ unsigned int expectation; /*heuristic+cost*/ long double hash; /*前に展開したノードと同じノードを展開しないためにハッシュ値を使う*/ struct node *next[6]; /*ここから展開される子ノードへのポインタ*/ struct node *reverse; /*親ノードへのポインタ。最後に解へのパスをたどるめに使う*/ struct node *nextleaf; /*現在のリーフをリスト構造でつなぐ。次のリーフへのポインタ*/ struct node *revleaf; /*前のリーフへのポインタ*/ struct node *nodelist; /*ハッシュ値を比べるために,生成したノードをすべてリニアにつなぐ。次のノードへのポインタ*/ struct node *revnode; /*一つ前のノードへのポインタ*/ char ope; /*親ノードから,どんな状態変化をされて来たのかを記憶*/ char opecolor; /*親ノードからこの状態に来るときに,どの面を回したのか記憶*/ }root, goal, *minG, leaflist, endleaf, nodeend; unsigned int min; /*heuristic+costの最小値*/ void start(void); /*rootの初期化など*/ void develop(struct node *cube); /*ノードを展開する*/ void allocate(struct node *cube); /*ノードを展開するための,メモリを確保*/ void heuristic(struct node *cube); /*ヒューリスティック関数*/ void operate(struct node *cube); /*生成したノードの状態遷移を行う*/ void Rrot(struct node *next, struct node *original, char s); /*一面を右に90度回転*/ void Lrot(struct node *next, struct node *original, char s); /*一面を左に90度回転*/ void rot(struct node *next, struct node *original, char s); /*一面を180度回転*/ void search(void); /*heuristic+costが最小のリーフを探す*/ void output(void); /*解へのパスをたどって解法を表示*/ void exception(void); /*rootを展開するときだけちょっと特別*/ int main(void) { unsigned int depth=0; start(); /*いろんなものを初期化*/ develop(&root); /*rootを展開*/ exception(); /*rootを展開その2*/ search(); /*展開すべきリーフを探す*/ while(minG->heuristic){ /*ゴール状態でない限りループ*/ if(minG->cost>depth) printf("%dn",++depth); /*現在展開した一番深いノードの深さを表示*/ develop(minG); /*リーフを展開*/ search(); /*次に展開するリーフを探す*/ } output(); /*解法を表示*/ return 0; } void start(void) { char i,j,k; for(i=0;i<6;i++)
next[i]); /*展開した各ノードのヒューリスティック値を計算*/ } void allocate(struct node *cube) { char i,j,k,l; struct node *nextcube; nextcube=(struct node *)malloc(sizeof(struct node)*6); /*メモリ確保*/ if(!nextcube){ printf("メモリ割り当てエラーan"); exit(1); } nodeend.revnode->nodelist=&nextcube[0]; /*ノードリストにつなげる*/ cube->revleaf->nextleaf=&nextcube[0]; /*リーフリストにつなげる*/ nextcube[0].revleaf=cube->revleaf; for(i=0;i<5;i++){ /*生成したノードをリストにつなげて,親と同じ状態をコピー*/
next[i]=&nextcube[i]; nextcube[i].reverse=cube; nextcube[i].nodelist=&nextcube[i+1]; for(k=0;k<6;k++)
surface[k][j][l]; nextcube[i].cost=1+cube->cost; nextcube[i].nextleaf=&nextcube[i+1]; nextcube[i+1].revleaf=&nextcube[i]; } cube->next[5]=&nextcube[5]; nextcube[5].reverse=cube; nextcube[5].nodelist=&nodeend; nodeend.revnode=&nextcube[5]; for(k=0;k<6;k++)
surface[k][j][l]; nextcube[5].cost=cube->cost+1; nextcube[5].nextleaf=cube->nextleaf; cube->nextleaf->revleaf=&nextcube[5]; } void operate(struct node *cube) /*各ノードで状態遷移を行う*/ { struct node *nextcube; char i, k=0; if(cube->opecolor!=1){ nextcube=cube->next[k++]; for(i=0;i<D;i++){
surface[0][i][0]=cube->surface[3][i][0]; nextcube->surface[2][i][0]=cube->surface[0][i][0]; nextcube->surface[5][i][0]=cube->surface[2][i][0]; nextcube->surface[3][i][0]=cube->surface[5][i][0]; } Lrot(nextcube, cube, 1); nextcube->ope=-1; nextcube->opecolor=1; nextcube=cube->next[k++]; for(i=0;i<D;i++){
surface[0][i][0]=cube->surface[5][i][0]; nextcube->surface[2][i][0]=cube->surface[3][i][0]; nextcube->surface[5][i][0]=cube->surface[0][i][0]; nextcube->surface[3][i][0]=cube->surface[2][i][0]; } rot(nextcube, cube, 1); nextcube->ope=0; nextcube->opecolor=1; nextcube=cube->next[k++]; for(i=0;i<D;i++){
surface[0][i][0]=cube->surface[2][i][0]; nextcube->surface[2][i][0]=cube->surface[5][i][0]; nextcube->surface[5][i][0]=cube->surface[3][i][0]; nextcube->surface[3][i][0]=cube->surface[0][i][0]; } Rrot(nextcube, cube, 1); nextcube->ope=1; nextcube->opecolor=1; } if(cube->opecolor!=2){ nextcube=cube->next[k++]; for(i=0;i<D;i++){
surface[0][0][D-1-i]=cube->surface[1][D-1-i][1]; nextcube->surface[4][i][0]=cube->surface[0][0][D-1-i]; nextcube->surface[5][1][i]=cube->surface[4][i][0]; nextcube->surface[1][D-1-i][1]=cube->surface[5][1][i]; } Lrot(nextcube, cube, 2); nextcube->ope=-1; nextcube->opecolor=2; nextcube=cube->next[k++]; for(i=0;i<D;i++){
surface[0][0][D-1-i]=cube->surface[5][1][i]; nextcube->surface[4][i][0]=cube->surface[1][D-1-i][1]; nextcube->surface[5][1][i]=cube->surface[0][0][D-1-i]; nextcube->surface[1][D-1-i][1]=cube->surface[4][i][0]; } rot(nextcube, cube, 2); nextcube->ope=0; nextcube->opecolor=2; nextcube=cube->next[k++]; for(i=0;i<D;i++){
surface[0][0][D-1-i]=cube->surface[4][i][0]; nextcube->surface[4][i][0]=cube->surface[5][1][i]; nextcube->surface[5][1][i]=cube->surface[1][D-1-i][1]; nextcube->surface[1][D-1-i][1]=cube->surface[0][0][D-1-i]; } Rrot(nextcube, cube, 2); nextcube->ope=1; nextcube->opecolor=2; } if(cube->opecolor!=0){ nextcube=cube->next[k++]; for(i=0;i<D;i++){
surface[4][1][i]=cube->surface[3][0][D-1-i]; nextcube->surface[2][1][i]=cube->surface[4][1][i]; nextcube->surface[1][1][i]=cube->surface[2][1][i]; nextcube->surface[3][0][D-1-i]=cube->surface[1][1][i]; } Lrot(nextcube, cube, 0); nextcube->ope=-1; nextcube->opecolor=0; nextcube=cube->next[k++]; for(i=0;i<D;i++){
surface[4][1][i]=cube->surface[1][1][i]; nextcube->surface[2][1][i]=cube->surface[3][0][D-1-i]; nextcube->surface[1][1][i]=cube->surface[4][1][i]; nextcube->surface[3][0][D-1-i]=cube->surface[2][1][i]; } rot(nextcube, cube, 0); nextcube->ope=0; nextcube->opecolor=0; nextcube=cube->next[k]; for(i=0;i<D;i++){
surface[4][1][i]=cube->surface[2][1][i]; nextcube->surface[2][1][i]=cube->surface[1][1][i]; nextcube->surface[1][1][i]=cube->surface[3][0][D-1-i]; nextcube->surface[3][0][D-1-i]=cube->surface[4][1][i]; } Rrot(nextcube, cube, 0); nextcube->ope=1; nextcube->opecolor=0; } } void Lrot(struct node *next, struct node *original, char s) { char i,j; for(i=0;i<D;i++)
surface[s][i][j]=original->surface[s][j][D-1-i]; /*左回転*/ } void Rrot(struct node *next, struct node *original, char s) { char i, j; for(i=0;i<D;i++)
surface[s][i][j]=original->surface[s][D-1-j][i]; /*右回転*/ } void rot(struct node *next, struct node *original, char s) { char i,j; for(i=0;i<D;i++)
surface[s][i][j]=original->surface[s][D-i-1][D-1-j]; /*180度回転*/ }
/*続く*/
※コメント投稿者のブログIDはブログ作成者のみに通知されます