用c ++编写的SUDOKU解算器

时间:2013-09-26 08:11:24

标签: c++ sudoku

我是c ++的初学者::你可以从我的代码中理解::需要帮助在c ++中制作数独求解器

该计划的要求:

  1. 输入数独:[完成]
  2. 阅读数独:[完成]
  3. 验证功能:(验证数独:) [完成]
  4. 显示功能[完成]
  5. 解决功能[需要帮助]
  6. 我的计划:

    • 创建一个函数来验证数独[完成] 并为每个空白字符分配1-9的可能性。并执行蛮力
      解决这个难题的方法。它每次都会调用函数validate 在做蛮力的同时。它耗费了大量时间,我明白它是 不可能。

    我需要一个更好的解算函数算法,请帮助我:

    我已经评论了一些代码来分析代码:如果这是错误的方式,请道歉。我只是个初学者。上个月开始编写c ++编码。我在网上看到了一些关于数独解决的代码,但我觉得很难分析它们。

    这是我到目前为止所做的:

    /*  Program: To solve a SU-DO-KU: 
        Date:23-sep-2013 @ 5.30:
    */
    
    
    #include<iostream>
    using namespace std;
    
    int su_in[9][9]={
                     0,0,7   ,0,0,0    ,4,0,6,
                     8,0,0   ,4,0,0    ,1,7,0,
                     0,0,0   ,3,0,0    ,9,0,5,
    
                     0,0,0   ,7,0,5    ,0,0,8,
                     0,0,0   ,0,0,0    ,0,0,0,
                     4,0,0   ,2,0,8    ,0,0,0,
    
                     7,0,4   ,0,0,3    ,0,0,0,
                     0,5,2   ,0,0,1    ,0,0,9,
                     1,0,8   ,0,0,0    ,6,0,0   
                    };
    int su_out[9][9];/*={
    
    
                     5,3,7   ,9,1,2    ,4,8,6,
                     8,2,9   ,4,5,6    ,1,7,3,
                     6,4,1   ,3,8,7    ,9,2,5,
    
                     9,1,3   ,7,4,5    ,2,6,8,
                     2,8,6   ,1,3,9    ,7,5,4,
                     4,7,5   ,2,6,8    ,3,9,1,
    
                     7,6,4   ,8,9,3    ,5,1,2,
                     3,5,2   ,6,7,1    ,8,4,9,
                     1,9,8   ,5,2,4    ,6,3,7
                    };*/
    
    struct chance{
    
        int poss[9];
    
    };              
    
    int box_validate(int,int,int);
    void read(int);
    void display(int);
    int validate(int);
    int solve();
    
    int main()
    {   
        int i,j,row,get_res=2;
    
        enum {input=1,output};
    
        cout<<"enter the sudoku: use 0 if the colum is empty:\n";
    
    //  for(i=0; i<9; i++){
    //  read(i);
    //  }
    
        cout<<"\n\t\tTHE ENTERED SU-DO-CU IS:\n\n";
        display(input);
    
        get_res=validate(input);
    
        if(get_res==0)
            cout<<"valid input!\n";
            else if(get_res==1)
               cout<<"invalid input!\n";
    
    //  display(input);
        for(i=0; i<9; i++)
        for(j=0; j<9; j++)
        su_out[i][j]=su_in[i][j];
    
    //  display(output);
        get_res=validate(output);
    
        if(get_res==0){
            cout<<"valid solution!\n"; display(output);}
        //  else if(get_res==1)
        //     cout<<"invalid sudoku!\n";
    
        if(solve()==0) display(output);
        else cout<<"not solved buddy!!\n";
    
    
    }
    
    
    
    
    void read(int row) // function to read the SU-DO-CU
    {   
        unsigned num,i;
        cout<<"enter the row:'"<<row+1<<"'\n";
    
        for(i=0; i<9;   i++)
        {
        cin>>num;
        if(num<0||num>9)
        cout<<"error! invalid input: enter a number < or = 9 and > or = 0 \n";
        else
        su_in[row][i]=num;
        }
    }
    
    
    void display(int sudoku) // function to display the SU-DO-CU
    {
        unsigned i,j;
    
            for(i=0;i<9; i++)
            {   
                if(i%3==0)
                cout<<"\t\t-------------------------\n";    
    
                cout<<"\t\t";
                for(j=0; j<9; j++)
                    {   
                        if(j%3==0)
                        cout<<"| ";
    
                //      if(su[i][j]==0)
                //      cout<<"_ ";
                //      else    
                        if(sudoku==1)
                        cout<<su_in[i][j]<<" ";
    
                        else if(sudoku==2)
                        cout<<su_out[i][j]<<" ";
    
                        if(j==8)
                        cout<<"|";  
    
                    }
    
                cout<<"\n";
                if(i==8)
                cout<<"\t\t-------------------------\n";    
    
    
            }
    
    
    }
    
    
    int validate(int sudoku) // function to validate the input SU-DO-CU
    {
        unsigned i,j,k,n,count=0;
    //..........................row validation
        for(i=0; i<9; i++)
            for(j=0; j<9; j++)
                for(k=0;k<9;k++)
                    {
                        if(sudoku==1 && k!=j && su_in[i][j]!=0)
                           {
                            if(su_in[i][j]==su_in[i][k])
                            return 1;
                           }
                         else if(sudoku==2 && k!=j )
                           {
                            if(su_out[i][j]==su_out[i][k])
                            return 1;
                           }  
    
    
                    }
    //..................................colume validation
        for(i=0;  i<9;  i++)
            for(j=0;  j<9;  j++)
                for(k=0;  k<9;  k++)
                    {
                        if(sudoku==1 && k!=j && su_in[j][i]!=0)
                           {
                            if(su_in[j][i]==su_in[k][i])
                            return 1;
                           }
                         else if(sudoku==2 && k!=i )
                           {
                            if(su_out[j][i]==su_out[j][k])
    
                            return 1;
                           }    
                    }
        // each box validating.......................
        for(i=0;  i<=6;  i=i+3)
            for(j=0; j<=6; j=j+3)
            {
                if(box_validate(i,j,sudoku)==1)
                return 1;
            }
    
        // sum validation for output....
    
        if(sudoku==2)
        {
            for(i=0; i<9; i++)
            for(j=0; j<9; j++)
                count=count+su_out[i][j];
    
        if(count!=405) return 1;
        }
    
    
            return 0;           
    
    }
    
    
    int box_validate(int i,int j,int sudoku)
    {   
        unsigned k=j,n=i;
        int temp_i=i,temp_j=j,temp_k=k, temp_n=n;
            for(i=temp_i;  i<temp_i+3;  i++)
            for(j=temp_j;  j<temp_j+3;  j++)
                for(k=temp_k;  k<temp_k+3;  k++)
                    {           
                      if(sudoku==1 && k!=j && su_in[i][j]!=0)
                     {
                        if(su_in[i][j]==su_in[i][k])
                         return 1;
    
                            for(n=temp_n;  n<temp_n+3;  n++)
                            {
                                 if(sudoku==1 &&  su_in[i][j]!=0)
                                  if(k==j && n==i)
                                    ;else 
                                      if(su_in[i][j]==su_in[n][k])
                                        return 1;
    
                            }
                    }
    
    
                    if(sudoku==2 && k!=j )
                    {
                        if(su_out[i][j]==su_out[i][k])
                         return 1;
    
                            for(n=temp_n;  n<temp_n+3;  n++)
                            {
                                 if(sudoku==1 )
                                  if(k==j && n==i)
                                    ;else 
                                      if(su_out[i][j]==su_out[n][k])
                                        return 1;
    
    
    
                              }
                    }
                }
        return 0;
    
    }
    
    
    int solve()
    {
        unsigned i,j,k,m,n,x;   
    
    struct chance cell[9][9];
    
        for(i=0; i<9; i++)
            for(j=0; j<9; j++)
                if(su_in[i][j]==0)
                    for(k=0;k<9; k++)
                    cell[i][j].poss[k]=k+1;
    
                    /*
        for(i=0; i<9; i++)
            for(j=0; j<9; j++)
                if(su_in[i][j]==0)
                    for(k=0;k<9; k++)
                    {   su_out[i][j]=cell[i][j].poss[k]=k+1;            
                            su_out[i][j]=cell[i][j].poss[k];
                            for(m=0; m<9; m++)
                              for(n=0; n<9; n++)
                              for(x=1; x<=9; x++)
                              { if(x!=k+1)
                                cell[m][n].poss[x]==x;
                                if(validate(2)==0)
                                   return 0;
                           }
                }*/
    
            for(i=0; i<9; i++)
            for(j=0; j<9; j++)
                if(su_in[i][j]==0)
                while (validate(2)==0)
                {
    
                    for(k=0;k<9; k++)
                    {   su_out[i][j]=k+1;           
                            for(m=i+1; m <9 ; m++)
                              for(n=0; n <9 ; n++)
                                for(x=1; x<=9; x++)
                              { su_out[m][n]=x;
                                if(validate(2)==0)
                                   return 0;
                           }
                }
    
              }
    
    
    }
    

