数独无限循环使用堆栈

时间:2013-04-15 15:44:00

标签: c++ sudoku

我是新手,并且在五年内没有对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"
}

谢谢你的帮助,伙计们!任何意见都表示赞赏。

2 个答案:

答案 0 :(得分:0)

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

另一点:我认为你会发现它更简单(特别是 如果你不使用递归,如果你代表数独板 作为一个简单的线性数组,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的成员,并且 该拼图还包含一个标志,告诉您何时找到 解决方案。

答案 1 :(得分: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

哈哈。再次感谢所有帮助人员。