1. 程式人生 > >基於轉角數為基準的廣度優先搜尋(樣例:連連看)

基於轉角數為基準的廣度優先搜尋(樣例:連連看)

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);
		}
	}
	
}