1

我是新手,五年多没有编写 C++ 代码了。我有一个关于数独求解器的课程。它(在大多数情况下)有效,除非它回溯(当它无法找到放入框中的单个可能值时)它要么一直回溯到开头,要么无法退出循环。帮助?代码如下

Address::Address(int row, int col) //This class is for the addresses of each block of of the 9x9 grid
{
    this->row=row;
    this->col=col;
}//finds the locations of each block

Puzzle::Puzzle(const char grid[][9])
{
}

void Puzzle::solve(char grid[][9])
{
stack <Address> locations; //creates stack of locations
for(int row=0; row<9;row++)
{
    for (int col=0; col<9; col++)
    {
        if (grid[row][col]=='*') //checks for an empty block
        {
            Possibles possibles(grid,Address(row,col)); //creates an array of possible values for that specific block
            int possvalue = possibles.GetNextPossible(0); //gets the next possible value from the array of possible values
            while(possvalue == -1) //checks if there's no possible values for the block 
            {
                if(locations.empty())
                {
                    cout << "Puzzle Unsolvable" << endl;
                    return;
                }
                cout<<"PossValue before: "<< possvalue <<endl;
                Address previouslocation = locations.top(); //stores the previous location from the stack
                Possibles previouspossible(grid,previouslocation); //creates a new array of new possibles
                previouspossible.array[grid[previouslocation.row][previouslocation.col]-'0'] = false;
                grid[previouslocation.row][previouslocation.col] = '*'; //changes the previous location back to empty
                possvalue = previouspossible.GetNextPossible(grid[previouslocation.row][previouslocation.col]-'0'); //gets the new possible value from new possibles
                locations.pop();


                cout<<"PossValue after: "<< possvalue<<endl;
                cout<<"row: "<< row<<endl;
                cout<<"col: "<< col<<endl;
                cout<<"previouslocation.row: "<< previouslocation.row<<endl;
                cout<<"previouslocation.col: "<< previouslocation.col<<endl;
                cout<<"previousvalue" << grid[previouslocation.row][previouslocation.col] << endl;
                cout<<"grid[previouslocation.row][previouslocation.col]: "<< grid[previouslocation.row][previouslocation.col]<<endl;
                cout << locations.size() << endl;
                cout<<endl;

                row = previouslocation.row; //changes the row where we're trying to solve
                col = previouslocation.col; //changes the column where we're trying to solve
            }

            grid[row][col] = (char) ( ((int)'0') + possvalue); //puts the "good" value on the grid
            locations.push (Address(row,col)); // pushes the location of the box into the stack
            /*for(int i = 0; i< 9; i++)
            {
                for(int j = 0; j< 9; j++)
                    cout << grid[i][j];

                    cout << endl;
            }*/ // for row
            cout << endl;
        }
    }
}

}//solves sudoku

Possibles::Possibles(char grid[][9], Address currentAddress) //makes an array for each block for the number of possibles
{
for (int i=0; i<10; i++)
{
        array[i] = true; //setting a boolean array of size 9 to true
}

for (int row=0; row<9;row++)
{
array[grid[row][currentAddress.col]-'0'] = false; //checks for repeated values on the row 
}
for(int col=0; col<9; col++)
{
    array[grid[currentAddress.row][col]-'0'] = false; //checks for repeated values on the column
}
for(int row=currentAddress.row-(currentAddress.row%3); row < (currentAddress.row-(currentAddress.row%3))+3 ; row++) 
{
    for(int col=currentAddress.col-(currentAddress.col%3); col < (currentAddress.col-(currentAddress.col%3))+3 ; col++)
    {
        array[grid[row][col]-'0'] = false; //checks for repeated values in the box
    }
}

}//this function returns an array of "possibles" which is a boolean array for every value from 1-9. This determines whether the value is a possibility for that block.

int Possibles::GetNextPossible(int nextpossible) //determines the next "possible" array
{
for(int i=nextpossible+1; i<10; i++)
{
    if (array[i] == true)
        {
            return i; //if the boolean array returns true, then return the value of that boolean array.
        }
}
return -1; // if there is no "true" in the boolean array, then returns "NULL"
}

感谢您的帮助,伙计们!任何输入表示赞赏。

4

2 回答 2

0

我真的不知道你的代码,但如果你要回溯(你必须解决数独),你真的应该使用递归。没有它,你必须模拟它;最重要的是,您将无法使用for循环,因为有时您必须递减。

char [81]另一点:如果您将数独板表示为简单的线性数组或类似的东西,我认为您会发现它更简单(特别是如果您不使用递归) 。如果这样做,您将拥有一个当前位置索引,您可以对其进行递减和递增,而无需担心行和列。

所以,递归:

void
Puzzle::solve( int currentPosition = 0 )
{
    if ( currentPosition >= 81 ) {
        solved = true;
    } else if ( board[ currentPosition ] != empty ) {
        solve( currentPosition + 1 );
    } else {
        for ( int newValue = 1; ! solved && newValue <= 9; ++ newValue ) {
            if ( isLegal( currentPosition, newValue ) ) {
                set( currentPosition, newValue );
                solve( currentPosition + 1 );
                if ( ! solved ) {
                    unset( currentPosition );
                }
            }
        }
    }
}

这假设板本身是 Puzzle 的成员,并且 Puzzle 还包含一个标志,告诉您何时找到解决方案。

于 2013-04-15T16:10:41.983 回答
0

谢谢大家的帮助!我已经弄清楚我的问题是什么。我的台词只是重新排列错了。

 Address previouslocation = locations.top(); //stores the previous location from the stack
 Possibles previouspossible(grid,previouslocation); //creates a new array of new possibles
 previouspossible.array[grid[previouslocation.row][previouslocation.col]-'0'] = false;
 grid[previouslocation.row][previouslocation.col] = '*'; //changes the previous location back to empty
 possvalue = previouspossible.GetNextPossible(grid[previouslocation.row[previouslocation.col]-'0'); //gets the new possible value from new possibles

应该是:

Address previouslocation = locations.top(); //stores the previous location from the stack
Possibles previouspossible(grid,previouslocation); //creates a new array of new possibles
possvalue = previouspossible.GetNextPossible(grid[previouslocation.row][previouslocation.col]-'0'); //gets the new possible value from new possibles. the '0' is to convert char to int
grid[previouslocation.row][previouslocation.col] = '*'; //changes the previous location back to empty

哈哈。再次感谢所有帮助的家伙。

于 2013-04-16T01:20:33.680 回答