前面让DeepSeek独立自主做了一个数独生成器,它生成大的数独效率较低,观察如下结果:
1 2 3 4 5 6 7 8 9
4 5 6 7 8 9 1 2 3
7 8 9 1 2 3 4 5 6
2 1 4 3 6 5 8 9 7
3 6 5 8 9 7 2 1 4
8 9 7 2 1 4 3 6 5
5 3 1 6 4 2 9 7 8
6 4 2 9 7 8 5 3 1
9 7 8 5 3 1 6 4 2
把数字3个一组顺序编排,可以生成有规律的数独答案,在此基础上,交换组内的行不影响结果,比如1、2行互换,仍然是有效的。如下所示:
4 5 6 7 8 9 1 2 3
1 2 3 4 5 6 7 8 9
7 8 9 1 2 3 4 5 6
2 1 4 3 6 5 8 9 7
3 6 5 8 9 7 2 1 4
8 9 7 2 1 4 3 6 5
5 3 1 6 4 2 9 7 8
6 4 2 9 7 8 5 3 1
9 7 8 5 3 1 6 4 2
交换组内的列也是如此,依据此思路,随机交换几次行列,再随机去掉多余的数来生成数独题目。16x16则4个一组(即一个宫)。
让DeepSeek按照上述思路重新编写,一举成功。
import random
import csv
def generate_sudoku_template(n):
box_size = int(n ** 0.5)
grid = [[0 for _ in range(n)] for _ in range(n)]
for i in range(n):
for j in range(n):
grid[i][j] = (i * box_size + i // box_size + j) % n + 1
return grid
def shuffle_grid(grid, n, shuffle_times=10):
box_size = int(n ** 0.5)
for _ in range(shuffle_times):
# 交换组内的行
block = random.randint(0, box_size - 1)
row1 = random.randint(0, box_size - 1)
row2 = random.randint(0, box_size - 1)
r1 = block * box_size + row1
r2 = block * box_size + row2
grid[r1], grid[r2] = grid[r2], grid[r1]
# 交换组内的列
block = random.randint(0, box_size - 1)
col1 = random.randint(0, box_size - 1)
col2 = random.randint(0, box_size - 1)
c1 = block * box_size + col1
c2 = block * box_size + col2
for i in range(n):
grid[i][c1], grid[i][c2] = grid[i][c2], grid[i][c1]
return grid
def create_puzzle(grid, n, q):
total_cells = n * n
if q > total_cells:
q = total_cells
puzzle = [[grid[i][j] for j in range(n)] for i in range(n)]
positions = [(i, j) for i in range(n) for j in range(n)]
random.shuffle(positions)
for i in range(total_cells - q):
row, col = positions[i]
puzzle[row][col] = 0
return puzzle
def convert_to_char(num, n, char_type):
if num == 0:
return '-'
if char_type == 'digit':
return str(num)
elif char_type == 'upper':
if num <= 26:
return chr(num - 1 + ord('A'))
else:
return str(num)
elif char_type == 'mixed':
if num <= 26:
return chr(num - 1 + ord('A'))
elif num <= 52:
return chr(num - 27 + ord('a'))
else:
return str(num)
def save_sudoku(puzzle, n, char_type, csv_filename, txt_filename):
# 保存CSV格式
with open(csv_filename, 'w', newline='') as csvfile:
writer = csv.writer(csvfile)
for row in puzzle:
csv_row = []
for num in row:
if num == 0:
csv_row.append('*')
else:
csv_row.append(str(num))
writer.writerow(csv_row)
# 保存字符格式
with open(txt_filename, 'w') as txtfile:
for row in puzzle:
char_row = []
for num in row:
char_row.append(convert_to_char(num, n, char_type))
txtfile.write(''.join(char_row) + '\n')
if __name__ == "__main__":
n = 9
q = 30
char_type = 'upper'
template = generate_sudoku_template(n)
shuffled = shuffle_grid(template, n, shuffle_times=20)
puzzle = create_puzzle(shuffled, n, q)
save_sudoku(puzzle, n, char_type, 'sudoku.csv', 'sudoku.txt')
以下是它生成的16x16(30)的数独,DLX程序求解结果随后,所以它是有效的。
---N--------L---
-----F--------O-
-------L---P-A--
LI--------------
----------------
-----------M----
--H---L-----E---
-N-------F-I---K
--------D-------
B--P------------
--------P-------
F---G-----------
----L--O--------
--------I-------
----P-B-----K---
----------N-----
EPFNAHGBJMIOLKCD
HCJDIFMPLNKABGOE
KGBMNCOLFDEPJAHI
LIAOEDJKCHBGFPNM
DKCAFINMOPJEHLBG
OJGBKPHENLAMIFDC
MFHIOJLGKCDBENPA
PNLECBDAHFGIMOJK
NEIGMLPJDAFCOBKH
BLOPDKCIEGHNAJMF
AMKCBOFHPILJDEGN
FHDJGEANMBOKPCIL
CDNKLMIOAJPFGHEB
JBPLHGKFIECDNMAO
IAEFPNBCGOMHKDLJ
GOMHJAEDBKNLCIFP
以上程序生成最大的数独支持到49x49,更大的无法用大小写字母数字字符表示了。

844

被折叠的 条评论
为什么被折叠?



