zoukankan      html  css  js  c++  java
  • 用C++实现的解数独(Sudoku)程序

    我是一个C++初学者,控制台实现了一个解数独的小程序。

    代码如下:

    //"数独游戏"V1.0
    //李国良于2016年11月11日编写完成
    
    #include <iostream>
    #include <fstream>
    #include <string>
    #include <Windows.h>
    
    using namespace std;
    
    const int ArSize = 9;
    
    string loadFile(int arr[ArSize][ArSize]);//读取文件,返回文件名
    void printMap(int arr[ArSize][ArSize]);//显示数独
    void solve(int arr[ArSize][ArSize], int enumer[ArSize], int i, int j);//计算当前单元格的候选数
    bool solveV(int arr[ArSize][ArSize], int i, int j);//判断当前单元格是否可填
    bool lopMap(int arr[ArSize][ArSize]);//循环遍历未解单元格,调用solveV求解
    bool loopMap(int arr[ArSize][ArSize]);//暴力求解!!!
    void saveFile(int arr[ArSize][ArSize], string str);//保存文件
    
    int main()
    {
    	SetConsoleTitle("数独游戏");
    	int map[ArSize][ArSize];
    	for (auto &row : map)
    		for (auto &ival : row)
    			ival = -1;
    	string name = loadFile(map);
    	printMap(map);
    	bool surplus = lopMap(map);
    	cout << "lopMap()解答完毕" << endl;
    	printMap(map);
    	if (!surplus)
    	{
    		loopMap(map);
    		cout << "loopMap()解答完毕" << endl;
    		printMap(map);
    	}
    	saveFile(map, name);
    	cin.get();
    	cin.get();
    	return 0;
    }
    
    string loadFile(int arr[ArSize][ArSize])
    {
    	string fileName;
    	ifstream inFile;
    	cout << "请输入文件名:" << endl;
    	while (true)
    	{
    		cin >> fileName;
    		inFile.open(fileName + ".txt");
    		if (!inFile.is_open())
    		{
    			cout << "文件未能成功打开,请重新输入文件名:" << endl;
    			continue;
    		}
    		bool judg = true;
    		for (int i = 0; i < ArSize; ++i)
    		{
    			for (int j = 0; j < ArSize; ++j)
    			{
    				inFile >> arr[i][j];
    				if (arr[i][j] < 0 || arr[i][j] > 9)
    					judg = false;
    			}
    		}
    		if (judg)
    		{
    			cout << "文件"" << fileName << ".txt" << ""载入成功!" << endl;
    			inFile.close();
    			break;
    		}
    		else
    		{
    			cout << "文件内容有误,请重新输入文件名:" << endl;
    			inFile.close();
    			continue;
    		}
    	}
    	return fileName;
    }
    
    void printMap(int arr[ArSize][ArSize])
    {
    	cout << endl;
    	int num = 0;
    	for (int i = 0; i < ArSize; ++i)
    	{
    		for (int j = 0; j < ArSize; ++j)
    		{
    			cout << arr[i][j];
    			if (j != 8)
    				cout << " ";
    			if (!arr[i][j])
    				num += 1;
    		}
    		cout << endl;
    	}
    	cout << num << "剩余单元格!" << endl << endl;
    }
    
    void solve(int arr[ArSize][ArSize], int enumer[ArSize], int i, int j)
    {
    	for (int num = 0; num < ArSize; ++num)
    		enumer[num] = num + 1;
    	for (int m = 0; m < ArSize; ++m)
    	{
    		if (arr[m][j])
    			enumer[arr[m][j] - 1] = 0;
    	}
    	for (int n = 0; n < ArSize; ++n)
    	{
    		if (arr[i][n])
    			enumer[arr[i][n] - 1] = 0;
    	}
    	for (int m = i / 3 * 3; m < i / 3 * 3 + 3; ++m)
    	{
    		for (int n = j / 3 * 3; n < j / 3 * 3 + 3; ++n)
    		{
    			if (arr[m][n])
    				enumer[arr[m][n] - 1] = 0;
    		}
    	}
    }
    
    bool solveV(int arr[ArSize][ArSize], int i, int j)
    {
    	int enumeration[ArSize];
    	int ation[ArSize];
    	solve(arr, enumeration, i, j);
    	int x = 0;
    	int y;
    	for (int i = 0; i < ArSize; ++i)
    	{
    		if (enumeration[i])
    		{
    			y = i;
    			x += 1;
    		}
    	}
    	if (x == 1)
    	{
    		arr[i][j] = enumeration[y];
    		return true;
    	}
    	else
    	{
    		for (y = 0; y < ArSize; ++y)
    		{
    			if (enumeration[y])
    			{
    				for (int m = 0; m < ArSize; ++m)
    				{
    					if (arr[m][j] == 0 && m != i)
    					{
    						solve(arr, ation, m, j);
    						if (ation[y])
    						{
    							break;
    						}
    					}
    				}
    				if (!ation[y])
    				{
    					arr[i][j] = enumeration[y];
    					return true;
    				}
    				for (int n = 0; n < ArSize; ++n)
    				{
    					if (arr[i][n] == 0 && n != j)
    					{
    						solve(arr, ation, i, n);
    						if (ation[y])
    						{
    							break;
    						}
    					}
    				}
    				if (!ation[y])
    				{
    					arr[i][j] = enumeration[y];
    					return true;
    				}
    				bool judge = false;
    				for (int m = i / 3 * 3; m < i / 3 * 3 + 3; ++m)
    				{
    					for (int n = j / 3 * 3; n < j / 3 * 3 + 3; ++n)
    					{
    						if (arr[m][n] == 0 && (m != i || n != j))
    						{
    							solve(arr, ation, m, n);
    							if (ation[y])
    							{
    								goto label;
    							}
    						}
    					}
    				}
    				label:
    				if (!ation[y])
    				{
    					arr[i][j] = enumeration[y];
    					return true;
    				}
    			}
    		}
    	}
    	return false;
    }
    
    bool lopMap(int arr[ArSize][ArSize])
    {
    	int num = 0;
    	while (true)
    	{
    		int number = 0;
    		for (int i = 0; i < ArSize; ++i)
    		{
    			for (int j = 0; j < ArSize; ++j)
    			{
    				if (!arr[i][j])
    				{
    					if (!solveV(arr, i, j))
    					{
    						number += 1;
    					}
    				}
    			}
    		}
    		if (!number || num == number)
    		{
    			num = number;
    			break;
    		}
    		num = number;
    	}
    	return num == 0 ? true : false;
    }
    
    bool loopMap(int arr[ArSize][ArSize])
    {
    	for (int i = 0; i < ArSize; ++i)
    	{
    		for (int j = 0; j < ArSize; ++j)
    		{
    			if (!arr[i][j])
    			{
    				int enumer[ArSize];
    				solve(arr, enumer, i, j);
    				for (int n = 0; n < ArSize; ++n)
    				{
    					if (enumer[n])
    					{
    						int maps[ArSize][ArSize];
    						for (int x = 0; x < ArSize; ++x)
    						{
    							for (int y = 0; y < ArSize; ++y)
    							{
    								maps[x][y] = arr[x][y];
    							}
    						}
    						maps[i][j] = enumer[n];
    						if (lopMap(maps))
    						{
    							for (int x = 0; x < ArSize; ++x)
    							{
    								for (int y = 0; y < ArSize; ++y)
    								{
    									arr[x][y] = maps[x][y];
    								}
    							}
    							return true;
    						}
    						else
    						{
    							bool judge = true;
    							for (int i = 0; i < ArSize; ++i)
    							{
    								for (int j = 0; j < ArSize; ++j)
    								{
    									if (!maps[i][j])
    									{
    										int num = 0;
    										int enumerat[ArSize];
    										solve(maps, enumerat, i, j);
    										for (auto n : enumerat)
    										{
    											num += n;
    										}
    										if (!num)
    										{
    											judge = false;
    										}
    									}
    								}
    							}
    							if (judge)
    							{
    								if (loopMap(maps))
    								{
    									for (int x = 0; x < ArSize; ++x)
    									{
    										for (int y = 0; y < ArSize; ++y)
    										{
    											arr[x][y] = maps[x][y];
    										}
    									}
    									return true;
    								}
    							}
    						}
    					}
    				}
    				return false;
    			}
    		}
    	}
    }
    
    void saveFile(int arr[ArSize][ArSize], string str)
    {
    	ofstream outFile;
    	outFile.open(str + "answer.txt");
    	if (!outFile.is_open())
    	{
    		cout << "文件保存失败!" << endl;
    		return;
    	}
    	for (int i = 0; i < ArSize; ++i)
    	{
    		for (int j = 0; j < ArSize; ++j)
    		{
    			outFile << arr[i][j];
    			if (j != 8)
    				outFile << " ";
    		}
    		outFile << endl;
    	}
    	cout << "文件"" << str << "answer.txt" << ""保存成功!" << endl;
    	outFile.close();
    }
    

    loopMap()函数使用了递归,递归函数写的非常伤脑筋,感觉这个函数写的不好,目前还没找到改进的办法,姑且能用。

  • 相关阅读:
    Boost智能指针——shared_ptr
    Boost.asio的简单使用(timer,thread,io_service类)
    ACE线程管理机制
    利用boost::asio实现一个简单的服务器框架
    【转载】boost::lexical_cast 的使用
    BOOST 实用手册(摘录自校友博客)
    ACE的安装
    Microsoft SQL Server 2000 中的数据转换服务 (DTS)
    将 DTS 用于业务智能解决方案的最佳实践
    [转]理解“Future”
  • 原文地址:https://www.cnblogs.com/yonggandefeng/p/6198222.html
Copyright © 2011-2022 走看看