4 个答案:

答案 0 :(得分:5)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
using namespace std;
#define UNASSIGNED 0
#define N 9

bool FindUnassignedLocation(int grid[N][N], int &row, int &col);
bool isSafe(int grid[N][N], int row, int col, int num);

/* assign values to all unassigned locations for Sudoku solution  
 */
bool SolveSudoku(int grid[N][N])
{
    int row, col;
    if (!FindUnassignedLocation(grid, row, col))
       return true;
    for (int num = 1; num <= 9; num++)
    {
    if (isSafe(grid, row, col, num))
    {
        grid[row][col] = num;
        if (SolveSudoku(grid))
            return true;
        grid[row][col] = UNASSIGNED;
    }
    }
    return false;
}

/* Searches the grid to find an entry that is still unassigned. */
bool FindUnassignedLocation(int grid[N][N], int &row, int &col)
{
    for (row = 0; row < N; row++)
        for (col = 0; col < N; col++)
            if (grid[row][col] == UNASSIGNED)
                return true;
    return false;
}

/* Returns whether any assigned entry n the specified row matches 
   the given number. */
bool UsedInRow(int grid[N][N], int row, int num)
{
    for (int col = 0; col < N; col++)
    if (grid[row][col] == num)
        return true;
    return false;
}

/* Returns whether any assigned entry in the specified column matches 
   the given number. */
