Python 数独生成算法

       0.013秒生成一个完全随机的数独矩阵,在我的电脑上。Core i5。Python。

       无关的话就不多说了,这是一个生成随机数独的算法,用Python写成的。当然,你也可以把它翻译成你喜欢用的语言,如果你有兴趣的话。这个算法,生成数独是需要概率的,但是不要担心概率的问题,像这种需要概率的问题,也就是需要时间,而,这程序运行的是特别快的,95秒运行10000次,生成了6001个数独,自己看看到底有多快吧。当然,俺的电脑也不差的嘞,Macbook Air。话休絮烦,直接来代码吧。此外,代码太小,就不喜欢注释了,但是也大概加了一点,不算难懂吧应该。

       Javascript版本的数独生成算法,参见另一篇博客,地址:https://blog.csdn.net/LiebeULQQ/article/details/82711996

       另外,项目的Github地址是https://github.com/LiebeU/Sudoku。如果这个数独生成算法对你有用的话,欢迎star me。

import random
import time


class Sudoku:
	'''
	数独生成器类, 调用Sudoku实例的 make_digits() 方法,尝试生成数独
	但,数独生成是随机的,那么,可能会成功,也许会失败
	因此,make_digits() 方法的返回值代表生成数独是否成功
	如果 make_digits() 返回 True,那么可以使用实例的 digits 属性,里面有生成的新数独
	'''
	def __init__(self):
		'''
		digits 属性里面保存着当前的数独矩阵
		'''
		self.digits = [[] for i in range(9)]

	def make_digits(self):
		'''
		尝试生成数独,返回值代表生成是否成功
		'''
		#  数独矩阵的列数组,即9个竖行
		col_lists = [[] for i in range(9)]
		#  数独矩阵的区域数组,即九宫格的几个区域
		area_lists = [[] for i in range(3)]
		#  1 - 9 的随机排列
		nine = self.random_nine()
		for i in range(9):
			col_lists[i].append(nine[i])
		area_lists[0] = nine[0:3]
		area_lists[1] = nine[3:6]
		area_lists[2] = nine[6:]

		for i in range(8):
			nine = self.random_nine()
			#  九宫格的当前格已变换,重置当前格的数字
			if i % 3 == 2:
				area_lists[0] = []
				area_lists[1] = []
				area_lists[2] = []
			for j in range(9):
				area_index = j // 3
				count = 0
				error = False
				while nine[0] in col_lists[j] or nine[0] in area_lists[area_index]:
					count += 1
					if count >= len(nine):
						error = True
						break
					nine.append(nine.pop(0))
				if error:
					return False
				first = nine.pop(0)
				col_lists[j].append(first)
				area_lists[area_index].append(first)
		self.digits = col_lists
		return True

	def random_nine(self):
		'''
		1 - 9 的随机排列
		'''
		nine = [i + 1 for i in range(9)]
		for i in range(5):
			nine.append(nine.pop(random.randint(0, 8)))
		return nine


if __name__ == '__main__':
	#  实例化数独生成器
	sudoku = Sudoku()
	#  开始生成时间
	start = time.time()
	#  不断尝试生成数独,直到生成成功
	while not sudoku.make_digits():
		pass
	#  结束时间
	end = time.time()
	print('Milliseconds:\t{0}'.format((end - start) * 1000))
	for row in sudoku.digits:
		print(row)

 

  • 9
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的 Python 数独生成器,它使用递归算法生成一个有解的数独谜题: ```python import random def generate_board(): # 创建一个 9x9 的数独棋盘 board = [[0 for i in range(9)] for j in range(9)] # 递归填充数字 fill_board(board) # 随机移除部分数字 remove_numbers(board) return board def fill_board(board): # 获取第一个空格的位置 row, col = get_next_empty_cell(board) # 如果没有空格,则数独已经填好并且有解 if row == -1: return True # 从 1 到 9 随机选择一个数字 for num in random.sample(range(1, 10), 9): # 检查数字是否可以放入当前空格 if is_valid(board, row, col, num): # 如果可以,将数字填入当前空格 board[row][col] = num # 递归填充下一个空格 if fill_board(board): return True # 如果下一个空格无法填入数字,则回溯并尝试下一个数字 board[row][col] = 0 # 如果所有数字都无法填入当前空格,则数独无解 return False def get_next_empty_cell(board): # 找到下一个空格的位置 for i in range(9): for j in range(9): if board[i][j] == 0: return i, j # 如果没有空格,则返回 (-1, -1) return -1, -1 def is_valid(board, row, col, num): # 检查行和列是否有重复数字 for i in range(9): if board[row][i] == num or board[i][col] == num: return False # 检查 3x3 的子区域是否有重复数字 sub_row = (row // 3) * 3 sub_col = (col // 3) * 3 for i in range(3): for j in range(3): if board[sub_row+i][sub_col+j] == num: return False # 如果没有重复数字,则该数字可以放入当前位置 return True def remove_numbers(board): # 随机移除一些数字,直到达到所需的空格数 num_empty = random.randint(40, 60) for i in range(num_empty): row, col = random.randint(0, 8), random.randint(0, 8) while board[row][col] == 0: row, col = random.randint(0, 8), random.randint(0, 8) board[row][col] = 0 ``` 你可以使用以下代码生成一个数独谜题: ```python board = generate_board() for row in board: print(row) ``` 输出结果将类似于: ``` [6, 4, 0, 0, 0, 0, 5, 0, 0] [0, 0, 0, 0, 0, 0, 0, 0, 9] [0, 0, 0, 0, 0, 0, 0, 2, 0] [0, 0, 0, 0, 0, 0, 0, 0, 2] [0, 0, 0, 0, 0, 0, 0, 0, 8] [0, 0, 0, 0, 0, 0, 0, 0, 6] [4, 0, 0, 0, 0, 5, 9, 0, 0] [0, 0, 0, 0, 0, 7, 0, 0, 0] [0, 0, 0, 0, 0, 0, 0, 0, 0] ``` 每个空格为 0 表示该位置为空,需要填入一个数字。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值