算法练习---数独游戏

#include "stdafx.h"
#include <iostream>
#include <time.h>
#include <vector>
using namespace std;
typedef unsigned char u8;
typedef struct Point{
	int x = 0;
	int y = 0;
};
class SudoMatric{
public:
	u8 sudo_data[10][10];//没有数字,表示为0
	void findPosiableValue(u8 i, u8 j, vector<u8>* v);
	void showSudo();
	void captureData();
	bool huishuoSearch(vector<Point*>* point_buff);
	void writeNumber(vector<u8>* v);
	bool isNullValue();
};

bool SudoMatric::huishuoSearch(vector<Point*>* point_buff)//回朔法给数独填数
{
	vector<u8> v;
	//vector<Point*> point_buff;
	//char error=0;
	bool flag = 1;
	while (isNullValue() != 0 && flag == 1){//先把所有唯一值填完
		flag = 0;
		for (int i = 1; i < 10; i++){
			for (int j = 1; j < 10; j++){
				if (sudo_data[i][j] == 0){//找出该点可能值,如果唯一,则先赋值
					findPosiableValue(i, j, &v);
					if (v.size() == 0) {
						v.clear();
						return 1;
						
					}
					else if (v.size() == 1){
						flag = 1;
						sudo_data[i][j] = v.front();
						Point* pt=new Point;
						pt->x = i;
						pt->y = j;
						point_buff->push_back(pt);
						v.clear();
					}
					else{
						v.clear();
					}
				}
			}
		}
	}
	//cout << "##########################" << endl;
	//showSudo();
	if (isNullValue() != 0){
		for (int i = 1; i < 10; i++){
			for (int j = 1; j < 10; j++){
				if (sudo_data[i][j] == 0){//找出该点可能值
					findPosiableValue(i, j, &v);
					if (v.size() == 0) {
						return 1;
					}

					for (int k = 0; k < v.size(); k++){
						sudo_data[i][j] = v[k];
						bool f = huishuoSearch(point_buff);
						if (f != 0){//搜索失败
							for (int m = 0; m < point_buff->size(); m++){
								Point* p = (*point_buff)[m];
								sudo_data[p->x][p->y] = 0;
								delete p;
							}
							sudo_data[i][j] = 0;
							point_buff->clear();
						}
						else{//搜索成功
							return 0;
						}
					}
					v.clear();
					return 1;//k次搜索都失败,返回1
				}
			}
		}
	}
	else{
		return 0;
	}
	
}
bool SudoMatric::isNullValue()//检测是否全部填完
{
	for (int i = 1; i < 10; i++){
		for (int j = 1; j < 10; j++){
			if (sudo_data[i][j] == 0)
				return 1;
		}
	}
	return 0;
}
void SudoMatric::writeNumber(vector<u8>* v)//写到一半,发现写错了,应该整个函数递归
{
	bool error = false;
	bool flag = 1;
	while (isNullValue() != 0 && flag == 1){//先把所有唯一值填完
		flag = 0;
		for (int i = 1; i < 10; i++){
			for (int j = 1; j < 10; j++){
				if (sudo_data[i][j] == 0){//找出该点可能值,如果唯一,则先赋值
					findPosiableValue(i, j, v);
					if (v->size() == 0) {
						error = true;
						v->clear();
					}
					else if (v->size() == 1){
						flag = 1;
						sudo_data[i][j] = v->front();
						v->clear();
					}
					else{
						v->clear();
					}
				}
			}
		}
	}
	//对所有非唯一值进行回朔填写
	if (isNullValue() != 0){
		
	}
	
}
void SudoMatric::showSudo()//显示
{
	char buff[5];
	for (int i = 1; i < 10; i++){
		for (int j = 1; j < 10; j++){
			_itoa_s(sudo_data[i][j], buff, 10);
				cout << buff << ' ';
			if (j == 3 || j == 6) cout << "| ";
		}
		cout << endl;
		if (i == 3 || i == 6) cout << "---------------------" << endl;
	}
}
void SudoMatric::captureData()//捕获数据,可以手动输入,也可以初始化赋值
{
	//手动输入采集
	/*for (int i = 1; i < 10; i++){
		for (int j = 1; j < 10; j++){
			cin >> sudo_data[i][j];
		}
	}*/ 
	//固定数组
	//可以通过找唯一值填完
	/*u8 data[9][9] = { { 0, 6, 0, 5, 9, 3, 0, 0, 0 },
	{ 9, 0, 1, 0, 0, 0, 5, 0, 0 },
	{ 0, 3, 0, 4, 0, 0, 0, 9, 0 },
	{ 1, 0, 8, 0, 2, 0, 0, 0, 4 },
	{ 4, 0, 0, 3, 0, 9, 0, 0, 1 },
	{ 2, 0, 0, 0, 1, 0, 6, 0, 9 },
	{ 0, 8, 0, 0, 0, 6, 0, 2, 0 },
	{ 0, 0, 4, 0, 0, 0, 8, 0, 7 },
	{ 0, 0, 0, 7, 8, 5, 0, 1, 0 }
	};*/
	u8 data[9][9] = { { 9, 2, 3, 0, 0, 0, 0, 0, 0 },
					  { 5, 4, 1, 0, 0, 0, 0, 0, 0 },
					  { 6, 7, 8, 0, 0, 0, 0, 0, 0 },
					  { 1, 0, 5, 0, 0, 0, 0, 0, 0 },
					  { 0, 0, 6, 0, 0, 0, 0, 0, 1 },
					  { 0, 0, 7, 0, 1, 0, 0, 0, 0 },
					  { 0, 0, 9, 0, 0, 0, 0, 0, 0 },
					  { 0, 0, 2, 0, 0, 0, 0, 0, 0 },
					  { 0, 0, 4, 0, 0, 0, 0, 1, 0 }
					};
	for (int i = 1; i < 10; i++){
		for (int j = 1; j < 10; j++){
			sudo_data[i][j] = data[i-1][j-1];
		}
	}
}
void SudoMatric::findPosiableValue(u8 i, u8 j,vector<u8>* v)//找出i,j单元格的可能值,1表示可能,0表示不可能
{
	u8 result = 0;
	u8 num_p[10];
	u8 conflict[10];
	if (i<1 || i>9 || j<1 || j>9) return;
	if (sudo_data[i][j] != 0){
		v->push_back(sudo_data[i][j]);
		return;
	}
	memset(num_p, 1, 10);//9个数都有可能
	memset(conflict, 1, 10);
	for (int m= 1; m < 10; m++){//行 搜索
		if (sudo_data[i][m] != 0 && num_p[sudo_data[i][m]]!=0){
			num_p[sudo_data[i][m]] = 0;
		}
		if (sudo_data[i][m] != 0){
			if (conflict[sudo_data[i][m]] == 0){
				v->clear();
				return;
			}
			else{
				conflict[sudo_data[i][m]] = 0;
			}		
		}
		/*else if (sudo_data[i][m] != 0 && num_p[sudo_data[i][m]] == 0){
			v->clear();
			return;
		}*/
	}
	memset(conflict, 1, 10);
	for (int m = 1; m < 10; m++){//列 搜索
		if (sudo_data[m][j] != 0 && num_p[sudo_data[m][j]]!=0){
			num_p[sudo_data[m][j]] = 0;
		}
		if (sudo_data[m][j] != 0){
			if (conflict[sudo_data[m][j]] == 0){
				v->clear();
				return;
			}
			else{
				conflict[sudo_data[m][j]] = 0;
			}
		}
		/*else if (sudo_data[m][j] != 0 && num_p[sudo_data[m][j]] == 0){
			v->clear();
			return;
		}*/
	}
	int x = ((i - 1) / 3) * 3 + 1;
	int y = ((j - 1) / 3) * 3 + 1;
	memset(conflict, 1, 10);
	for (int m = 0; m < 3; m++){//3*3 搜索
		for (int n = 0; n < 3; n++){
			if (sudo_data[x + m][y + n] != 0 && num_p[sudo_data[x + m][y + n]] != 0)
				num_p[sudo_data[x + m][y + n]] = 0;
			if (sudo_data[x + m][y + n] != 0){
				if (conflict[sudo_data[x + m][y + n]] == 0){
					v->clear();
					return;
				}
				else{
					conflict[sudo_data[x + m][y + n]] = 0;
				}
			}
			/*else if (sudo_data[x + m][y + n] != 0 && num_p[sudo_data[x + m][y + n]] == 0){
				v->clear();
				return;
			}*/
		}
	}
	for (int m = 1; m < 10; m++){
		if (num_p[m] == 1){
			v->push_back(m);
		}
	}

}
int _tmain(int argc, _TCHAR* argv[])
{
	SudoMatric sudo;
	vector<Point*> pv;
	vector<u8>* vec=new vector<u8>;
	bool r;
	sudo.captureData();
	sudo.showSudo();
	
	
	clock_t start_time = clock();
	{
		r = sudo.huishuoSearch(&pv);//r非0表示无解
	}
	clock_t end_time = clock();

	cout << "##########################" << endl;
	sudo.showSudo();

	cout << "Running time is: " << static_cast<double>(end_time - start_time) / CLOCKS_PER_SEC * 1000 << "ms" << endl;//输出运行时间
	
	

	return r;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值