Lỗi thuật toán backtrack trong game sudoku

Em vừa dùng thuật toán backtrack để giải một board Sudoku cho trước. Và khi em để khai báo kiểu int thì nó chạy đúng, nhưng khi em chuyển thành unsigned char để còn phục vụ cho mục đích sau này thì nó không quay lui được nữa. Mong các bác chỉ giáo cho em với ._.

#include <iostream>
#include <windows.h>
#include <fstream>

using namespace std;

const int xMax = 9;
const int xMin = 0;
const int yMax = 9;
const int yMin = 0;

void inputBoard(unsigned char s[][9]);
void solveBoard(unsigned char s[][9], int x, int y);
bool checkBoard(unsigned char s[][9], int x, int y, int check);
void outputBoard(unsigned char s[][9]);

int main()
{
    unsigned char s[9][9];
    inputBoard(s);
    solveBoard(s,xMin,yMin);
    outputBoard(s);
}

void inputBoard(unsigned char s[][9])
{
    ifstream file ("input.txt");
    if(file.is_open())
        while(!file.eof())
        {
            for(int i=0; i<xMax; i++)
                for(int j=0; j<yMax; j++)
                {
                    file >> s[i][j];
                }
        }
    else cout << "Unable to open file";
    file.close();
}

void solveBoard(unsigned char s[][9], int x, int y)
{
    if(y==yMax)
    {
        if(x==xMax-1)
        {
            outputBoard(s);
            exit(0);
        }
        else solveBoard(s,x+1,yMin);
    }
    else if(s[x][y]=='0')
    {
        for(int check = 1; check <= yMax; check++)
        {
            //Kiểm tra ô đang mở xem có thỏa mãn không, nếu thỏa mãn thì xét cột tiếp theo
            if(checkBoard(s,x,y,check)==true)
            {
                char c_check = check + '0';
                s[x][y]=c_check;
                solveBoard(s,x,y+1);
                //Nếu solveBoard phía trên không khả thi, đưa giá trị của ô đang xét về 0 và xét vòng lặp khác
                s[x][y]='0';
            }
        }
    }
    solveBoard(s,x,y+1);
}
bool checkBoard(unsigned char s[][9], int x, int y, int check)
{
    char c_check=check+'0';
    //Xét giá trị ở hàng thứ x
    for(int i=0; i<yMax; i++)
    {
        if(s[x][i]==c_check) return false;
    }
    //Xét giá trị ở cột thứ y
    for(int i=0; i<xMax; i++)
    {
        if(s[i][y]==c_check) return false;
    }
    //Xét giá trị ở hình vuông 3x3 chứa ô đang xét
    int a=x/3, b=y/3;
    for(int i=3*a; i<3*a+3; i++)
        for(int j=3*b; j<3*b+3; j++)
            if(s[i][j]==c_check) return false;
    return true;
}

void outputBoard(unsigned char s[][9])
{
    system("cls");
    for(int i=0; i<xMax; i++)
        for(int j=0; j<yMax; j++)
        {
            cout << s[i][j] << "|";
            if (j==yMax-1) cout << endl;
        }
}

còn đây là dữ liệu từ file txt của em:
5 0 6 9 0 0 0 4 1
0 0 0 0 0 0 0 0 2
0 0 0 4 0 0 9 7 0
0 0 5 1 9 0 7 0 6
0 0 0 5 0 0 4 0 0
7 4 0 0 0 6 0 9 0
6 2 0 0 0 9 0 0 4
1 0 8 0 0 0 0 6 0
4 0 9 6 1 5 2 0 7

Thuật toán của bạn thì đúng rồi, nhưng cách đọc file thì có vấn đề một chút. Bạn không nên dùng file.eof() trong khi đọc vì nó có thể đọc sai, hơn nữa bạn cũng không cần phải dùng mảng kí tự cho mảng s mà thay vào đó là mảng số nguyên luôn cho đỡ phải chuyển đổi kiểu

cách đọc file bạn có thể sửa lại:

void inputBoard(unsigned char s[][9])
{
    ifstream file ("input.txt");
    if(file.is_open())

            for(int i=0; i<xMax; i++)
                for(int j=0; j<yMax; j++)
                {
                    int x;
                    file >> x;
                    s[i][j]=x+'0';
                }

    else cout << "Unable to open file";
    file.close();
}

cách đọc bằng kí tự thì nó sẽ đọc cả dấu space nên việc đọc sẽ không đúng.

2 Likes

Không phải đâu ạ, em sử dụng PP chia để trị để test cái vấn đề đó rồi. và mảng s[i][j] nó đọc chính xác cái bảng đó luônấy :smiley:
Với cả em định đưa mảng này vào để làm đồ họa trên openGL, chứ không em cũng làm kiểu int cho dễ.

Em sửa lại thuật toán như thế mà nó vẫn không quay lui được ấy :stuck_out_tongue:

Ơ không ai giúp em được ạ? :neutral_face:

83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?