C语言实现8数码难题(宽度优先搜索)

最近人工智能基础老师让我们用宽度优先搜索来实现八数码难题,所以就用了自己所学不多的C语言进行了编写。

代码如下:

#include<stdio.h>
#include<string.h>

/*代码说明*/ 
/*8 puzzle problem*/
/*要输入可行解 否则会出现无解的情况*/ 

char start[10]={'2','8','3',//起始状态
			    '1',' ','4',
			    '7','6','5'};
			
char end[10]={'1','2','3',//目标状态 
		      '8',' ','4',
		  	  '7','6','5'};

char store[500][10];//用于存储状态的数组
int step;//步数
int location;//白框' '在start数组中的位置 
int total_num=0;//状态总数
int next_num=0;//下一级的状态个数 

int chess_x;//将start数组中白框' '的位置转换为3*3棋盘中的坐标
int chess_y;

int dx[4]={0,1,0,-1};//白框' '移动
int dy[4]={1,0,-1,0};

int compare_state()
{
	for(int i=0;i<total_num;i++)
	{
		if(strcmp(store[i],start)==0) return 0;//与状态库中的状态比较 若有相同的则返回0
	}
	return 1;//若没有相同的则返回1 
}

int main()
{
	int mid_vaule;//中间变量
	int fake_total_num=1;//用于循环 
	int fake_next_num=1;//用于循环  
	
	strcpy(store[total_num],start);//将初始状态存储到状态库中
	total_num++;
	
	if(strcmp(start,end)==0)//比较初始状态和目标状态是否相等
	{
		printf("最短步数为: %d\r\n",step);
		return 0;
	}
	
	while(1)
	{
		for(int j=fake_total_num-fake_next_num;j<fake_total_num;j++)
		{
			strcpy(start,store[j]);//将下一级的状态从状态库中提取出来存放到start数组中
			for(int i=0;i<9;i++)//寻找' '位置
			{
				if(start[i]==' ')
				{
					location = i;
					break;
				} 
			}
			
			chess_x = location/3;//将白框' '位置装换到3*3棋盘坐标中
			chess_y = location%3;
			
			for(int i=0;i<4;i++)//让白框' '移动
			{
				chess_x+=dx[i];
				chess_y+=dy[i];
				
				if(chess_x<0 || chess_x>=3 || chess_y<0 || chess_y>=3)//白框' '超出棋盘则continue
				{
					chess_x-=dx[i];
					chess_y-=dy[i];
					continue;
				}
			
				mid_vaule = start[chess_x*3+chess_y];       //将变换后的位置中的内容和原位置中的内容互换
				start[chess_x*3+chess_y] = start[location];
				start[location] = mid_vaule;

				if(compare_state())//比较此时状态是否存在与状态库中
				{
					strcat(store[total_num],start);//如果不存在则将此次状态存储在状态库中
					printf("此时状态: %s    总的状态数:%d\r\n",start,total_num);
					total_num++;//总状态加一
					next_num++;//下一级状态加一
					if(total_num>=500)//如果白框' '移动步数太多 则认为无解
					{
						printf("此问题无解\r\n");
						return 0;
					}
				}
				else//如果状态库中存在此时状态 则将内容和坐标都变换回去 然后continue
				{
					mid_vaule = start[chess_x*3+chess_y];       
					start[chess_x*3+chess_y] = start[location];
					start[location] = mid_vaule;
				
					chess_x-=dx[i];
					chess_y-=dy[i];
					continue;
				}
	
				if(strcmp(start,end)==0)//比较此时状态和目标状态是否相等
				{	
					step++;
					printf("最短步数为: %d\r\n",step);
					return 0;
				}
				
				mid_vaule = start[chess_x*3+chess_y];       //内容变换回去
				start[chess_x*3+chess_y] = start[location];
				start[location] = mid_vaule;
				
				chess_x-=dx[i];//坐标变换回去
				chess_y-=dy[i];
			}
		}
		fake_total_num=total_num;//将总的状态数赋值 用于循环
		fake_next_num = next_num;//将下一次状态数赋值 用于循环 
		next_num = 0;//清零
		step++;//步数加一 
	}
	return 0;
}
//作者:Black_Cat 

第一次发帖,有什么问题望指正。

  • 4
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值