bool UsedInCol(int grid[N][N], int col, int num)
{
    for (int row = 0; row < N; row++)
        if (grid[row][col] == num)
            return true;
    return false;
}

/* Returns whether any assigned entry within the specified 3x3 box matches 
   the given number. */
bool UsedInBox(int grid[N][N], int boxStartRow, int boxStartCol, int num)
{
    for (int row = 0; row < 3; row++)
        for (int col = 0; col < 3; col++)
            if (grid[row+boxStartRow][col+boxStartCol] == num)
                return true;
    return false;
}

/* Returns whether it will be legal to assign num to the given row,col location. 
 */
bool isSafe(int grid[N][N], int row, int col, int num)
{
    return !UsedInRow(grid, row, num) && !UsedInCol(grid, col, num) &&
       !UsedInBox(grid, row - row % 3 , col - col % 3, num);
}

void printGrid(int grid[N][N])
{
    for (int row = 0; row < N; row++)
    {
        for (int col = 0; col < N; col++)
            cout<<grid[row][col]<<"  ";
        cout<<endl;
    }
}

int main()
{
    int grid[N][N] = {{3, 0, 6, 5, 0, 8, 4, 0, 0},
                      {5, 2, 0, 0, 0, 0, 0, 0, 0},
                      {0, 8, 7, 0, 0, 0, 0, 3, 1},
                      {0, 0, 3, 0, 1, 0, 0, 8, 0},
                      {9, 0, 0, 8, 6, 3, 0, 0, 5},
                      {0, 5, 0, 0, 9, 0, 6, 0, 0},
                      {1, 3, 0, 0, 0, 0, 2, 5, 0},
                      {0, 0, 0, 0, 0, 0, 0, 7, 4},
                      {0, 0, 5, 2, 0, 6, 3, 0, 0}};
    if (SolveSudoku(grid) == true)
        printGrid(grid);
    else
        cout<<"No solution exists"<<endl;
    return 0;
}

答案 1 :(得分:5)

这是我的代码: 我认为这是最好的。

/*
 *  File: Sudoku-Solver.cc
 *
 *  Created On: 12, April 2016
 *      Author: Shlomo Gottlieb
 *
 * Description: This program holds A sudoku board (size: 9*9),
 *              it allows the user to input values that he choices
 *              and finds the first rational solution.
 *              The program also prints the sudoku whether A solution
 *              was found or not.
 *
 */

//========= Includes =========//
#include <iostream>

//========= Using ==========//
using namespace std;

//========= Constants =========//
const int N = 3;            // The size of 1 square in the sudoku.
const int EMPTY = 0;        // A sign for an empty cell.
const int STOP_INPUT = -1;  // A sign for stop get input.

//====== Function Declaration ======//
void input_sud(int sud[][N*N]);
bool fill_sud(int sud[][N*N], int row, int col);
void print_sud(const int sud[][N*N]);
bool is_legal(const int sud[][N*N], int row, int col, int val);
bool is_row_ok(const int row[], int col, int val);
bool is_col_ok(const int sud[][N*N], int row, int col, int val);
bool is_sqr_ok(const int sud[][N*N], int row, int col, int val);

