用C ++语言编写的数独求解器程序

时间:2019-05-14 12:05:00

标签: c++ algorithm sudoku

我已经编写了代码来解决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

1 个答案:

答案 0 :(得分:1)

可以使用回溯来解决数独问题,但是幼稚的回溯通常太慢。看一下Donald Knuth发明的“跳舞链接”技术。它可以用来更有效地解决数独问题。

几个相关链接:

您可以在Google上搜索“跳舞链接”以找到有关它的更多信息。