用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()函数使用了递归,递归函数写的非常伤脑筋,感觉这个函数写的不好,目前还没找到改进的办法,姑且能用。
用C++实现的解数独(Sudoku)程序的更多相关文章
- [Swift]LeetCode37. 解数独 | Sudoku Solver
Write a program to solve a Sudoku puzzle by filling the empty cells. A sudoku solution must satisfy ...
- Leetcode之回溯法专题-37. 解数独(Sudoku Solver)
Leetcode之回溯法专题-37. 解数独(Sudoku Solver) 编写一个程序,通过已填充的空格来解决数独问题. 一个数独的解法需遵循如下规则: 数字 1-9 在每一行只能出现一次.数字 1 ...
- 【原创】一个基于简单剪枝的DFS解数独程序
问题来源:leetCode Sudoku Solver Write a program to solve aSudoku puzzle by filling the empty cells. Empt ...
- [leetcode]37. Sudoku Solver 解数独
Write a program to solve a Sudoku puzzle by filling the empty cells. A sudoku solution must satisfy ...
- [LeetCode] Sudoku Solver 解数独,递归,回溯
Write a program to solve a Sudoku puzzle by filling the empty cells. Empty cells are indicated by th ...
- 解数独(Python)
0.目录 1.介绍 2.一些通用函数 3.全局变量(宏变量) 4.数独预处理(约束传播) 5.解数独(深度优先搜索+最小代价优先) 6.主函数 7.总代码 1.介绍 数独是一个非常有趣味性的智力游戏, ...
- SudokuSolver 1.0:用C++实现的数独解题程序 【二】
本篇是 SudokuSolver 1.0:用C++实现的数独解题程序 [一] 的续篇. CQuizDealer::loadQuiz 接口实现 1 CQuizDealer* CQuizDealer::s ...
- 用C++实现的数独解题程序 SudokuSolver 2.1 及实例分析
SudokuSolver 2.1 程序实现 在 2.0 版的基础上,2.1 版在输出信息上做了一些改进,并增加了 runtil <steps> 命令,方便做实例分析. CQuizDeale ...
- 用C++实现的数独解题程序 SudokuSolver 2.4 及实例分析
SudokuSolver 2.4 程序实现 本次版本实现了 用C++实现的数独解题程序 SudokuSolver 2.3 及实例分析 里发现的第三个不完全收缩 grp 算法 thirdGreenWor ...
随机推荐
- 关于ACM的总结
看了不少大神的退役帖,今天终于要本弱装一波逼祭奠一下我关于ACM的回忆. 从大二上开始接触到大三下结束,接近两年的时间,对于大神们来说两年的确算不上时间,然而对于本弱来说就是大学的一半时光.大一的懵懂 ...
- ELKStack-使用消息队列扩展(十)
ELKStack-使用消息队列扩展 官方文档:https://www.elastic.co/guide/en/logstash/5.x/deploying-and-scaling.html 流程图 流 ...
- 逆向工程学习第二天--动手开发自己的第一个shellcode
一个简单的c语言添加windows管理员账号的小程序,之前在渗透的时候经常用到,现在拿它来做自己的第一个shellcode. C代码: #pragma comment(lib, "netap ...
- Kinect之彩色图像数据
彩色图像很有用,很有用!!说到图像识别,未来肯定是个大方向!在机器人视觉和一些智能识别在应用很广,而获取下来的数据再加上Opencv就能做出很多很好玩很有趣的功能.这个以后等我进一步成长后再回来慢慢记 ...
- [Android]学习笔记Activity_001
操作button的说明 设置button的ID: android:id="@+id/button" 设置button的点击事件 findViewById(R.id.button). ...
- 学习MySQL之数据类型(四)
一. 整数类型: 整数类型 占用字节 最小值 最大值 TINYINT 1 有符号 -128 无符号0 有符号127 无符号255 SMALLINT 2 有符号-3 2768 无符号0 有符号3 2 ...
- JavaScript闭包浅谈
------------------- 作者:willingtolove: 本文链接:http://www.cnblogs.com/willingtolove/p/4745889.html 1. 变量 ...
- jcFeather For Arnold
jcFeather 现在可以支持Arnold了,可以用Arnold来贴图方式渲染jcFeather的刷出的多边形羽毛. jcFeather 自带笔刷刷羽毛多边形,再配上一个Arnold shader ...
- Block formatting context(块级格式化上下文)
今天看到豆瓣面试官的一篇文章,讲到关于CSS中的一个知识点:Block formatting context ,感觉这个确实挺有用,同时我也挺赞同作者的一些观点的,这里就不展开谈我的感受了, 此文只 ...
- C/C++头文件使用 #ifndef #define #endif 的原因
背景 在编译的时候,出现"redefine"的错误,最后检查才发现对应的头文件没有写正确的预编译信息: #ifndef _HeadFileName_H #define _HeadF ...