我正在构建一个解决数独难题的程序。这是代码:
def set_table(boxes_v, boxes_h, tiles_v, tiles_h):
""" boxes_v = boxes on vertical side of the whole table;
boxes_h = boxes on horixontal side of the whole table;
tiles_v = tiles on vertical line in each box;
tiles_h = tiles on horizontal line in each box.
"""
total_boxes = boxes_v * boxes_h
tiles_in_box = tiles_v * tiles_h
return [[{None : [False, 0]} for x in range(1, tiles_in_box + 1)] for a in range(total_boxes)]
def insert_numbers(table, numbers_and_positions):
""" table = sudoku table set up in "set_table";
numbers_and_postions = dictionary containing already given numbers and their positions in the table.
"""
noPos = numbers_and_positions
for number in noPos:
box = noPos[number][0]
tile = noPos[number][1]
table[box][tile] = {None : [True, number]}
return table
def test(table, index, number):
"Tests if number is suitable in a tile on vertical and horizontal lines"
box_index, tile_index = index
lines = {
0 : [(0,1,2), (0,3,6)],
1 : [(0,1,2), (1,4,7)],
2 : [(0,1,2), (2,5,8)],
3 : [(3,4,5), (0,3,6)],
4 : [(3,4,5), (1,4,7)],
5 : [(3,4,5), (2,5,8)],
6 : [(6,7,8), (0,3,6)],
7 : [(6,7,8), (1,4,7)],
8 : [(6,7,8), (2,5,8)]
}
box_line_h, box_line_v = lines[index[0]]
tile_line_h, tile_line_v = lines[index[1]]
################################### horizontal line tester
taken_numbers_h = []
for box_index in box_line_h:
index_counter = 0
for tile in table[box_index]:
if index_counter in tile_line_h:
taken_numbers_h.append(tile[None][1])
index_counter += 1
################################### vertical line tester
taken_numbers_v = []
for box_index in box_line_v:
index_counter = 0
for tile in table[box_index]:
if index_counter in tile_line_v:
taken_numbers_v.append(tile[None][1])
index_counter += 1
################################### box tester
taken_numbers_b = []
for tile in table[box_index]:
taken_numbers_b.append(tile[None][1])
###################################
taken_numbers = taken_numbers_h + taken_numbers_v + taken_numbers_b
if number in taken_numbers:
return True
elif number not in taken_numbers:
return False
def reset_key(dictionary, old_key, new_key, value):
"Resets a key of a dictionary to a different name"
dictionary[new_key] = dictionary[old_key]
del dictionary[old_key]
return dictionary
def solve(table):
""" Solves the sudoku puzzle
"""
box_index = 0
tile_index = 0
safe = True
def repeat():
tile[None][1] += 1
if tile[None][1] > 9:
tile[None][1] = 0
safe = False
tile_index -= 1
elif tile[None][1] <= 9:
if test(table, [box_index, tile_index], tile[None][1]) is True:
repeat()
elif test(table, [box_index, tile_index], tile[None][1]) is False:
tile_index += 1
safe = True
valid = False
while valid is not True:
box = table[box_index]
tile = box[tile_index]
if tile[None][0] is True:
if safe is True:
tile_index += 1
safe = True
elif safe is False:
tile_index -= 1
elif tile[None][0] is False:
repeat()
我在Python shell中做的是:
>>>table = set_table(3,3,3,3)
>>>table = insert_numbers(table, {0 : [0,4]})
>>>solve(table)
我期望发生的是程序将表[0](方框1)上每个字典的值更改为{None:[False,1]},{None:[False,2]},{None: [False,3]}依此类推,直到它在整个网格的第一个大框内的最后一个小框中达到9,因为代码应该导致索引错误。这是因为当它到达第一个大框中的最后一个小框时,对于数字1-8,应该出现违反规则的负面测试结果,因为它们显然已经在框中。但是,我没有看到这个错误,而是这个错误:
Traceback (most recent call last):
File "<pyshell#2>", line 1, in <module>
solve(t)
File "C:\Users\cdobr\Desktop\Sudoku Solver.py", line 153, in solve
repeat()
File "C:\Users\cdobr\Desktop\Sudoku Solver.py", line 129, in repeat
if test(table, [box_index, tile_index], tile[None][1]) is True:
UnboundLocalError: local variable 'tile_index' referenced before assignment
我应该怎么做才能解决这个问题?就好像函数内部的函数看不到父变量。
答案 0 :(得分:1)
tile_index
是一个非局部变量,但您没有指定它。您可以使用nonlocal
显式执行此操作:
def repeat():
nonlocal tile_index
为什么要为此指定nonlocal
而不是为任何其他非局部变量指定?{1}}?因为这一行:
tile_index -= 1
递归调用会导致执行此操作。但是,在进行赋值时,python假定变量是本地的,除非另有说明。没有其他非局部变量被分配给/更新,因此这不适用。