⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 8数码问题.cpp

📁 本程序是用C++语言编写的
💻 CPP
字号:
/*--------------------------------------------------说明------------------------------------------------*/
/*                         此程序为八数码问题求解                                                       */

/*                 本程序利用启发函数来实现A算法(实为A*算法),效率较高;                              */
/*                        具体思想请参考人工智能相关书籍;                                              */
/*                           启发函数为 深度+不在位数;                                                 */
/*                             作者:张莉           学号:040640203;                                     */
/*                                  日期:2008.06.21;                                                  */
/*                                   仅供学习使用。                                                     */
 

#include<stdio.h>
#include<stdlib.h>

#define  UP    1                    //节点向上移
#define  DOWN  2                    //节点向下移
#define  LEFT  3                    //节点向左移
#define  RIGHT 4                    //节点向右移
#define MAXVEX  40320               //定义最大扩展节点数

/*---------------------------------------------部分参数--------------------------------------------------------*/
int origin_data[9];                 //初始节点
int target_data[9];                 //目标节点
typedef struct vex{                 //定义结构体节点
    int data[9];                    //此时的数据排列,等价于八数码状态
	int layer;                      //节点的层数
	int diff;                       //节点与目标节点相比不同的位数
	int point;                      //标志位,未被访问为0,被open表访问后为1,被close表访问时为1
	int weight;                     //weight=diff+layer,相当于A*算法中的f函数
	struct vex *next;
	struct vex  *prio;
	struct vex *father;
}vexnode;
vexnode *open_root;
vexnode*close_root;
/*------------------------------------------部分参数-----------------------------------------------------------*/

/*---------------------------------------------------主要函数------------------------------------------------------------*/



//函数名称:vexnode*create_vexnode()
//功能说明:新建一个结构体节点,返回节点指针
//入口参数:无
//出口参数:结构体节点的指针
vexnode*create_vexnode(){
	return(vexnode*)malloc(sizeof(vexnode));
}




//函数名称:check_inputnum(int data[]);
//功能说明:检查输入数据的正确性
//入口参数:一维数组
//出口参数:若数组正确,返回值为1,反之返回0,并输出错误原因
int check_inputnum(int data[]){
	int i=0,j;
	while(i<9){
		if(data[i]>8){
			printf("此输入数据中第%d行%d列 %d大于8\n",i/3+1,i%3+1,data[i]);
		    return 0;
		}//if
		if(data[i]<0){
			printf("此输入数据中第%d行%d列 %d小于0\n",i/3+1,i%3+1,data[i]);
				return 0;
		}//if
		i++;
	}
	for(i=0;i<9;i++)
		for(j=i+1;j<9;j++){
			if(data[i]==data[j]){
				printf("此输入数据中第%d行%d列与第%d行%d列数据%d相同.\n",i/3+1,i%3+1,j/3+1,j%3+1,data[i]);
				return 0;
			}//if
		}//for
		return 1;
}


//函数名称:ary_attr(int data[]);
//功能说明:判断一维数组的奇偶属性
//入口参数:一维数组
//出口参数:若数组属性为奇,返回值为1,为偶则返回为0
int ary_attr(int data[]){
	int i,j,attri;
	attri=0;
	for(i=1;i<9;i++)
		for(j=0;j<i;j++)
			if(data[i]!=0&&data[j]!=0&&data[j]<data[i])
				attri++;
			return   attri%2;
}


//函数名称:input_data(int data1[],int data2[]);
//功能说明: 输入初始节点和目标节点的八数码状态,并判断正确性,直到输入正确或退出程序为止
//入口参数:两个一维数组
//出口参数:如果输入正确,返回值为1,否则退出程序
int input_data(int data1[],int data2[]){
	int i;
	char choice1;
	printf("请输入初始节点数据: \n");
	printf("请输入3行从0到8的数据:\n");
	for(i=0;i<9;i++)
		scanf("%d",data1+i);
	while(!check_inputnum(data1)){
		
		printf("数据输入错误!\n");
		printf("要重新输入吗?(y/n)");

		scanf("%c",&choice1);
		if(choice1=='y'||choice1=='Y'){
			printf("\n请重新输入:");
			for(i=0;i<9;i++)
	        	scanf("%d",data1+i);
		}//if
		else if(choice1=='n'||choice1=='N'){
			printf("\n抱歉,数据输入错误,无法求解\n");
			printf("\n下面将退出程序。");
			exit(0);
		}//else if

	}//while

	printf("初始数据输入无误!\n");

	printf("\n下面请输入目标节点数据:\n");
	printf("请输入3行从0到8的数据:\n");
	for(i=0;i<9;i++)
		scanf("%d",data2+i);
	while(!check_inputnum(data2)){
		
		printf("数据输入错误!\n");
		printf("要重新输入吗?(y/n)");
		scanf("%c",&choice1);
		if(choice1=='y'||choice1=='Y'){
			printf("\n请重新输入:");
			for(i=0;i<9;i++)
	        	scanf("%d",data2+i);
		}//if
		else if(choice1=='n'||choice1=='N'){
            printf("\n抱歉,数据输入错误,无法求解\n");
			printf("\n下面将退出程序。\n");
			exit(0);
		}//else
	}//while
	printf("目标数据输入无误!\n");
	return 1;
}//end of program





