Python列表生成无重复9x9数独网格的重复值问题排查
问题根因
你的for循环和while判断逻辑都存在bug,3行版本能跑通纯粹是规模小、撞对结果的概率高,本质逻辑从一开始就有缺陷:
- 首先是最显眼的低级错误:for循环的遍历范围写错了
你写的range(0, 8)是Python左闭右开区间,只会遍历索引0到7,对应第1到第8列,最后一列(索引8)从头到尾没做过任何重复校验,天生就留了出重复的口子。 - 更核心的逻辑错误:逐列校验+整行洗牌的操作,会直接破坏之前已经校验通过的结果
你是按x从小到大逐列检查的,比如x=0时把row2洗到第一列没重复,等x=1检查第二列时,再次调用random.shuffle(row2)会把整行所有元素全部打乱,之前已经校验合格的第一列元素会被直接改掉,而你不会再回头重新检查第一列的合法性,前面的列出重复是必然结果。
你之前的3行测试版没频繁出问题,只是因为行数少,shuffle之后刚好把前面列也凑对的概率不低,多跑个十几次你一样能看到重复值,不是逻辑正确。 - 额外的隐性坑:这种纯随机洗牌硬凑的方案,在9行规模下很容易进入死循环——比如前8行生成完之后,剩下的排列组合里根本不存在能满足所有列不重复的第9行,程序会卡在while循环里无限洗牌跑不出来。
排查&修正思路
- 先修正遍历范围:要覆盖全部9列,得写
range(9)或者range(0,9),别漏最后一列。 - 彻底改掉逐列校验的逻辑:校验某一行是否合法时,必须一次性检查这一行所有列和前面所有已确定行的同位置值,只要任意一列存在重复,就重新洗牌,洗完之后从头重新校验所有列,不要逐列割裂检查。
- 别用row1到row9这种零散变量存行,把所有行放到同一个二维列表里管理,写循环的时候不用重复堆大段冗余判断。
按你原有思路修正后的可运行参考代码:
import random # 初始化9行数据,统一放到二维列表管理 grid = [["1", "2", "3", "4", "5", "6", "7", "8", "9"] for _ in range(9)] random.shuffle(grid[0]) # 第一行直接随机打乱即可 # 从第二行开始逐行生成 for row_idx in range(1, 9): is_valid = False while not is_valid: random.shuffle(grid[row_idx]) is_valid = True # 一次性校验当前行所有列,和前面所有已生成行有没有同列重复 for col in range(9): for prev_row in range(row_idx): if grid[row_idx][col] == grid[prev_row][col]: is_valid = False break if not is_valid: break # 打印结果 for row in grid: print(row)
注:这个版本只是修正了你原有逻辑的错误,依然存在低概率卡死后几行的问题。真要做高效的数独终盘生成,一般会用回溯法填充,而不是纯随机洗牌硬凑。
内容的提问来源于stack exchange,提问作者Buttered Toast
相关产品推荐
相关产品推荐

