简体   繁体   中英

Sudoku Solving - Skip on stage in backtracking

I already asked for help here, but nobody answer, and it really frustrating, I am trying to write a code that solve a Sudoku in recursive function (backtracking), here is the code:

#include <stdio.h>
#include <windows.h>

#define SIZE        9
#define SQUARE_SIZE 3

void print(int arrBoard[SIZE][SIZE])
{
     system("cls");
     int i, j;
     for (i = 0; i < SIZE; i++)
     {
         if (i % 3 == 0) printf("_ _ _ _ _ _ _ _ _ _ _ _\n");
         for (j = 0; j < SIZE; j++)
         {
             if (j % 3 == 0) printf("| ");
             printf("%d ", arrBoard[i][j]);
         }
         printf("\n");
     }

     Sleep(100);
}

BOOL IsValidRow(int arrBoard[SIZE][SIZE], int iNum, int iRow)
{
    int iCol;

    for (iCol = 0; iCol < SIZE; iCol++)
        if (arrBoard[iRow][iCol] == iNum) return FALSE;

    return TRUE;
}

BOOL IsValidCol(int arrBoard[SIZE][SIZE], int iNum, int iCol)
{
    int iRow;

    for (iRow = 0; iRow < SIZE; iRow++)
        if (arrBoard[iRow][iCol] == iNum) return FALSE;

    return TRUE;
}

BOOL IsValidSquare(int arrBoard[SIZE][SIZE], int iNum, int iRow, int iCol)
{
    iRow-= (iRow % SQUARE_SIZE);
    iCol-= (iCol % SQUARE_SIZE);

    int i, j;
    for(i = 0; i < SQUARE_SIZE; i++)
        for (j = 0; j < SQUARE_SIZE; j++)
            if (arrBoard[iRow + i][iCol + j] == iNum) return FALSE;

    return TRUE;
}

BOOL IsValid(int arrBoard[SIZE][SIZE], int iNum, int iRow, int iCol)
{
    if (IsValidRow(arrBoard, iNum, iRow) == FALSE) return FALSE;
    if (IsValidCol(arrBoard, iNum, iCol) == FALSE) return FALSE;
    if (IsValidSquare(arrBoard, iNum, iCol, iRow) == FALSE) return FALSE;

    return TRUE;
}

BOOL _Solve(int arrBoard[SIZE][SIZE], int iRow, int iCol)
{
    if (iRow == 9) return TRUE;

    if (arrBoard[iRow][iCol])
    {
        iRow = (iCol == 8) ? iRow + 1 : iRow;
        iCol = (iCol == 8) ? 0 : iCol + 1;

        if(_Solve(arrBoard, iRow, iCol)) return TRUE;
        return FALSE;
    }

    int iNewNum, iOldRow, iOldCol;
    for (iNewNum = 1; iNewNum <= SIZE; iNewNum++)
    {
        if (IsValid(arrBoard, iNewNum, iRow, iCol))
        {
            arrBoard[iRow][iCol] = iNewNum;
            print(arrBoard);
            iOldRow = iRow; iOldCol = iCol;
            iRow = (iCol == 8) ? iRow + 1 : iRow;
            iCol = (iCol == 8) ? 0 : iCol + 1;

            if (_Solve(arrBoard, iRow, iCol)) return TRUE;

            iRow = iOldRow; iCol = iOldCol;
            arrBoard[iRow][iCol] = 0;
        }
    }
    return FALSE;
}

int main(void)
{
    int arrBoard[SIZE][SIZE] =
    {0, 1, 0, 3, 6, 4, 0, 2, 0,
     6, 0, 0, 0, 0, 0, 0, 9, 7,
     0, 0, 0, 9, 0, 7, 0, 0, 0,
     0, 0, 6, 1, 0, 2, 8, 0, 0,
     1, 9, 8, 0, 0, 0, 0, 3, 2,
     0, 0, 7, 8, 0, 3, 9, 0, 0,
     0, 0, 0, 7, 0, 8, 0, 0, 0,
     4, 0, 0, 0, 0, 0, 0, 0, 3,
     0, 2, 0, 4, 5, 6, 0, 1, 0};

     _Solve(arrBoard, 0, 0);

    fflush(stdin);
    getchar();
    return 0;
}

its not the real code (just because the UI isnt important now). so what I did here is to print the board every time it change any cell. I saw one mistake while it tried to solve, when it reached to cell at row: 2 col: 6 (in index its [1][5]), it skip on the number 1 (which is the real answer), because it didnt try one, it cannot solve the rest of the sudoku. i cant find out why it doesnt work.

You've already accomplished the first step, identifying where and when the problem occurs. With the help of a debugger, you can step through _Solve when iRow is 1 and iCol is 5. Here's what I see, just looking at the first point when your problem occurs:

  • IsValid(arrBoard, iNewNum, iRow, iCol) returns FALSE .

  • Stepping into that method, IsValidSquare(arrBoard, iNum, iCol, iRow) is returning FALSE .

  • Looking again at that line, it seems a bit odd that you've got iCol before iRow , when your pattern elsewhere is row-then-column. Comparing the call to the declaration/definition, it looks like you've mixed up the parameters at the call-site.

Fixing the order of the parameters for that call to IsValidSquare and re-running results in a solution.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM