数独终结者Rev6附代码

经过许久的不屑努力,在数独终结者5的版本上,增加了可以输入数独的功能

输入规则
按照九宫格从左到右,从上到下的排序方式

分别将数字输入进去,输入数字后需要继续输入空格,PS空的值请输入0
不然程序没法运算出结果
每输入完一行请输入回车
如果需要修改请输入1 不需要修改请输入0 如有类似逻辑的地方请参考此输入规则

上代码

#include "pch.h"
#include <iostream>


void inputSudoku(int **p, bool jud);
void modifySudoku(int **p, bool jud);

void judgeLRN(int **c, int **cc, int **a);
void judgeMaybeA(int **am, int **c);
void fillA(int **am, int **a, int **cc);
void outputSudoku(int **a);
void outputSudokuIn(int **a);
void dealSudoku(int **ppc, int**ppc_c, int **ppa, int**ppa_m);

int main()
{
	int i, j, k;
	std::cout << "数独终结者\n";

	int maybe_a[9][9][9]; // 某个数字可能存在的值

	int c[3][9][9];   // 行列九宫格 限制条件
	int cal_c[9][9];  // 用于计数 当该单元格的被限制条件限制只能取1个数时,则将该数填入数独数组

	int flag;    //用于标记那一个数的位置



	bool jud;//用于判断输入是否需要修改
	jud = true;
	bool jud_1 = true; //用于判定是否完成了数独
	bool jud_2 = true; //用于判定是否运算次数过多而毫无进展

	int jud_i = 0; //计数循环次数,大于某一值认为当前算法有问题,无法解决数独问题,中断循环

	int a[9][9] = { {5,3,0,8,4,1,6,2,0},{9,0,0,5,0,2,8,0,0},{0,0,0,0,6,9,0,0,1},
					{0,0,0,2,0,0,0,1,0},{7,5,2,1,0,0,9,8,6},{1,4,0,7,9,0,0,5,3},
					{0,0,0,0,8,3,0,4,2},{4,0,1,6,2,7,3,9,5},{0,0,3,0,0,5,0,6,0} }; //初始数独

	//二级指针用于快速寻址

	int *pa;
	int **ppa;
	pa = &a[0][0];
	ppa = &pa;

	int *pc;
	int **ppc;
	pc = &c[0][0][0];
	ppc = &pc;

	int *pc_c;
	int **ppc_c;
	pc_c = &cal_c[0][0];
	ppc_c = &pc_c;

	int *pa_m;
	int **ppa_m;
	pa_m = &maybe_a[0][0][0];
	ppa_m = &pa_m;

	//数独输出
	inputSudoku(ppa, jud);
	modifySudoku(ppa, jud);
	outputSudokuIn(ppa);
	dealSudoku(ppc, ppc_c, ppa, ppa_m);
}


//输入数独
void inputSudoku(int **p, bool jud)
{
	int i, j;
	std::cout << "计算默认数独请输入1";
	std::cin >> jud;

	if (!jud)
	{
		for (i = 0; i < 9; i++)
		{
			std::cout << "请输入第" << i + 1 << "行\n";
			for (j = 0; j < 9; j++)
			{
				std::cin >> *(*p + i * 9 + j);
			}
		}
	}
}

//修改数独
void modifySudoku(int **p, bool jud)
{
	bool xg, xgg, xggg;//如果输入数独错误,用于标记是否需要修改的状态
	xg = true;
	xgg = true;
	xggg = true;
	int i, j;
	int xg1, xg2, xg3;
	std::cout << "如需继续修改请输入1\n";
	std::cin >> xggg;
	if (xggg)
	{
		if (xg && !jud)
		{
			while (1)
			{
				std::cout << "如需修改请输入行数和列数\n\n";
				std::cout << "请输入行数\n";
				std::cin >> xg1;
				std::cout << "请输入列数\n";
				std::cin >> xg2;
				std::cout << "请输入修改数\n";
				std::cin >> xg3;
				*(*p + 9 * xg1 + xg2) = xg3;
				for (i = 0; i < 9; i++)
				{
					std::cout << "数独如下";
					for (j = 0; j < 9; j++)
					{
						std::cout << *(*p + i * 9 + j) << " ";
					}
					std::cout << "\n";
				}
				std::cout << "如需继续修改请输入1\n";
				std::cin >> xgg;
				if (!xgg)
				{
					break;
				}
			}
		}
	}
}

//行列以及九宫格的判定
void judgeLRN(int **c, int **cc, int **a)
{
	int i, j, k;
	for (i = 0; i < 243; i++) // c
		*(*c + i) = 1;

	for (i = 0; i < 81; i++) //cal_c
		*(*cc + i) = 0;

	//这里的主要思路是行列和九宫格,分别将已有的数字标记为0
	for (i = 0; i < 9; i++)
	{
		for (int j = 0; j < 9; j++)
		{
			if (*(*a + i * 9 + j) != 0) //a[i][j]  			
			{
				//行
				*(*c + i * 9 + *(*a + i * 9 + j) - 1) = 0; //c[0][i][a[i][j] - 1]
				//列
				*(*c + j * 9 + *(*a + i * 9 + j) + 80) = 0; //c[1][j][a[i][j] - 1]
				//九个九宫格
				if (i < 3 && j < 3)
				{
					*(*c + 162 + *(*a + i * 9 + j) - 1) = 0; //c[2][0][a[i][j] - 1] = 0;
				}

				else if (i < 3 && j > 2 && j < 6)
				{
					*(*c + 171 + *(*a + i * 9 + j) - 1) = 0;
				}

				else if (i < 3 && j > 5)
				{
					*(*c + 180 + *(*a + i * 9 + j) - 1) = 0;
				}

				else if (i > 2 && i < 6 && j < 3)
				{
					*(*c + 189 + *(*a + i * 9 + j) - 1) = 0;
				}

				else if (i < 6 && i > 2 && j > 2 && j < 6)
				{
					*(*c + 198 + *(*a + i * 9 + j) - 1) = 0;
				}

				else if (i > 2 && i < 6 && j > 5)
				{
					*(*c + 207 + *(*a + i * 9 + j) - 1) = 0;
				}

				else if (i > 5 && j < 3)
				{
					*(*c + 216 + *(*a + i * 9 + j) - 1) = 0;
				}

				else if (i > 5 && j > 2 && j < 6)
				{
					*(*c + 225 + *(*a + i * 9 + j) - 1) = 0;
				}
				else if (i > 5 && j > 5)
				{
					*(*c + 234 + *(*a + i * 9 + j) - 1) = 0;
				}
			}
		}
	}
}

