import random import numpy as np class Sudo: def __init__(self): self.sudo = np.zeros((9, 9), dtype=int) self.base_sudo = np.zeros((9, 9), dtype=int) self.base_sudo_list = [] self.base_sudo_list_index = 0 self.base_sudo_list_length = 0 self.base_sudo_list_index_list = [] self.base_sudo_list_index_list_length = 0 self.subject = None self.del_cnt = 0 def get_del_cnt(self): return self.del_cnt def createSubjectByLevel(self, level): max_clear_count = 64 min_clear_count = 14 each_level_count = (max_clear_count - min_clear_count) / 5 # 难度对应删除数 level_start = min_clear_count + (level - 1) * each_level_count self.del_cnt = random.randrange(level_start, level_start + each_level_count) self.create_base_sudo() self.random_sudo(50) self.get_sudo_subject(self.del_cnt) return self.subject def create_base_sudo(self): # 9*9的二维矩阵,每个格子默认值为0 self.sudo = np.zeros((9, 9), dtype=int) # 随机生成起始的基数(1 ~ 9) num = random.randrange(9) + 1 # 遍历从左到右,从上到下逐个遍历 for row_index in range(9): for col_index in range(9): # 获取该格子对应的行、列、九宫格 sudo_row = self.get_row(row_index) sudo_col = self.get_col(col_index) sudo_block = self.get_block(row_index, col_index) # 如果该数字已经存在于对应的行、列、九宫格 # 则继续判断下一个候选数字,直到没有重复 while num in sudo_row or num in sudo_col or num in sudo_block: num = num % 9 + 1 # 赋值 self.sudo[row_index, col_index] = num num = num % 9 + 1 return self.sudo def get_row(self, row): return self.sudo[row, :] def get_col(self, col): return self.sudo[:, col] def get_block(self, row, col): row_start = row // 3 * 3 col_start = col // 3 * 3 return self.sudo[row_start: row_start + 3, col_start: col_start + 3] def print_sudo(self): for row_index, row in enumerate(self.sudo): if row_index % 3 == 0 and row_index != 0: print('-' * (9 + 8 + 4)) row = list(map(str, row.tolist())) row.insert(6, '|') row.insert(3, '|') row_str = ' '.join(row) print(row_str.replace('0', ' ')) def random_sudo(self, times): for _ in range(times): # 随机交换两行 rand_row_base = random.randrange(3) * 3 # 从0,3,6 随机取一个 rand_rows = random.sample(range(3), 2) # 从 0,1,2中随机取两个数 row_1 = rand_row_base + rand_rows[0] row_2 = rand_row_base + rand_rows[1] self.sudo[[row_1, row_2], :] = self.sudo[[row_2, row_1], :] # 随机交换两列 rand_col_base = random.randrange(3) * 3 rand_cols = random.sample(range(3), 2) col_1 = rand_col_base + rand_cols[0] col_2 = rand_col_base + rand_cols[1] self.sudo[:, [col_1, col_2]] = self.sudo[:, [col_2, col_1]] def get_sudo_subject(self, del_nums): self.subject = self.sudo.copy() # 随机擦除(从0到80,随机取要删除的个数) clears = random.sample(range(81), del_nums) for clear_index in clears: # 把0到80的坐标转化成行和列索引 # 这样就不会重复删除同一个格子的数字 row_index = clear_index // 9 col_index = clear_index % 9 self.subject[row_index, col_index] = 0 return self.subject # 获取格子所在的行的全部格子 def get_row(sudo, row): return sudo[row, :] # 获取格子所在的列的全部格子 def get_col(sudo, col): return sudo[:, col] # 获取格子所在的九宫格的全部格子 def get_block(sudo, row, col): row_start = row // 3 * 3 col_start = col // 3 * 3 return sudo[row_start: row_start + 3, col_start: col_start + 3] # # # # 打印数独 # def print_sudo(sudo): # for row_index, row in enumerate(sudo): # if row_index % 3 == 0 and row_index != 0: # print('-' * (9 + 8 + 4)) # row = list(map(str, row.tolist())) # row.insert(6, '|') # row.insert(3, '|') # row_str = ' '.join(row) # print(row_str.replace('0', ' ')) # # def create_base_sudo(): # # 9*9的二维矩阵,每个格子默认值为0 # sudo = np.zeros((9, 9), dtype=int) # # 随机生成起始的基数(1 ~ 9) # num = random.randrange(9) + 1 # # # 遍历从左到右,从上到下逐个遍历 # for row_index in range(9): # for col_index in range(9): # # 获取该格子对应的行、列、九宫格 # sudo_row = get_row(sudo, row_index) # sudo_col = get_col(sudo, col_index) # sudo_block = get_block(sudo, row_index, col_index) # # # 如果该数字已经存在于对应的行、列、九宫格 # # 则继续判断下一个候选数字,直到没有重复 # while num in sudo_row or num in sudo_col or num in sudo_block: # num = num % 9 + 1 # # # 赋值 # sudo[row_index, col_index] = num # num = num % 9 + 1 # return sudo # # # def random_sudo(sudo, times): # for _ in range(times): # # 随机交换两行 # rand_row_base = random.randrange(3) * 3 # 从0,3,6 随机取一个 # rand_rows = random.sample(range(3), 2) # 从 0,1,2中随机取两个数 # row_1 = rand_row_base + rand_rows[0] # row_2 = rand_row_base + rand_rows[1] # sudo[[row_1, row_2], :] = sudo[[row_2, row_1], :] # # # 随机交换两列 # rand_col_base = random.randrange(3) * 3 # rand_cols = random.sample(range(3), 2) # col_1 = rand_col_base + rand_cols[0] # col_2 = rand_col_base + rand_cols[1] # sudo[:, [col_1, col_2]] = sudo[:, [col_2, col_1]] # # # def get_sudo_subject(sudo, del_nums): # subject = sudo.copy() # # # 随机擦除(从0到80,随机取要删除的个数) # clears = random.sample(range(81), del_nums) # for clear_index in clears: # # 把0到80的坐标转化成行和列索引 # # 这样就不会重复删除同一个格子的数字 # row_index = clear_index // 9 # col_index = clear_index % 9 # subject[row_index, col_index] = 0 # return subject #