数独生成以及解数独

数独

昨天给数独游戏这题出个数据,看了看网上代码有点少,所以就自己操作了一下(可能有地方操作不到位,望见谅!代码功底不是很好!
废话不多上那就直接上代码了!

生成代码

  • 代码有些地方都加了注释,生成速度还是蛮快的,
  • 原本rand的想使用C++的mt19937,可是不太会用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
#include <bits/stdc++.h>
using namespace std;
char mp[9][9];
int flag = 0;
//检查函数
bool check(int x,int y,char k){
//检查行
for(int i = 0 ; i < 9 ; i ++){
if(mp[x][i] == k)
return false;
}
//检查列
for(int i = 0 ; i < 9 ; i ++){
if(mp[i][y] == k)
return false;
}
//检查九宫格
for(int i = x / 3 * 3 ; i < x / 3 * 3 + 3 ; i ++){
for(int j = y / 3 * 3 ; j < y / 3 * 3 + 3 ; j ++){
if(mp[i][j] == k)
return false;
}
}
return true;
}
//搜索函数
bool dfs(){
for(int i = 0 ; i < 9 ; i ++){
for(int j = 0 ; j < 9 ; j ++){
if(mp[i][j] != '?')
continue;
else{
for(char k = '1' ; k <= '9' ; k ++){
if(check(i,j,k)){
mp[i][j] = k;
if(dfs())
return true;
else
mp[i][j] = '?';
}
}
return false;
}
}
}
return true;
}


class cShuDu {
static const int MAXN = 15;
bool vis[MAXN][MAXN][MAXN]{}; // 标记每个3x3里出现了哪些数字
bool vis_x[MAXN][MAXN]{}; // 标记行里出现了哪些数字
bool vis_y[MAXN][MAXN]{}; // 标记列里出现了哪些数字
char cmap[MAXN * MAXN]{}; // 地图
int num{}; // 需要生成的个数
int sum[MAXN]{};

vector<int> randVe; // 随机1-9 顺序打乱
vector<vector<char> > mapVe; // 存放地图

void randNum9() {

for(int i = 1; i <= 222; i++){
int l = rand() % 9, r = rand() % 9;
// cout << l << " " << r << endl;
swap(randVe[l], randVe[r]);
}
// cout << "-------------------------------" << endl;
// for(auto i : randVe) {
// cout << i << " ";
// }
// cout << endl;
// cout << "-------------------------------" << endl;
}

void print(int now) {
for(int i = 1; i <= 81; i++){
mapVe[now].push_back(cmap[i]);
}
}

bool check(int xx, int yy, int val) {
return !(vis[(xx + 2) / 3][(yy + 2) / 3][val] || vis_x[xx][val] || vis_y[yy][val] || sum[val] >= 9);
}

void dfs(int now, int cnt) {
if(num == 0) return ;
if(now == 82) {
num--;
print(cnt - 1);
return ;
}
randNum9(); //打乱1-9
for(auto j : randVe) {
int xx = (now + 8) / 9;
int yy = (now - 1) % 9 + 1;
if(check(xx, yy, j)) {
vis[(xx + 2) / 3][(yy + 2) / 3][j] = vis_x[xx][j] = vis_y[yy][j] = true;
cmap[now] = char ('0' + j);
sum[j]++;
dfs(now + 1, cnt);
if(num == 0) return ;
sum[j]--;
vis[(xx + 2) / 3][(yy + 2) / 3][j] = vis_x[xx][j] = vis_y[yy][j] = false;
cmap[now] = '\0';
}
}
}

public:
void init() {
memset(vis, false, sizeof(vis));
memset(vis_x, false, sizeof(vis_x));
memset(vis_y, false, sizeof(vis_y));
memset(cmap, '\0', sizeof(cmap));
memset(sum, 0, sizeof(sum));
randVe.clear();
for(int i = 1; i <= 9; i++) randVe.push_back(i);
}

vector<vector<char> > getShuDu(int _num) {
mapVe.clear();
mapVe.resize(_num + 5);
for(int i = 1; i <= _num; i++){
init();
num = 1;
dfs(1, i);
}
return mapVe;
}
};
int main()
{
ios::sync_with_stdio(false);
// ifstream fileIn;
ofstream fileIn, fileOut;
srand(time(0));
for(int i = 1; i <= 20; i++){
int num = rand() % 6666 + 5555;
// int num = 1;
cShuDu tmp;
vector<vector<char> > ve = tmp.getShuDu(num);
// 输出 in
fileIn.open("data" + to_string(i) + ".in", ios::out);
for(int j = 0; j < num; j++){
int now = 0;
cout << "*********************" << endl;
int maxn = 80; // 最大问号数
for(auto &t : ve[j]) {
now++;
if(now % 9 != 1) {
fileIn << " ";
cout << " ";
}
if((rand() + now) % 5 == 0 && maxn > 0) {
t = '?';
maxn--;
}
fileIn << t;
cout << t;
if(now % 9 == 0) {
fileIn << endl;
cout << endl;
}
}
cout << "*********************" << endl;
}
fileIn.close();

// 输出out
fileOut.open("data" + to_string(i) + ".out", ios::out);
for(int j = 0; j < num; j++) {
int now = 0;
cout << "*********************" << endl;
for(auto t : ve[j]) {
now++;
mp[(now - 1) / 9][(now - 1) % 9] = t;
}
dfs();
for(int x = 0; x < 9; x++){
for(int y = 0; y < 9; y++){
if(y != 0) {
cout << " ";
fileOut << " ";
}
fileOut << mp[x][y];
cout << mp[x][y];
}
fileOut << endl;
cout << endl;
}
cout << "*********************" << endl;
if(j != num - 1) {
fileOut << endl;
cout << endl;
}
}
fileOut.close();
}

return 0;
}

HUSTOJ的spj

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include <bits/stdc++.h>
using namespace std;
char user_map[25][25];
char oj_map[25][25];
bool xx[25][25], yy[25][25], vis[25][25][25];
int main(int argc, char* argv[]) {

FILE * f_in=fopen(argv[1],"r");//测试输入
FILE * f_out=fopen(argv[2],"r");//测试输出
FILE * f_user=fopen(argv[3],"r");//用户输出
int ret=0; //AC=0,WA=1


/*****spj代码区域*******/
while(fgets(oj_map[1], 25, f_in) != NULL) {
memset(xx, false, sizeof(xx));
memset(yy, false, sizeof(yy));
memset(vis, false, sizeof(vis));
for(int i = 2; i <= 9; i++){
fgets(oj_map[i], 25, f_in);
}
for(int i = 1; i <= 10; i++){
fgets(user_map[i], 25, f_user);
}
for(int i = 1; i <= 9; i++){
for(int j = 0; j < 18; j += 2) {
int tmp = (j + 2) / 2;
if(oj_map[i][j] == '?') {
;
}
else{
if(oj_map[i][j] != user_map[i][j]){
ret = 1;
}
}

if(vis[(i + 2) / 3][(tmp + 2) / 3][user_map[i][j] - '0'] || xx[i][user_map[i][j] - '0'] || yy[tmp][user_map[i][j] - '0']){
ret = 2;
}
vis[(i + 2) / 3][(tmp + 2) / 3][user_map[i][j] - '0'] = xx[i][user_map[i][j] - '0'] = yy[tmp][user_map[i][j] - '0'] = true;
}
}
}
/*****spj-end********/

fclose(f_in);
fclose(f_out);
fclose(f_user);
return ret;
}

本文标题:数独生成以及解数独

文章作者:HKer_YM

发布时间:2020年03月03日 - 17:15:52

最后更新:2020年03月03日 - 17:25:46

原始链接:https://blog.dreams-wj.top/2020/03/03/%E6%95%B0%E7%8B%AC%E7%94%9F%E6%88%90%E4%BB%A5%E5%8F%8A%E8%A7%A3%E6%95%B0%E7%8B%AC/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。