北大 算法基础 Sudoku(数独)游戏

sudoku练习代码

#include<iostream> 
#include<vector>
using namespace std;

int rowFlags[9][10];//rowFlags[i][num]数字num在行i中存在的标记
int colFlags[9][10];//colFlags[j][num]数字num在列j中存在的标记
int blockFlags[9][10];//同上,数字在块里的标记
int plateNum[9][9] = {
	{1,0,3,0,0,0,5,0,9},
	{0,0,2,1,0,9,4,0,0},
	{0,0,0,7,0,4,0,0,0},
	{3,0,0,5,0,2,0,0,6},
	{0,6,0,0,0,0,0,5,0},
	{7,0,0,8,0,3,0,0,4},
	{0,0,0,4,0,1,0,0,0},
	{0,0,9,2,0,5,8,0,0},
	{8,0,4,0,0,0,1,0,7}
};

struct Pos
{
	int r, c;
	Pos(int rr, int cc) :r(rr),c(cc){}
};
vector<Pos> blankPos;//空位置
int boardNum[9][9];//数字板

int getBlockNo(int r, int c) {//计算块号
	int rr = r / 3;
	int cc = c / 3;
	return rr* 3 + cc;
}

void setAllFlags(int r, int c, int num, int f) {//设置标记
	int b = getBlockNo(r, c);
	rowFlags[r][num] = f;
	colFlags[c][num] = f;
	blockFlags[b][num] = f;
}

bool Dfs(int n) {
	if (n < 0) return true;//终止条件,所有空位填满
	int rr, cc, bb;
	rr = blankPos[n].r;//行
	cc = blankPos[n].c;//列
	bb = getBlockNo(rr,cc);//块
	for (int i = 1; i <= 9; i++)
	{		
		if (!rowFlags[rr][i] && !colFlags[cc][i] && !blockFlags[bb][i])
		{
			setAllFlags(rr, cc, i, 1);//符合条件后标记			
			if (Dfs(n-1)) {
				boardNum[rr][cc] = i;//n-1之后全都完成了,把i放入对应空位
				return true;
			}
			else
				setAllFlags(rr, cc, i, 0);//没有成功,标记删除
		}
	}
	return false;
}

int main() {
	memset(rowFlags, 0, sizeof(rowFlags));
	memset(colFlags, 0, sizeof(colFlags));
	memset(blockFlags, 0, sizeof(blockFlags));
	blankPos.clear();
	memset(boardNum, 0, sizeof(boardNum));

	//cout << "输入9*9初始矩阵:" << endl;
	int n;
	for(int i=0;i<9;i++)//输入
		for (int j = 0; j <9; j++) {
			/*cin >> boardNum[i][j];
			n = boardNum[i][j];*/
			boardNum[i][j] = n = plateNum[i][j];//为了校验方便,用了上面的矩阵plateNum的数据
			if (n) {//非0
				setAllFlags(i, j, n, 1);//标记
			}
			else
				blankPos.push_back(Pos(i,j));//未用位置记录下来
		}
	if (Dfs(blankPos.size()-1)) {//填空成功输出数字板
		cout << endl;
		for (int i = 0; i < 9; i++) {
			{
				for (int j = 0; j < 9; j++)
					cout << boardNum[i][j] << " ";
			}
			cout << endl;
		}
	}
	else
		cout << "没有找到合适的结果" << endl;

	return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值