//每个空余格子可能取值
void judgeMaybeA(int **am, int **c)
{
	int i, j, k;

	for (i = 0; i < 729; i++) //maybe_a
		*(*am + i) = 1;

	for (i = 0; i < 9; i++)
	{
		for (j = 0; j < 9; j++)
		{
			for (k = 0; k < 9; k++)
			{
				if (*(*c + i * 9 + k) == 0) //c[0][i][k]
					*(*am + i * 81 + j * 9 + k) = 0; //maybe_a[i][j][k]

				if (*(*c + j * 9 + k + 81) == 0)
					*(*am + i * 81 + j * 9 + k) = 0;

				//九个九宫格
				if (i < 3 && j < 3 && *(*c + 162 + k) == 0)
				{
					*(*am + i * 81 + j * 9 + k) = 0;
				}

				else if (i < 3 && j > 2 && j < 6 && *(*c + 171 + k) == 0)
				{
					*(*am + i * 81 + j * 9 + k) = 0;
				}

				else if (i < 3 && j > 5 && *(*c + 180 + k) == 0)
				{
					*(*am + i * 81 + j * 9 + k) = 0;
				}

				else if (i > 2 && i < 6 && j < 3 && *(*c + 189 + k) == 0)
				{
					*(*am + i * 81 + j * 9 + k) = 0;
				}

				else if (i > 2 && i < 6 && j > 2 && j < 6 && *(*c + 198 + k) == 0)
				{
					*(*am + i * 81 + j * 9 + k) = 0;
				}

				else if (i > 2 && i < 6 && j > 5 && *(*c + 207 + k) == 0)
				{
					*(*am + i * 81 + j * 9 + k) = 0;
				}

				else if (i > 5 && j < 3 && *(*c + 216 + k) == 0)
				{
					*(*am + i * 81 + j * 9 + k) = 0;
				}

				else if (i > 5 && j > 2 && j < 6 && *(*c + 225 + k) == 0)
				{
					*(*am + i * 81 + j * 9 + k) = 0;
				}
				else if (i > 5 && j > 5 && *(*c + 234 + k) == 0)
				{
					*(*am + i * 81 + j * 9 + k) = 0;
				}
			}
		}
	}
}

//将智能有一个数字填入的空格填入数字
void fillA(int **am, int **a, int **cc)
{
	int i, j, k;
	for (i = 0; i < 81; i++) //maybe_a
		*(*cc + i) = 0;

	for (i = 0; i < 9; i++)
	{
		for (j = 0; j < 9; j++)
		{
			for (k = 0; k < 9; k++)
			{
				if (*(*am + i * 81 + j * 9 + k) != 0)
				{
					(*(*cc + i * 9 + j))++;
				}
			}
			if (*(*cc + i * 9 + j) == 1 && *(*a + i * 9 + j) == 0)
			{
				for (k = 0; k < 9; k++)
				{
					if (*(*am + i * 81 + j * 9 + k) != 0)
					{
						*(*a + i * 9 + j) = k + 1;
					}
				}
			}
		}
	}
}

//输出输入数独
void outputSudokuIn(int **a)
{
	int i, j;
	std::cout << "数独如下\n";
	for (i = 0; i < 9; i++)
	{
		for (j = 0; j < 9; j++)
		{
			std::cout << *(*a + i * 9 + j) << " ";
		}
		std::cout << "\n";
	}
}

//输出结果数独
void outputSudoku(int **a)
{
	int i, j;
	std::cout << "结果如下\n";
	for (i = 0; i < 9; i++)
	{
		for (j = 0; j < 9; j++)
		{
			std::cout << *(*a + i * 9 + j) << " ";
		}
		std::cout << "\n";
	}
}

//数独整体判断
void dealSudoku(int **ppc, int**ppc_c, int **ppa, int**ppa_m)
{
	//这里的主要思路是行列和九宫格,分别将已有的数字标记为0
	bool jud_1 = true; //用于判定是否完成了数独
	bool jud_2 = true; //用于判定是否运算次数过多而毫无进展
	int jud_i = 0; //计数循环次数,大于某一值认为当前算法有问题,无法解决数独问题,中断循环
	int i;
	while (jud_1&&jud_2)
	{

		//这里的主要思路是行列和九宫格,分别将已有的数字标记为0
		judgeLRN(ppc, ppc_c, ppa);
		judgeMaybeA(ppa_m, ppc);
		fillA(ppa_m, ppa, ppc_c);

		jud_1 = false;

		for (i = 0; i < 81; i++)
		{
			if (*(*ppa + i) == 0)
				jud_1 = true;
		}

		jud_i++;

		if (jud_i > 10000)
			jud_2 = false;
	}

	outputSudoku(ppa);
}

相对上一版本,这一版本使用了函数的调用,主函数看起来更加干净,整体函数更容易读懂,功能模块更加清晰

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值