//========== Main ===========//
int main()
{
    int sud[N*N][N*N] = { { EMPTY } };  // The sudoku board.

    input_sud(sud);
    fill_sud(sud, 0, 0);
    print_sud(sud);

    return 0;
}

//======== Input Sudoku ========//
// Gets the input for the sudoku,
// 0 means an empty cell.
void input_sud(int sud[][N*N])
{
    for(int i = 0; i < N*N; i++)
        for(int j = 0; j < N*N; j++)
            cin >> sud[i][j];
}

//======== Fill Sudoku =========//
// Tries to fill-in the given sudoku board
// according to the sudoku rules.
// Returns whether it was possible to solve it or not.
bool fill_sud(int sud[][N*N], int row, int col)
{
    // Points to the row number of the next cell.
    int next_row = (col == N*N - 1) ? row + 1 : row;

    // Points to the column number of the next cell.
    int next_col = (col + 1) % (N*N);

    // If we get here, it means we succeed to solve the sudoku.
    if(row == N*N)  
        return true;

    // Checks if we are allowed to change the value of the current cell.
    // If we're not, then we're moving to the next one.
    if(sud[row][col] != EMPTY)
        return fill_sud(sud, next_row, next_col);

    // We're about to try and find the legal and appropriate value
    // to put in the current cell.
    for(int value = 1; value <= N*N; value++)
    {
        sud[row][col] = value;

        // Checks if 'value' can stay in the current cell,
        // and returns true if it does.
        if(is_legal(sud, row, col, value) && fill_sud(sud, next_row, next_col))
            return true;

        // Trial failed!
        sud[row][col] = EMPTY;
    }

    // None of the values solved the sudoku.
    return false;
}

//======== Print Sudoku ========//
// Prints the sudoku Graphically.
void print_sud(const int sud[][N*N])
{
    for(int i = 0; i < N*N; i++)
    {
        for(int j = 0; j < N*N; j++)
            cout << sud[i][j] << ' ';
        cout << endl;
    }
}

//========== Is Legal ==========//
// Checks and returns whether it's legal
// to put 'val' in A specific cell.
bool is_legal(const int sud[][N*N], int row, int col, int val)
{
    return (is_row_ok(sud[row], col, val) &&
            is_col_ok(sud, row, col, val) &&
            is_sqr_ok(sud, row, col, val));
}

//========= Is Row OK =========//
// Checks and returns whether it's legal
// to put 'val' in A specific row.
bool is_row_ok(const int row[], int col, int val)
{
    for(int i = 0; i < N*N; i++)
        if(i != col && row[i] == val)
            return false;       // Found the same value again!

    return true;
}

//========= Is Column OK =========//
// Checks and returns whether it's legal
// to put 'val' in A specific column.
bool is_col_ok(const int sud[][N*N], int row, int col, int val)
{
    for(int i = 0; i < N*N; i++)
        if(i != row && sud[i][col] == val)
            return false;       // Found the same value again!

    return true;
}

//========= Is Square OK =========//
// Checks and returns whether it's legal
// to put 'val' in A specific square.
bool is_sqr_ok(const int sud[][N*N], int row, int col, int val)
{
    int row_corner = (row / N) * N;
    // Holds the row number of the current square corner cell.

    int col_corner = (col / N) * N;
    // Holds the column number of the current square corner cell.

    for(int i = row_corner; i < (row_corner + N); i++)
        for(int j = col_corner; j < (col_corner + N); j++)
            if((i != row || j != col) && sud[i][j] == val)
                return false;       // Found the same value again!

    return true;
}

答案 2 :(得分:0)

上面给出的答案与许多人在https://www.geeksforgeeks.org/sudoku-backtracking-7/等多个网站上发布的答案相似。 TBH,当我不初始化row和col并在FindUnassignedLocation函数中调用它们时,这些解决方案对我来说并不直观。我想在LeetCode上找到的另一个答案的帮助下,自己尝试一下。如果它可以帮助任何人,那么您来了。

n

答案 3 :(得分:-3)

我认为如果你为单元格和sudokus创建不同的类,这会使你的工作更容易。例如,如果你为单元格创建类,你可以为该唯一单元格创建概率数组,并且每个循环使这些概率数组变得更窄只有一个不同的元素然后是零,那么你发现细胞真正有价值。我回家后给出了一个例子。