深度遍历破解数独游戏

#include <iostream>
#define N 9
using namespace std;

//判断该位置放置的数据是否符合规则
bool panduan(int (*fang)[N],int row_now,int col_now,int count)
{
	//打印行列
	//cout << row_now << "\t" << col_now << endl;
	//扫描本行是否有重复数据
	int i,j;
	for(i = 0;i < N;i++)
	{
		if( fang[row_now][i] == count && i != col_now)
		{
			return false;
		}
	}
	//扫描本列是否有重复数据
	for(i = 0;i < N;i++)
	{
		if( fang[i][col_now] == count && i != row_now)
		{
			return false;
		}
	}
	//扫描本方块区域之内是否有重复数据
	//扫描(0,0)区域
	if(row_now < 3 && col_now < 3)
	{
		for(i = 0;i <= 2;i++)
		{
			for(int j = 0;j <= 2;j++)
			{
				//如果有重复数据 判断是不是自身
				if( fang[i][j] == count )
				{
					//如果不是自身  就返回false
					if( i != row_now && j != col_now)
						return false;
				}
			}
		}
	}
	//扫描(0,1)区域
	else if( row_now < 3 && col_now < 6 && col_now > 2)
	{
		
		for(i = 0;i <= 2;i++)
		{
			for(j = 3;j <= 5;j++)
			{
				//如果有重复数据 判断是不是自身
				if( fang[i][j] == count )
				{
					//如果不是自身  就返回false
					if( i != row_now && j != col_now)
						return false;
				}
			}
		}
		
	}
	//扫描(0,2)区域
	else if( row_now < 3 && col_now > 5)
	{
		for(i = 0;i <= 2;i++)
		{
			for(j = 6;j <= 8;j++)
			{
				//如果有重复数据 判断是不是自身
				if( fang[i][j] == count )
				{
					//如果不是自身  就返回false
					if( i != row_now && j != col_now)
						return false;
				}
			}
		}
	}
	
	
	//扫描(1,0)区域
	else if(row_now > 2 && row_now < 6 && col_now < 3)
	{
		
		for(i = 3;i <= 5;i++)
		{
			for(j = 0;j <= 2;j++)
			{
				//如果有重复数据 判断是不是自身
				if( fang[i][j] == count )
				{
					//如果不是自身  就返回false
					if( i != row_now && j != col_now)
						return false;
				}
			}
		}
		
	}
	//扫描(1,1)区域
	else if(row_now > 2 && row_now < 6 && col_now <6 && col_now > 2)
	{
		for(i = 3;i <= 5;i++)
		{
			for(j = 3;j <= 5;j++)
			{
				//如果有重复数据 判断是不是自身
				if( fang[i][j] == count )
				{
					//如果不是自身  就返回false
					if( i != row_now && j != col_now)
						return false;
				}
			}
		}
	}
	//扫描(1,2)区域
	else if(row_now > 2 && row_now < 6 && col_now > 5)
	{
		
		for(i = 3;i <= 5;i++)
		{
			for(j = 6;j <= 8;j++)
			{
				//如果有重复数据 判断是不是自身
				if( fang[i][j] == count )
				{
					//如果不是自身  就返回false
					if( i != row_now && j != col_now)
						return false;
				}
			}
		}
		
	}
	
	
	//扫描(2,0)区域
	else if(row_now > 5 && col_now < 3 )
	{
		
		for(i = 6;i <= 8;i++)
		{
			for(j = 0;j <= 2;j++)
			{
				//如果有重复数据 判断是不是自身
				if( fang[i][j] == count )
				{
					//如果不是自身  就返回false
					if( i != row_now && j != col_now)
						return false;
				}
			}
		}
		
	}
	//扫描(2,1)区域
	else if(row_now > 5 && col_now > 2 && col_now < 6)
	{
		
		for(i = 6;i <= 8;i++)
		{
			for(j = 3;j <= 5;j++)
			{
				//如果有重复数据 判断是不是自身
				if( fang[i][j] == count )
				{
					//如果不是自身  就返回false
					if( i != row_now && j != col_now)
						return false;
				}
			}
		}
		
	}
	//扫描(2,2)区域
	else if(row_now > 5 && col_now > 5)
	{
		for(i = 6;i <= 8;i++)
		{
			for(j = 6;j <= 8;j++)
			{
				//如果有重复数据 判断是不是自身
				if( fang[i][j] == count )
				{
					//如果不是自身  就返回false
					if( i != row_now && j != col_now)
						return false;
				}
			}
		}
	}
	
	return true;
}

int count = 0;

//计算程序
void shudu(int (*fang)[N],int row_now,int col_now)
{

	//初始化数据副本
	int fang2[N][N];
	int i,j;
	for(i = 0;i < N;i++)
	{
		for(j = 0;j < N;j++)
		{
			fang2[i][j] = fang[i][j];
		}
	}
	//设计出口 如果当前行达到N 便说明递归完毕 可以输出
	if(row_now == N )// && col_now == N - 1
	{
		cout << "方案" << ++count << ":" << endl;
		//输出
		for(i = 0;i < N;i++)
		{
			for(j = 0;j < N;j++)
			{
				cout << fang2[i][j];
			}
			cout << endl;
		}
		cout << endl << endl;
	}
	else
	{
		//如果本位置不为0 说明本位置不需要放置数据 则进行下一列的判断
		if(fang2[row_now][col_now] != 0)
		{
			//如果尚未到达行尾 便进行下一列
			if(col_now < N - 1)
			{
				shudu(fang2,row_now,col_now+1);
			}
				
			//如果已经到达了行尾 便进行换行
			else
			{
				shudu(fang2,row_now+1,0);
			}
		}
		
		//如果本位置为0 说明该位置需要放置数据
		else
		{
			//放置的数据为1~9	进列逐一判断填放
			for(int count = 1;count <= 9;count++)
			{
				//清空本位置数据 即回复为0	以便下一次放置数据
				fang2[row_now][col_now] = 0;

				//该位置放置该数据如果符合规则
				if ( panduan(fang2,row_now,col_now,count) )
				{
					//放置该数据在本位置
					fang2[row_now][col_now] = count;
					
					//该位置放置合法数据之后 进行下一个位置的递归判断
					
					//如果尚未到达行尾 便进行下一列
					if(col_now < N - 1)
					{
						shudu(fang2,row_now,col_now+1);
					}
					//如果已经到达了行尾 便进行换行
					else
					{
						shudu(fang2,row_now+1,0);
					}
				}
			}	
		}
	}
}


int main()
{
	//打印游戏规则
	cout << "游戏规则:需要根据9×9盘面上的已知数字,推理出所有剩余空格的数字,并满足每一行、每一列、每一个同色九宫内的数字均含1-9,不重复" << endl;
	cout << "每行输入9个数字 共输入9行 需要空出的方格位置用0表示" << endl;
	int fang[N][N];

	char fang_char[N][N];
	int i,j;
	//初始化数独
	for(i = 0;i < N;i++)
	{
		for(j = 0;j < N;j++)
		{
			cin >> fang_char[i][j];
			fang[i][j] = ((int)fang_char[i][j])-48;
		}
	}
	
	cout << endl << endl;

	//进入计算程序
	int row_now = 0,col_now = 0;
	count = 0;
	shudu(fang,row_now,col_now);
	cout << "以上为可行解!" << endl;
	system("pause");
	return 0;
}
posted @ 2017-08-12 09:22  春雨冰河  阅读(278)  评论(0编辑  收藏  举报