实验目的:通过visual c++进行算法编辑,准确掌握算法运行方式及流程。
通过程序实现类似九宫格的拼图效果,也叫做八方块。
用最快的时间实现最后的效果:1 2 34 5 67 8 0实验原理:先实现一个三行三列数组,再依次比较第一个数与上下左右数值的大小,进行移动,最后实现效果图。
计算出一共移动的步数和每移一步的效果。
实验内容:程序代码如下:// 8block.cpp : 定义控制台应用程序的入口点。
//#include "stdafx.h"#include <stdio.h>#include <stdlib.h>#include <time.h>#define GOAL 123804765//表示我们要找得目标状态struct Node{short state[9];//存放结点的状态short pos;//空格所在的位置,在数组中用0代表空格struct Node *up;//空格上移后的状态struct Node *down;//空格下移后的状态struct Node *left;//空格左移后的状态struct Node *right;//空格右移后的状态struct Node *parent;//它是从哪一状态变换而来的struct Node *next;//表示在队列中的下一个状态} ;struct Tree{short key;//表示当前结点的数值short * state;//表示当前状态的整个数组,当整颗树生成完毕后这一数组将被释放short index;//表示当前数值在数组中的位置bool visited;//对于叶子结点而言,表示这一结点是否被访问过struct Tree * next;//指向它的(下一个)兄弟结点,表示这一位置的下一个数struct Tree *down;//指向它的第一个孩子结点,表示下一位置的第一个数};struct Queue//定义一个队列用于广度优先遍历{struct Node * front;struct Node * rear;};void InitQueue(struct Queue *Q);//初始化一个空队列bool QueueEmpty(struct Queue *Q);//判断队列是否为空void EnQueue(struct Queue *Q,struct Node *N);//入队列struct Node * DeQueue(struct Queue *Q);//出队列,返回队结点void ClearQueue(struct Queue *Q);//清空队列struct Node * GetBestPath(struct Node *tree);//找到一个最短路径,并返回最后的状态结点,如果没有路径返回NULLstruct Tree * CreateCheckTree();//生成一个用于检查状态的查询树void CreateSubCheckTree(struct Tree * T);//生成状态检查子树void FreeCheckTree(struct Tree * checkTree);//释放状态检查树的空间int checkCount=0;//检查结点状态次数int deCount=0;//出队列次数int enCount=0;//入队列次数struct Tree * checkTree;void main(){struct Node* tree=new struct Node;tree->parent=NULL;printf("输入0-8的任意一个排列,其中0表示空格所在的位置:\n");for(int i=0;i<=8;i++){scanf("%d",&tree->state[i]);}for(int i=0;i<=8;i++){if(tree->state [i]==0){tree->pos =i;}}tree->next =NULL;int c1=clock();struct Node *result=GetBestPath(tree);int c2=clock();double t=(c2-c1)/1000.0;printf("状态检查次数:%d,入队列次数:=%d,出队列次数:%d\n",checkCount,enCount,deCount);if(result!=NULL){int path[200];int count=0;struct Node *N=result;while(N!=NULL){path[count]=N->pos;N=N->parent;count++;}printf("有最短路径,共须%d步。
\n下面给出各步空格出现的位置(第一个数为初始位置):\n",count-1);for(int i=count-1;i>=0;i--){printf("%d ",path[i]);}}else{printf("不存在路径!");}printf("\n所用时间为:%f秒",t);getchar();getchar();}void FreeCheckTree(struct Tree * checkTree){if(checkTree->down!=NULL){FreeCheckTree(checkTree->down);}if(checkTree->next!=NULL){FreeCheckTree(checkTree->next);}delete checkTree;}struct Tree * CreateCheckTree(){struct Tree *T = new struct Tree;T->index =0;T->key =-1;T->next =NULL;T->down =NULL;T->state =new short[10];T->state[0]=-1;for(int i=1;i<=9;i++){T->state [i]=i-1;}CreateSubCheckTree(T);return T;}void CreateSubCheckTree(struct Tree * T){if(T->index==8)//如果前八个数都排好了{T->down =new struct Tree;T->down->key =T->state[9];T->down->visited =false;T->down ->down =NULL;T->down ->next =NULL;delete T->state;}else{struct Tree *old=T;for(int i=T->index+1;i<10;i++){struct Tree *current=new struct Tree;current->state =new short[10];for(int j=0;j<=9;j++){current->state [j]=T->state [j];}current->index =T->index +1;//将指针前移current->next =NULL;current->down =NULL;current->key=current->state[i];//将关键字设置为当前i所指处int temp=current->state[current->index];//以下三句完成交换current->state[current->index]=current->state[i];current->state[i]=temp;if(i==T->index+1)//如果是第一个孩子{T->down=current;old=current;}else{old->next =current;old=current;}CreateSubCheckTree(current);}delete T->state;}}bool checkNode(struct Node *N){checkCount++;struct Tree *current=checkTree;for(int i=0;i<9;i++){current=current->down;while(N->state[i]!=current->key){current=current->next;}}if(current->visited==false){current->visited =true;return true;}else{return false;}}struct Node * GetBestPath(struct Node *tree)//找到一个最短路径,并返回最后的状态结点,如果没有路径返回NULL{checkTree=CreateCheckTree();// printf("分配完成!\n");getchar();int i;struct Queue *Q=new struct Queue;InitQueue(Q);EnQueue(Q,tree);while(!QueueEmpty(Q)){struct Node *N=DeQueue(Q);int index=0;for(i=0;i<=8;i++){index=index*10+N->state[i];}if(index==GOAL){FreeCheckTree(checkTree);ClearQueue(Q);return N;}if(N->pos>=3)//空格可以往上移{struct Node *up=new struct Node;for(i=0;i<=8;i++){up->state [i]=N->state [i];}up->state[N->pos]=up->state [N->pos-3];//完成上移up->state [N->pos-3]=0;//同上up->pos =N->pos-3;if(checkNode(up))//如果这一状态以前没有出现过,保留这一状态{N->up =up;up->parent =N;EnQueue(Q,up);}else//如果这一状态以前出现过,{delete up;N->up =NULL;}}//空格可以往上移if(N->pos<=5)//空格可以往下移{struct Node *down=new struct Node;for(i=0;i<=8;i++){down->state [i]=N->state [i];}down->state[N->pos]=down->state [N->pos+3];//完成下移down->state [N->pos+3]=0;//同上down->pos =N->pos+3;if(checkNode(down))//如果这一状态以前没有出现过,保留这一状态{N->down =down;down->parent =N;EnQueue(Q,down);}else//如果这一状态以前出现过,{delete down;N->down =NULL;}}//空格可以往下移if(N->pos!=0 && N->pos!=3 && N->pos!=6)//空格可以往左移{struct Node *left=new struct Node;for(i=0;i<=8;i++){left->state [i]=N->state [i];}left->state[N->pos]=left->state [N->pos-1];//完成上移left->state [N->pos-1]=0;//同上left->pos =N->pos-1;if(checkNode(left))//如果这一状态以前没有出现过,保留这一状态{N->left =left;left->parent =N;EnQueue(Q,left);}else//如果这一状态以前出现过,{delete left;N->left =NULL;}}//空格可以往左移if(N->pos!=2 && N->pos!=5 && N->pos!=8)//空格可以往右移{struct Node *right=new struct Node;for(i=0;i<=8;i++){right->state [i]=N->state [i];}right->state[N->pos]=right->state [N->pos+1];//完成上移right->state [N->pos+1]=0;//同上right->pos =N->pos+1;if(checkNode(right))//如果这一状态以前没有出现过,保留这一状态{N->right =right;right->parent =N;EnQueue(Q,right);}else//如果这一状态以前出现过,{delete right;N->right =NULL;}}//空格可以往右移}FreeCheckTree(checkTree);return NULL;}void InitQueue(struct Queue *Q)//初始化一个空队列{struct Node * head=new struct Node;head->next =NULL;Q->front =head;Q->rear=head;};bool QueueEmpty(struct Queue *Q)//判断队列是否为空{if(Q->front ==Q->rear ){return true;}else{return false;}};void EnQueue(struct Queue *Q,struct Node *N)//入队列{enCount++;Q->rear->next=N;Q->rear=N;struct Node * DeQueue(struct Queue *Q)//出队列,返回队结点{deCount++;if(Q->front ==Q->rear ){printf("队列已空!!\n");return NULL;}else{struct Node *N=Q->front->next;Q->front->next=N->next;if(Q->rear==N){Q->rear =Q->front;}return N;}}void ClearQueue(struct Queue *Q)//清空队列{while(!QueueEmpty(Q)){delete(DeQueue(Q));}}实验结果:。