//函数名称:copy(int data1[],int data2[])
//函数功能:复制数组
//入口参数:复制数组和被复制数组指针
//出口参数:无
void copy(int data1[],int data2[]){
		int i=0;
		for(i=0;i<9;i++)
			data1[i]=data2[i];
	
}

//函数名称:data_solution(int data1[],int data2[])
//函数功能:判断目标节点到初始节点是否有解
//入口参数:连个一维数组(初始节点和目标节点八数码状态)
//出口参数:有解返回值1,无解重新输入或退出
int data_solution(int data1[],int data2[]){
	char choice2;
	while(ary_attr(data1)!=ary_attr(data2)){
		printf("\n抱歉,此8数码无解!\n");
		printf("需要重新输入吗?(y/n)");
		scanf("%c",&choice2);
		if(choice2=='y'||choice2=='Y'){
			printf("\n下面请重新输入数据:\n");
			input_data(data1,data2);

		}
		else if(choice2=='N'||choice2=='n'){
			printf("\n--下面将退出程序--\n");
			exit(0);
		}
	}
	return 1;
}



//函数名称:insert_open(vexnode*root,vexnode*p);
//函数功能:将节点有序插入open表中
//入口参数:open表入口指针,插入节点指针
//出口参数:节点指针为空,则返回0,否则,插入open表返回值1
int insert_open(vexnode*root,vexnode*p){
	if(p==NULL)
		return 0;
	vexnode*p1,*p2;
	p1=root->next;
	p2=root;
	while(p1!=NULL&&p->weight>p1->weight){
		p2=p1;
	    p1=p1->next;
	}
	p2->next=p;
	p->prio=p2;
	p->next=p1;
	if(p1!=NULL)
		p1->prio=p;
	return 1;
}



//函数名称:insert_close(vexnode*root,vexnode*p);
//函数功能:将节点插入close表中
//入口参数:close表入口指针,插入节点指针
//出口参数:节点指针为空,则返回0,否则,插入close表返回值1
int ADD_close(vexnode*closeroot,vexnode*p){
	if(p==NULL)
		return 0;
	p->next=closeroot->next;
	p->prio=closeroot;
	closeroot->next=p;
	if(p->next!=NULL)
		p->next->prio=p;
	return 1;
}


//函数名称:*first_open(vexnode*root)
//函数功能:删除open表中第一个节点
//入口参数:open表的入口指针
//出口参数:若open表为空,则返回NULL,否则返回删除节点指针
vexnode*remove_open(vexnode*openroot){
	vexnode *p;
	if(openroot->next==NULL)
		return NULL;
	p=openroot->next;
	openroot->next=p->next;
	if(p->next!=NULL)
		p->next->prio=openroot;
	p->prio=NULL;
	p->next=NULL;
	return p;
}


//函数名称:swap(int *data1,int *data2)
//函数功能:交换一维数组中的两个数
//入口参数:一维数组中两个数的指针
//出口参数:无
void swap(int *data1,int *data2){
	int data;
	data=*data1;
	*data1=*data2;
	*data2=data;
}



//函数名称:do_direct(int m[],int op)
//函数功能:对八数码中的数进行移动
//入口参数:一维数组(视为八数码),移动方向 
//出口参数:移动成功返回值为1,否则为0
int do_direct(int m[],int op){
	int blank;
	blank=0;
	while(m[blank]!=0&&blank<9)
		blank++;
	if(blank>=9)
		printf("");
	switch(op){
	case UP:
		if(blank>2)
			swap(m+blank,m+blank-3);
		break;
	case DOWN:
		if(blank<6)
			swap(m+blank,m+blank+3);
		break;
	case LEFT:
		if(blank%3!=0)
			swap(m+blank,m+blank-1);
		break;
	case RIGHT:
		if(blank%3!=2)
			swap(m+blank,m+blank+1);
		break;
	default:return 0;
	}
	return 1;
}

