我已经编写了代码来解决C ++中的Sudoku游戏。该算法可在简单和中等数独游戏上轻松运行,但不会在硬数独游戏中返回任何内容。 您能帮我改进这段代码来解决更难的数独吗? It's my code
#ifndef SUDOKU_H
#define SUDOKU_H
#include<iostream>
#include<cmath>
#include<string>
using namespace std;
class Sudoku
{
friend ostream &operator<<(ostream&, Sudoku&);
public:
Sudoku(string);
void solver();
void row_solver();
void column_solver();
void square_solver();
bool check_status();
~Sudoku();
private:
int a[9][9][10];
void refresh();
};
Sudoku::Sudoku(string s)
{
for (int i = 0; i < 9; i++)
for (int j = 0; j < 9; j++)
a[i][j][0] = 0;
for (int i = 0, x = 0; i < 9; i++)
{
for (int j = 0; j < 9; j++)
{
a[i][j][0] = stoi(s.substr(x, 1));
x++;
}
}
}
void Sudoku::solver()
{
while (!check_status())
{
column_solver();
row_solver();
square_solver();
}
}
void Sudoku::row_solver()
{
for (int i = 0; i < 9; i++)
{
refresh();
int n_status[10] = {};
for (int j = 0; j < 9; j++)
if (a[i][j][0] == 0)
for (int m = 1; m < 10; m++)
if (a[i][j][m] == 1)
n_status[m]++;
for (int m = 1; m < 10; m++)
if (n_status[m] == 1)
for (int j = 0; j < 9; j++)
if (a[i][j][m] == 1 && a[i][j][0] == 0)
a[i][j][0] = m;
}
}
void Sudoku::column_solver()
{
for (int j = 0; j < 9; j++)
{
refresh();
int n_status[10] = {};
for (int i = 0; i < 9; i++)
if (a[i][j][0] == 0)
for (int m = 1; m < 10; m++)
if (a[i][j][m] == 1)
n_status[m]++;
for (int m = 1; m < 10; m++)
if (n_status[m] == 1)
for (int i = 0; i < 9; i++)
if (a[i][j][m] == 1 && a[i][j][0] == 0)
a[i][j][0] = m;
}
}
void Sudoku::square_solver()
{
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
refresh();
int n_status[10] = {};
for (int x = 0; x < 3; x++)
for (int y = 0; y < 3; y++)
if (a[i * 3 + x][j * 3 + y][0] == 0)
for (int m = 1; m < 10; m++)
if (a[i * 3 + x][j * 3 + y][m] == 1)
n_status[m]++;
for (int m = 1; m < 10; m++)
if (n_status[m] == 1)
for (int x = 0; x < 3; x++)
for (int y = 0; y < 3; y++)
if (a[i * 3 + x][j * 3 + y][m] == 1 && a[i * 3 + x][j * 3 + y][0] == 0)
a[i * 3 + x][j * 3 + y][0] = m;
}
}
}
bool Sudoku::check_status()
{
int r = 0;
for (int i = 0; i < 9; i++)
for (int j = 0; j < 9; j++)
if (a[i][j][0] != 0)
r++;
return r == 81;
}
Sudoku::~Sudoku()
{
}
void Sudoku::refresh()
{
for (int i = 0; i < 9; i++)
for (int j = 0; j < 9; j++)
for (int z = 1; z < 10; z++)
a[i][j][z] = 1;
for (int i = 0; i < 9; i++)
{
for (int j = 0; j < 9; j++)
{
if (a[i][j][0] != 0)
{
int x = a[i][j][0];
for (int m = 0; m < 9; m++)
a[m][j][x] = 0;
for (int m = 0; m < 9; m++)
a[i][m][x] = 0;
int im = floor(i / 3), jm = floor(j / 3);
for (int m = 0; m < 3; m++)
for (int n = 0; n < 3; n++)
a[im * 3 + m][jm * 3 + n][x] = 0;
}
}
}
}
ostream &operator<<(ostream& output, Sudoku& sudoku)
{
for (int i = 0; i < 9; i++)
{
for (int j = 0; j < 9; j++)
{
output << sudoku.a[i][j][0] << "\t";
if (j % 3 == 2)
cout << "|\t";
}
cout << "\n\n";
if (i % 3 == 2)
cout << "-----------------------------------------------------------------------------------------\n\n";
}
return output;
}
#endif // !SUDOKU_H
答案 0 :(得分:1)
可以使用回溯来解决数独问题,但是幼稚的回溯通常太慢。看一下Donald Knuth发明的“跳舞链接”技术。它可以用来更有效地解决数独问题。
几个相关链接:
您可以在Google上搜索“跳舞链接”以找到有关它的更多信息。