简体   繁体   中英

Python for loop range function causing an infinite loop

I am building a sudoku function to learn how to code in python. I seem to be creating an infinite loop with a for loop but I don't understand how. The code attempts to look at each empty square of the sudoku board and check if a value counter is allowed by the rules of sudoku. If counter is allowed the board is updated and the function moves on to the next empty square. If counter is not allowed than counter is incremented by 1 and tested again.

The issue I am having comes when counter is greater then 9. When this happens I want to look at the previous square which was empty on the original board (named puzzle) and delete the value in this square. The function than should set counter equal to the value in the previous square +1 and call itself to run again.

In essence the function is testing each empty square for possible values until it finds a value and than move on to the next square. If there are no possible values the function will back track, delete the last square and try running again.

My problem seems to happen in the else condition when counter is greater than 9. This part of the function is causing an infinite loop which prints out 'no' repeatedly.

I'm assuming that my function is getting stuck on the while loop but I'm not sure why.

puzzleBoard =[[1,2,3,4,5,6,7,8,9],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0]]


def solvePuzzle():

#start by looking at each square in the 9x9 sudoku grid and check if that square is empty (=0)
for i in range(9):
    for j in range(9):
        counter = 1
        topX = 3*(i//3)
        topY = 3*(j//3)

        # while the board at index [i][j] is empty check if the value of 'counter' fits in the square and adheres to the sudoku rules
        # if counter is not an allowed value increment counter by 1 and try again
        while puzzleBoard[i][j] ==0:
            if counter < 10:
                row = all([counter != puzzleBoard[i][x] for x in range(9)])
                column = all([counter != puzzleBoard[y][j] for y in range(9)])
                box = all([counter != puzzleBoard[x][y] for x in range(topX, topX+3) for y in range(topY, topY+3)])

                if row and column and box == True:
                    puzzleBoard[i][j]=counter
                    uploadBoard()
                else:
                    counter = counter + 1

            # if counter is larger than ten set the previous square ([i][j-1]) equal to zero, set the counter equal to one more than the previous squares value, and call the solvePuzzle function again.
            else:
                for k in range(i,0,-1):
                    for l in range(j-1,0,-1):
                        if puzzle[k][l]==0:
                            counter = puzzleBoard[k][l] + 1
                            puzzleBoard[k][l]=0
                            solvePuzzle()
                            return
                        else:
                            print("no")

I was able to work out the answer. There are a few issues with the code but the main problem is that in the lower else statement counter = puzzleBoard[k][l] + 1 and then the function was being called again, which resets the variable counter to 1.

I was able to fix this problem by creating a global variable countholder and modifying the else statement to say countholder = puzzleBoard[k][l] + 1

The full working code looks like this:

puzzleBoard =[[0,2,0,0,0,0,0,0,0],[0,0,0,6,0,0,0,0,3],
              [0,7,4,0,8,0,0,0,0],[0,0,0,0,0,3,0,0,2],
              [0,8,0,0,4,0,0,1,0],[6,0,0,5,0,0,0,0,0],
              [0,0,0,0,1,0,7,8,0],[5,0,0,0,0,9,0,0,0],
              [0,0,0,0,0,0,0,4,0]]

puzzle =[[0,2,0,0,0,0,0,0,0],[0,0,0,6,0,0,0,0,3],
              [0,7,4,0,8,0,0,0,0],[0,0,0,0,0,3,0,0,2],
              [0,8,0,0,4,0,0,1,0],[6,0,0,5,0,0,0,0,0],
              [0,0,0,0,1,0,7,8,0],[5,0,0,0,0,9,0,0,0],
              [0,0,0,0,0,0,0,4,0]]

countholder = 1

def solvePuzzle():

    #start by looking at each square in the 9x9 sudoku grid and check if that square is empty (=0)
    for i in range(9):
        for j in range(9):
            global countholder
            counter = countholder
            topX = 3*(i//3)
            topY = 3*(j//3)

            # while the board at index [i][j] is empty check if the value of 'counter' fits in the square and adheres to the sudoku rules
            # if counter is not an allowed value increment counter by 1 and try again
            while puzzleBoard[i][j] ==0:
                if counter < 10:
                    row = all([counter != puzzleBoard[i][x] for x in range(9)])
                    column = all([counter != puzzleBoard[y][j] for y in range(9)])
                    box = all([counter != puzzleBoard[x][y] for x in range(topX, topX+3) for y in range(topY, topY+3)])

                    if (row and column and box) == True:
                        puzzleBoard[i][j]=counter
                        print(puzzleBoard)
                        countholder = 1
                    else:
                        counter = counter + 1

                # if counter is larger than ten set the previous square ([i][j-1]) equal to zero, set the counter equal to one more than the previous squares value, and call the solvePuzzle function again.
                else:
                    run_One = True         
                    for k in range(i,-1,-1):
                        if run_One == True:
                            run_One = False
                            for l in range(j,0,-1):
                                if l == 0:
                                    print(run_One)
                                elif puzzle[k][l-1]==0:
                                    countholder = puzzleBoard[k][l-1] + 1
                                    puzzleBoard[k][l-1]=0
                                    solvePuzzle()
                                    return
                                else:
                                    continue
                        else:
                            for l in range(8,-1,-1):
                                if puzzle[k][l]==0:
                                    countholder = puzzleBoard[k][l] + 1
                                    puzzleBoard[k][l]=0
                                    solvePuzzle()
                                    return
                                else:
                                    continue

solvePuzzle()   

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