基于转角数为基准的广度优先搜索(样例:连连看)

c++作业,设计一个简单的连连看程序,建立一个 图 ,然后每次输入两个坐标,判断是否可以消除,初次写觉得广搜可以完成(事实证明的确可以),但是略有些麻烦,本来想看老师的代码的,结果一下整个600来行的简单模拟(八种情况,分别尝试),太麻烦了,就查找这方面的资料,《编程之美》中就对这个方面有所涉及:下面;

首先找到一个起点,起点到终点的路径问题,中间转角数小于3,记录转角;

代码如下,亲自测试消除5-6对方块,还没发现什么bug,有大佬发现欢迎指出:

#include<stdio.h>
#include<string.h>
#include<math.h>
#include<stdlib.h> 
#include<time.h>

//#include<map>
#include<set>
#include<deque>
#include<queue>
#include<stack>
#include<string>
#include<fstream> 
#include<iostream>
#include<algorithm>
using namespace std;

#define ll long long
#define INF    0x3f3f3f3f
#define clean(a,b) memset(a,b,sizeof(a))// 水印 

struct node{
	int x,y;
	int direction,turn_num;
};

void swap(int *a,int *b)
{
	int can=*a;
	*a=*b;
	*b=can;
}

void build_map(int map[10][10])
{
	//定义一个8*8的nmap 
	//地图边界0-|1-8|-9 
	
//	for(int i=0;i<10;++i)
//	{
//		for(int j=0;j<10;++j)
//			cout<<map[i][j]<<" ";
//		cout<<endl;
//	}
	for(int i=1;i<9;++i)
	{
		for(int j=1;j<9;++j)
			map[i][j]=i;//八组不同的图案 对应八个不同的数字 
	}
	for(int i=0;i<100;++i)//打乱100次,从新排列 
		swap(map[rand()%8+1][rand()%8+1],map[rand()%8+1][rand()%8+1]);
	
}

void show_map(int map[10][10],char *img)
{
	cout<<"    ";
	for(int i=1;i<9;++i)
		cout<<i<<"  ";
	cout<<endl<<"---------------------------"<<endl;
	for(int i=1;i<9;++i)
	{
		cout<<i<<"|";
		for(int j=1;j<9;++j)
		{
			if(map[i][j])
				cout<<"  "<<img[map[i][j]];
			else
				cout<<"   ";
		}
			
		cout<<endl;
	}
	cout<<"---------------------------"<<endl;
}

input_dot(int *dot)
{
	for(int i=0;i<4;++i)
		cin>>dot[i];
}

int judge(int map[10][10],int dot[4])
{
	bool biaoji[15][15];
	int fx[4]={1,-1,0,0};
	int fy[4]={0,0,1,-1};
	clean(biaoji,0);
	node str;
	str.x=dot[0];
	str.y=dot[1];
	str.direction=INF;
	str.turn_num=-1;
	queue<node> s;
	s.push(str);
	biaoji[str.x][str.y]=1;//防止自身找自身 
	while(s.size())
	{
		node now=s.front();
		for(int i=0;i<4;++i)//四个方向 0,1,2,3; 
		{
			node can;
			can.x=now.x+fx[i];
			can.y=now.y+fy[i];
			can.direction=i;
			if(now.direction==INF||(now.direction+i)%2)//起点|| 转角 
				can.turn_num=now.turn_num+1;
			else
				can.turn_num=now.turn_num;
			
			if(can.x<0||can.x>10||can.y<0||can.y>10)//超出地图 
				continue;
			if(can.turn_num>2)//转交大于2 
				continue;
			if(can.x==dot[2]&&can.y==dot[3])//符合要求的路线 
				return 1;
			if(map[can.x][can.y])//该位置有东西 
				continue;
			if(biaoji[can.x][can.y])//该位置已经走过了
				continue;
			s.push(can);
			biaoji[can.x][can.y]=1;
			
		}
		s.pop();
	}
	return 0;
	
}

int emtry(int map[10][10])
{
	for(int i=1;i<9;++i)
	{
		for(int j=1;j<9;++j)
		{
			if(map[i][j])
				return 0;
		}
	}
	return 1;
}

int main()
{
	int map[10][10];//建立一个地图 
	int dot[4];//起点0,1;终点2,3;
	char img[9]={' ','!','@','#','$','%','&','+','~'};
	clean(map,0);
	build_map(map);
	show_map(map,img);
	
	while(1)
	{
		cout<<"输入坐标x1 y1 x2 y2"<<endl; 
		input_dot(dot);
		if(judge(map,dot))
		{
			system("cls");
			cout<<"clean seccess"<<endl;
			map[dot[0]][dot[1]]=0;
			map[dot[2]][dot[3]]=0;
			show_map(map,img);
			if(emtry(map))
			{
				cout<<"winner"<<endl;
				exit(0);
			}
		}
		else
		{
			system("cls");
			cout<<"clean failure"<<endl;
			show_map(map,img);
		}
	}
	
}

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值