简体   繁体   English

Python for循环范围函数导致无限循环

[英]Python for loop range function causing an infinite loop

I am building a sudoku function to learn how to code in python. 我正在构建一个数独函数来学习如何在python中编码。 I seem to be creating an infinite loop with a for loop but I don't understand how. 我似乎用for循环创建了一个无限循环,但我不明白如何。 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. 代码试图查看数独板的每个空方块,并检查数独规则是否允许值counter 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. 如果不允许计数器,则计数器增加1并再次测试。

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. 我遇到的问题是当计数器大于9时。当发生这种情况时,我想查看原始板上的前一个方块(命名为难题)并删除此方块中的值。 The function than should set counter equal to the value in the previous square +1 and call itself to run again. 该函数应该设置计数器等于前一个方格+1中的值,并调用自身再次运行。

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. 当计数器大于9时,我的问题似乎发生在else条件下。这部分函数导致无限循环,反复打印出'no'。

I'm assuming that my function is getting stuck on the while loop but I'm not sure why. 我假设我的函数卡在while循环中,但我不知道为什么。

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. 代码有一些问题,但主要问题是在较低的else语句counter = puzzleBoard[k][l] + 1然后再次调用该函数,它将变量counter重置为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 我能够通过创建一个全局变量countholder并修改else语句来说明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()   

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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