我的数独模拟器的验证功能有问题吗?

Is there any problem with my validate function for my sudoku simulator?

我最近正在使用 python 构建一个数独模拟器,我很困惑为什么我的验证函数没有按预期工作。我尝试使用另一种使用 3 个 for 循环的验证方法并且它有效,所以我认为我的解决方法没有问题。 基本上如果在同一行、同一列或对角线上有相同的数字,它将 return False,否则为 True

def validate1(grid, r, c, val):
    var = 0
    r_up = r-var
    r_down = r+var
    c_right = c+var
    c_left = c-var
    while(r_up>=0 or r_down<=8 or c_right<=8 or c_left>=0):
        if(r_up>=0):
            if(grid[r_up][c]==val):
                return False
        if(r_down<=8):
            #print("down" + str(grid[r_down][c]))
            if(grid[r_down][c]==val):
                return False
        if(c_right<=8):
            if(grid[r][c_right]==val):
                return False
        if(c_left>=0):
            if(grid[r][c_left]==val):
                return False
        if(r_up>=0 and c_right<=8):
            if(grid[r_up][c_right]==val):
                return False
        if(r_up>=0 and c_left>=0):
            if(grid[r_up][c_left]==val):
                return False
        if(r_down<=8 and c_right<=8):
            if(grid[r_down][c_right]==val):
                return False
        if(r_down<=8 and c_left>=0):
            if(grid[r_down][c_left]==val):
                return False
        var = var + 1
        r_up = r-var
        r_down = r+var
        c_right = c+var
        c_left = c-var
    return True 

与其试图找出问题所在,不如让函数更简单(更符合 Pythonic):

def validate1(grid,r,c,val):
    if val in grid[r] : return False
    if val in (row[c] for row in grid): return False
    if any(val in row[c//3*3:][:3] for row in grid[r//3*3:][:3]): return False
    return True

但是,像这样检查冲突并不是最快的方法。你能做的就是在棋盘上维护 27 组与专属组相对应的已用号码。每个位置映射到这些组中的 3 个(行、列、块),因此您可以快速将放置的数字添加到它们,还可以使用集合成员快速检查是否存在冲突数字。这可以通过将数字与其组索引组合来进一步改进,从而允许您使用一组 243 个组 ID-数字对来管理冲突。有了这个,您可以编写一个非常紧凑的数独解算器,带有回溯法,蛮力解决问题:

def shortSudokuSolve(board):
    size    = len(board)
    block   = int(size**0.5)
    board   = [n for row in board for n in row ]      
    span    = { (n,p): { (g,n)  for g in (n>0)*[p//size, size+p%size, 2*size+p%size//block+p//size//block*block] }
                for p in range(size*size) for n in range(size+1) }
    empties = [i for i,n in enumerate(board) if n==0 ]
    used    = {gn for p,n in enumerate(board) for gn in span[n,p] if n}
    empty   = 0
    while empty>=0 and empty<len(empties):
        pos        = empties[empty]
        used      -= span[board[pos],pos]
        board[pos] = next((n for n in range(board[pos]+1,size+1) if not span[n,pos]&used),0)
        used      |= span[board[pos],pos]
        empty     += 1 if board[pos] else -1
    return [board[r:r+size] for r in range(0,size*size,size)]