//函数名称:compare(int data1[],int data2[])
//函数功能:比较当前节点和目标节点,得出当前节点不在位数
//入口参数:两个一维数组(视为八数码当前状态) 
//出口参数:返回节点不在位数
int compare(int data1[],int data2[]){
	int i,diff;
	diff=0;
	for(i=0;i<9;i++)
		if(data1[i]!=data2[i])
			diff++;
		return diff;
}





//函数名称:has_appear(vexnode*open,vexnode*close,vexnode*p)
//函数功能:判断移动后节点是否已经在open表或在close表中出现过
//入口参数:open表和close表入口指针,当前节点指针 
//出口参数:出现过返回值为1,否则为0

int has_appear(vexnode*open,vexnode*close,vexnode*p){
        vexnode *p1;
		int i,same=1;
		p1=open->next;
		while(p1!=NULL){
			for(i=0;i<9;i++)
				if(p1->data[i]!=p->data[i])
					same=0;
				if(same)
					return 1;
				p1=p1->next;
		}
		p1=close->next;
		while(p1!=NULL){
			same=1;
			for(i=0;i<9;i++)
				if(p1->data[i]!=p->data[i])
					same=0;
				if(same)
					return 1;
				p1=p1->next;
		}
		return 0;
}


//函数名称:vexnode *copy(vexnode *p);
//函数功能:复制节点
//入口参数:被复制节点指针
//出口参数:返回复制节点指针
vexnode *copy_vexnode(vexnode*p){
	vexnode*p1;
	p1=create_vexnode();
	int i;
	for(i=0;i<9;i++)
		(p1->data)[i]=(p->data)[i];
	p1->layer=p->layer;
	p1->diff=p->diff;
	p1->weight=p->weight;
	return p1;
}


//函数名称:print_vexdata(int data[])
//函数功能:打印节点的八数码数据
//入口参数:一维数组(视为八数码)
//出口参数:无
void print_vexdata(int data[]){
	int i=0;
	for(i=0;i<9;i++){
		if((i%3)==0)
			printf("\n");
		printf("%d  ",data[i]);
	}
}


//函数名称:print_allvex(vexnode *p)
//函数功能:采用递归,输出从目标节点到初始节点路径
//入口参数:一维数组(视为八数码),移动方向 
//出口参数:当前输出节点的层数
int print_allvex(vexnode*p){
	vexnode*p1=p;
	int layer;
	if(p1!=NULL){
		layer=print_allvex(p1->father);
		printf("\n");
		print_vexdata(p1->data);
		return layer+1;
	}
		else
			return -1;
}



//函数名称:free_stru(vexnode*root)
//函数功能:释放节点表
//入口参数:表入口指针
//出口参数:无
void free_stru(vexnode*root){
	vexnode*p1,*p2;
	p1=root->next;
	while(p1!=NULL){
		p2=p1->next;
		free(p1);
        p1=p2;
	}
	free(root);
}







			
//函数名称:mian()
//函数功能:主程序执行
//入口参数:无
//出口参数:无
void main(){
	vexnode *p1,*p2;
	int op;
	int node_num,total_step;
	open_root=create_vexnode();
    close_root=create_vexnode();
	open_root->prio=open_root->next=NULL;
	close_root->prio=close_root->next=NULL;

	p1=create_vexnode();
	p1->father=NULL;
	p1->layer=0;
	input_data(origin_data,target_data);
	data_solution(origin_data,target_data);
	
	copy(p1->data,origin_data);
    insert_open(open_root,p1);
    node_num=1;
	p1=remove_open(open_root);
while(p1!=NULL){
	if(node_num<=MAXVEX){
		ADD_close(close_root,p1);
		for(op=1;op<=4;op++){
			p2=copy_vexnode(p1);
			do_direct(p2->data,op);
			if(has_appear(open_root,close_root,p2)!=1){
				p2->father=p1;
				p2->layer=p1->layer+1;
				p2->diff=compare(p2->data,target_data);
				p2->weight=p2->layer+p2->diff;
				if(compare(p2->data,target_data)==0){
					total_step=print_allvex(p2);
					printf("\n总步数为:%d\n",total_step);
					free_stru(open_root);
					free_stru(close_root);
				}//if(compare)
				else{
			     node_num++;
				 insert_open(open_root,p2);
				}//else
			}//if(has_appear)
			else{
				free(p2);
			}//else
		}//for
		p1=remove_open(open_root);
	}//if(node_num)
    else {
		printf("\n抱歉,此八数码无解!\n");
	}//else
}//while
	
	printf("\n无解!\n");
}





	

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -