现在的位置: 首页 > 操作系统 > 正文

用C++实现的解数独(Sudoku)程序

2020年02月10日 操作系统 ⁄ 共 4157字 ⁄ 字号 评论关闭

我是一个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()函数使用了递归,递归函数写的非常伤脑筋,感觉这个函数写的不好,目前还没找到改进的办法,姑且能用。

本文永久更新链接地址:http://www.xuebuyuan.com/Linux/2017-01/139478.htm

以上就上有关用C++实现的解数独(Sudoku)程序的全部内容,学步园全面介绍编程技术、操作系统、数据库、web前端技术等内容。

抱歉!评论已关闭.