You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

数独求解器开发:如何遍历并验证所有3×3宫格?

数独棋盘有效性验证问题

我正在开发一款数独求解器,没怎么查资料,现在写了一个验证数独棋盘有效性的函数,后续会用到循环逻辑里。当前函数代码如下:

def valid(board):

    s = 0

    for row in board:
        if row.count('1') == 1 and row.count('2') == 1 and row.count('3') == 1 and row.count('4') == 1 and row.count('5') == 1 and row.count('6') == 1 and row.count('7') == 1 and row.count('8') == 1 and row.count('9') == 1:
            s += 1

    for column in range(len(board)):
        if i[column].count('1') == 1 and i[column].count('2') == 1 and i[column].count('3') == 1 and i[column].count('4') == 1 and i[column].count('5') == 1 and i[column].count('6') == 1 and i[column].count('7') == 1 and i[column].count('8') == 1 and i[column].count('9') == 1:
            s += 1

    for r in range(3):
        for c in range(3):
            print(board[r][c], end = '')

    if s == 18:
        print('valid')
    else:
        print('no')

测试用的有效棋盘是这个二维数组:

example = [['4','3','5','2','6','9','7','8','1'],['6','8','2','5','7','1','4','9','3'],['1','9','7','8','3','4','5','6','2'],
['8','2','6','1','9','5','3','4','7'],['3','7','4','6','8','2','9','1','5'],['9','5','1','7','4','3','6','2','8'],
['5','1','9','3','2','6','8','7','4'],['2','4','8','9','5','7','1','3','6'], ['7','6','3','4','1','8','2','5','9']]

我知道这种实现不是最优的,主要是想先搞懂逻辑:每行包含1-9各一次,s加1;每列符合同样条件,s也加1。所有行和列都符合的话s是18,但这还不够,得验证每个3×3宫格也满足1-9各出现一次,最终s要等于27才代表棋盘有效。

之前代码只能打印第一个3×3宫格,我试过暴力写法遍历所有宫格,但太繁琐,后来找到了更优的遍历方式:

def three(board):

    for row in range(0, 9, 3):
        for col in range(0, 9, 3):

            b = board[row][col] + board[row][col+1] + board[row][col+2] + board[row+1][col] + board[row+1][col+1] + board[row+1][col+2] + board[row+2][col] + board[row+2][col+1] + board[row+2][col+2]
            print(b)
            # test if valid...

这段代码能输出所有3×3宫格的内容:

435682197
269571834
781493562
826374951
195682743
347915628
519248763
326957418
874136259

现在需要完成这些3×3宫格的有效性验证,确保能正确判断整个数独棋盘是否有效,求帮助。


解决方案

首先,先优化你的验证逻辑,不管是行、列还是宫格,核心都是判断该区域是否包含1-9每个数字恰好一次,可以用集合来简化判断,比逐个count要简洁高效。另外你原来的列验证代码有错误(i未定义),先修正这部分,再整合宫格验证:

完整修改后的valid函数

def valid(board):
    s = 0
    target = set('123456789')  # 目标集合,包含1-9所有数字

    # 验证每一行
    for row in board:
        if set(row) == target:
            s += 1

    # 验证每一列
    for col in range(9):
        # 收集当前列的所有元素
        column_values = [board[row][col] for row in range(9)]
        if set(column_values) == target:
            s += 1

    # 验证每个3×3宫格
    for row_start in range(0, 9, 3):
        for col_start in range(0, 9, 3):
            # 收集当前宫格的所有元素
            grid_values = []
            for r in range(row_start, row_start + 3):
                for c in range(col_start, col_start + 3):
                    grid_values.append(board[r][c])
            # 验证宫格是否符合要求
            if set(grid_values) == target:
                s += 1

    # 判断最终结果
    if s == 27:
        print('valid')
        return True
    else:
        print('no')
        return False

代码说明

  1. 行验证:直接把每行转成集合,和包含1-9的目标集合对比,相等则说明该行符合要求。
  2. 列验证:通过列表推导式收集每一列的所有元素,同样转成集合对比目标集合。
  3. 宫格验证:用row_start和col_start遍历每个宫格的左上角坐标(步长为3),然后遍历宫格内的3×3元素收集到列表中,再用集合验证是否符合要求,符合则s加1。
  4. 结果判断:当s等于27(9行+9列+9宫格)时,棋盘有效,否则无效。

测试验证

调用valid(example)会输出valid,返回True,符合预期。

如果想保留你原来的count逻辑(为了理解基础逻辑),也可以把集合验证替换成你原来的多个count判断,比如对宫格的grid_values:

if (grid_values.count('1') == 1 and grid_values.count('2') == 1 
    and grid_values.count('3') == 1 and grid_values.count('4') == 1 
    and grid_values.count('5') == 1 and grid_values.count('6') == 1 
    and grid_values.count('7') == 1 and grid_values.count('8') == 1 
    and grid_values.count('9') == 1):
    s += 1

这样也能实现同样的效果,只是代码更冗长。

内容的提问来源于stack exchange,提问作者rooknoobski

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 20:50:33