import sys
import pygame
from pygame.color import THECOLORS as COLORS
import random
from bulid import give_me_a_game, check
import time
import os
import threading
DIFFICULTY_LEVELS = {
"初级": {"blank_size": 30, "hint": True, "real_time_check": True},
"中级": {"blank_size": 45, "hint": True, "real_time_check": True},
"高级": {"blank_size": 60, "hint": True, "real_time_check": True}
}
best_times = {
"初级": float('inf'),
"中级": float('inf'),
"高级": float('inf')
}
game_states = {
"初级": {"start_time": 0, "elapsed_time": 0, "completed": False},
"中级": {"start_time": 0, "elapsed_time": 0, "completed": False},
"高级": {"start_time": 0, "elapsed_time": 0, "completed": False}
}
if os.name == 'nt':
import ctypes
ctypes.windll.user32.ShowWindow(ctypes.windll.kernel32.GetConsoleWindow(), 0)
def resource_path(relative_path):
if hasattr(sys, '_MEIPASS'):
return os.path.join(sys._MEIPASS, relative_path)
return os.path.join(os.path.abspath("."), relative_path)
BEST_TIMES_FILE = resource_path("resource/sudoku_best_times.txt")
def load_best_times():
try:
if os.path.exists(BEST_TIMES_FILE):
with open(BEST_TIMES_FILE, 'r', encoding='utf-8') as f:
for line in f:
difficulty, time_str = line.strip().split(':')
best_times[difficulty] = float(time_str)
except Exception as e:
print(f"加载最佳成绩失败:{e}")
def save_best_times():
try:
with open(BEST_TIMES_FILE, 'w', encoding='utf-8') as f:
for difficulty, time_val in best_times.items():
if time_val != float('inf'):
f.write(f"{difficulty}:{time_val}\n")
except Exception as e:
print(f"保存最佳成绩失败:{e}")
def draw_background():
screen.fill(COLORS['whitesmoke'])
pygame.draw.rect(screen, COLORS['lightgray'], (0, 0, 540, 40))
pygame.draw.line(screen, COLORS['darkgray'], (0, 40), (540, 40), 2)
pygame.draw.rect(screen, COLORS['white'], (0, 40, 540, 540))
for i in range(0, 4):
pygame.draw.line(screen, COLORS['black'], (0, 40 + i * 180), (540, 40 + i * 180), 3)
pygame.draw.line(screen, COLORS['black'], (i * 180, 40), (i * 180, 580), 3)
for i in range(0, 10):
if i % 3 != 0:
pygame.draw.line(screen, COLORS['lightgray'], (0, 40 + i * 60), (540, 40 + i * 60), 1)
pygame.draw.line(screen, COLORS['lightgray'], (i * 60, 40), (i * 60, 580), 1)
def draw_choose():
s = pygame.Surface((60, 60), pygame.SRCALPHA)
s.fill((0, 255, 0, 50))
screen.blit(s, (cur_j * 60, cur_i * 60 + 40))
def check_win(matrix_all, matrix):
return matrix_all == matrix
def check_color(matrix, i, j):
_matrix = [[col for col in row] for row in matrix]
_matrix[i][j] = 0
if check(_matrix, i, j, matrix[i][j]):
return COLORS['blue']
return COLORS['red']
def draw_number():
game_state = game_states[current_difficulty]
if not game_state:
return
MATRIX = game_state["matrix"]
MATRIX_ANSWER = game_state["matrix_answer"]
BLANK_IJ = game_state["blank_ij"]
for i in range(9):
for j in range(9):
if game_state.get("hint_cell") == (i, j) and pygame.time.get_ticks() < game_state.get("hint_end_time", 0):
value = MATRIX_ANSWER[i][j]
color = COLORS['purple']
txt = font.render(str(value), True, color)
x, y = j * 60 + 30, i * 60 + 70
screen.blit(txt, (x - txt.get_width() // 2, y - txt.get_height() // 2))
continue
value = MATRIX[i][j]
if value == 0:
continue
if (i, j) not in BLANK_IJ:
color = COLORS['black']
else:
color = COLORS['blue']
if DIFFICULTY_SETTINGS['real_time_check'] and DIFFICULTY_SETTINGS['hint']:
color = check_color(MATRIX, i, j)
txt = font.render(str(value), True, color)
x, y = j * 60 + 30, i * 60 + 70
screen.blit(txt, (x - txt.get_width() // 2, y - txt.get_height() // 2))
def draw_difficulty_buttons():
for i, level in enumerate(["初级", "中级", "高级"]):
color = COLORS['lightgreen'] if current_difficulty == level else COLORS['lightblue']
pygame.draw.rect(screen, color, (i * 180, 0, 180, 40))
pygame.draw.rect(screen, COLORS['black'], (i * 180, 0, 180, 40), 1)
try:
txt = font_small.render(level, True, COLORS['black'])
except:
level_en = ["Easy", "Medium", "Hard"][i]
txt = font_small.render(level_en, True, COLORS['black'])
x, y = i * 180 + 90, 20
screen.blit(txt, (x - txt.get_width() // 2, y - txt.get_height() // 2))
def draw_context():
game_state = game_states[current_difficulty]
if not game_state:
return
txt = font_tiny.render(f'空白:{game_state["cur_blank_size"]}', True, COLORS['black'])
screen.blit(txt, (10, 610))
txt = font_tiny.render(f'操作:{game_state["cur_change_size"]}', True, COLORS['black'])
screen.blit(txt, (150, 610))
pygame.draw.rect(screen, COLORS['lightblue'], (350, 585, 80, 30))
pygame.draw.rect(screen, COLORS['black'], (350, 585, 80, 30), 1)
try:
txt_reset = font_tiny.render('重置 (R)', True, COLORS['black'])
except:
txt_reset = font_tiny.render('Reset', True, COLORS['black'])
screen.blit(txt_reset, (390 - txt_reset.get_width() // 2, 600 - txt_reset.get_height() // 2))
pygame.draw.rect(screen, COLORS['lightgreen'], (440, 585, 80, 30))
pygame.draw.rect(screen, COLORS['black'], (440, 585, 80, 30), 1)
try:
txt_records = font_tiny.render('成绩', True, COLORS['black'])
except:
txt_records = font_tiny.render('Records', True, COLORS['black'])
screen.blit(txt_records, (480 - txt_records.get_width() // 2, 600 - txt_records.get_height() // 2))
pygame.draw.rect(screen, COLORS['lightyellow'], (350, 625, 80, 25))
pygame.draw.rect(screen, COLORS['black'], (350, 625, 80, 25), 1)
try:
txt_hint = font_tiny.render('提示 (T)', True, COLORS['black'])
except:
txt_hint = font_tiny.render('Hint', True, COLORS['black'])
screen.blit(txt_hint, (390 - txt_hint.get_width() // 2, 637 - txt_hint.get_height() // 2))
pygame.draw.rect(screen, COLORS['lightpink'], (440, 625, 80, 25))
pygame.draw.rect(screen, COLORS['black'], (440, 625, 80, 25), 1)
try:
txt_help = font_tiny.render('说明 (H)', True, COLORS['black'])
except:
txt_help = font_tiny.render('Help', True, COLORS['black'])
screen.blit(txt_help, (480 - txt_help.get_width() // 2, 637 - txt_help.get_height() // 2))
try:
help_txt = font_tiny.render('方向键移动 | 数字键填写 | 空格/DEL 清除', True, COLORS['darkgray'])
except:
help_txt = font_tiny.render('Arrow:Move | Num:Input | Space/DEL:Clear', True, COLORS['darkgray'])
screen.blit(help_txt, (10, 655))
def draw_message(message, color):
msg_surface = font_small.render(message, True, color)
msg_rect = msg_surface.get_rect(center=(270, 610))
s = pygame.Surface((540, 40), pygame.SRCALPHA)
s.fill((255, 255, 255, 200))
screen.blit(s, (0, 590))
screen.blit(msg_surface, msg_rect)
pygame.display.flip()
pygame.time.delay(1500)
pygame.draw.rect(screen, COLORS['whitesmoke'], (0, 590, 540, 110))
def reset_game(difficulty):
try:
draw_message("正在生成新游戏...", COLORS['blue'])
except:
draw_message("Generating...", COLORS['blue'])
pygame.display.flip()
start_time = time.perf_counter()
MATRIX_ANSWER, MATRIX, BLANK_IJ = give_me_a_game(blank_size=DIFFICULTY_LEVELS[difficulty]["blank_size"])
elapsed = time.perf_counter() - start_time
print(f"生成时间:{elapsed:.6f}秒")
cur_blank_size = sum(1 for row in MATRIX for cell in row if cell == 0)
cur_change_size = 0
game_states[difficulty] = {
"matrix_answer": MATRIX_ANSWER,
"matrix": MATRIX,
"blank_ij": set(BLANK_IJ),
"cur_blank_size": cur_blank_size,
"cur_change_size": cur_change_size,
"hint_cell": None,
"hint_end_time": 0,
"show_reset_confirm": False,
"start_time": pygame.time.get_ticks(),
"completed": False
}
return game_states[difficulty]
def check_solution():
game_state = game_states[current_difficulty]
if not game_state:
return False
MATRIX = game_state["matrix"]
MATRIX_ANSWER = game_state["matrix_answer"]
for i in range(9):
for j in range(9):
if MATRIX[i][j] != MATRIX_ANSWER[i][j]:
return False
return True
def show_hint():
game_state = game_states[current_difficulty]
if not game_state:
return
if (cur_i, cur_j) not in game_state["blank_ij"]:
try:
draw_message("请选择空白格子", COLORS['red'])
except:
draw_message("Select a blank cell", COLORS['red'])
return
game_state["hint_cell"] = (cur_i, cur_j)
game_state["hint_end_time"] = pygame.time.get_ticks() + 2000
try:
draw_message("显示正确答案 1 秒", COLORS['purple'])
except:
draw_message("Showing answer for 2 seconds", COLORS['purple'])
def show_help_screen():
help_screen = pygame.display.set_mode((540, 700))
pygame.display.set_caption("游戏说明")
try:
title_font = pygame.font.SysFont('Microsoft YaHei', 30)
text_font = pygame.font.SysFont('Microsoft YaHei', 20)
except:
title_font = pygame.font.SysFont(None, 30)
text_font = pygame.font.SysFont(None, 20)
try:
title = title_font.render("数独游戏规则", True, COLORS['black'])
except:
title = title_font.render("Sudoku Rules", True, COLORS['black'])
texts = [
"游戏目标:在 9x9 的格子中填入数字 1-9,使得:",
"- 每一行包含 1-9 的所有数字,且不重复;",
"- 每一列包含 1-9 的所有数字,且不重复;",
"- 每一个 3x3 的宫格包含 1-9 的所有数字,且不重复。",
"",
"操作说明:",
"- 方向键或鼠标点击选择格子;",
"- 数字键 1-9 填写数字;",
"- 空格键、DEL 或 Backspace 删除数字;",
"- 顶部按钮切换难度;",
"- 重置:生成新游戏;",
"- 提交:检查解答是否正确;",
"- 提示:显示当前格子的正确答案(1 秒)。",
"",
"难度说明:",
"- 初级:30 个空格",
"- 中级:45 个空格",
"- 高级:60 个空格",
"",
"所有难度都有实时提示:",
"- 正确数字显示为蓝色",
"- 错误数字显示为红色",
"",
"按任意键返回游戏..."
]
running = True
while running:
help_screen.fill(COLORS['whitesmoke'])
help_screen.blit(title, (270 - title.get_width() // 2, 10))
y_pos = 70
for text in texts:
try:
rendered = text_font.render(text, True, COLORS['black'])
except:
rendered = text_font.render(text, True, COLORS['black'])
help_screen.blit(rendered, (20, y_pos))
y_pos += 25
pygame.display.flip()
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
pygame.quit()
sys.exit()
elif event.type == pygame.KEYDOWN or event.type == pygame.MOUSEBUTTONDOWN:
running = False
pygame.display.set_mode(SIZE)
pygame.display.set_caption("数独游戏")
def show_loading_screen():
screen.fill(COLORS['whitesmoke'])
try:
loading_text = font_large.render("数独游戏加载中...", True, COLORS['blue'])
except:
loading_text = font_large.render("Sudoku Loading...", True, COLORS['blue'])
text_rect = loading_text.get_rect(center=(SIZE[0] // 2, SIZE[1] // 2))
screen.blit(loading_text, text_rect)
pygame.display.flip()
def initialize_game_in_background():
def background_task():
for difficulty in DIFFICULTY_LEVELS:
reset_game(difficulty)
thread = threading.Thread(target=background_task)
thread.daemon = True
thread.start()
while thread.is_alive():
show_loading_screen()
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
pygame.time.delay(50)
def show_records():
records_screen = pygame.display.set_mode((540, 700))
pygame.display.set_caption("成绩记录")
try:
title_font = pygame.font.SysFont('Microsoft YaHei', 40)
text_font = pygame.font.SysFont('Microsoft YaHei', 30)
hint_font = pygame.font.SysFont('Microsoft YaHei', 24)
except:
title_font = pygame.font.SysFont(None, 40)
text_font = pygame.font.SysFont(None, 30)
hint_font = pygame.font.SysFont(None, 24)
load_best_times()
running = True
while running:
records_screen.fill(COLORS['whitesmoke'])
try:
title = title_font.render("最佳成绩记录", True, COLORS['blue'])
except:
title = title_font.render("Best Records", True, COLORS['blue'])
records_screen.blit(title, (270 - title.get_width() // 2, 40))
y_pos = 120
for level in ["初级", "中级", "高级"]:
time_val = best_times[level]
if time_val == float('inf'):
time_str = "暂无记录"
else:
time_str = f"{time_val:.3f}秒"
try:
level_text = text_font.render(f"{level}:", True, COLORS['black'])
time_text = text_font.render(time_str, True, COLORS['darkblue'])
except:
level_text = text_font.render(f"{level}:", True, COLORS['black'])
time_text = text_font.render(time_str, True, COLORS['darkblue'])
records_screen.blit(level_text, (150, y_pos))
records_screen.blit(time_text, (260, y_pos))
y_pos += 70
pygame.draw.line(records_screen, COLORS['lightgray'], (50, y_pos + 20), (490, y_pos + 20), 2)
y_pos += 50
try:
hint1 = hint_font.render("提示:", True, COLORS['darkred'])
hint2 = hint_font.render("1. 成绩按不同难度分别记录", True, COLORS['black'])
hint3 = hint_font.render("2. 只记录最快完成时间", True, COLORS['black'])
hint4 = hint_font.render("3. 空白格子越多难度越高", True, COLORS['black'])
except:
hint1 = hint_font.render("Note:", True, COLORS['darkred'])
hint2 = hint_font.render("1. Records are saved per difficulty", True, COLORS['black'])
hint3 = hint_font.render("2. Only the fastest time is saved", True, COLORS['black'])
hint4 = hint_font.render("3. More blanks = higher difficulty", True, COLORS['black'])
records_screen.blit(hint1, (90, y_pos))
records_screen.blit(hint2, (120, y_pos + 40))
records_screen.blit(hint3, (120, y_pos + 80))
records_screen.blit(hint4, (120, y_pos + 120))
try:
hint = hint_font.render("按任意键返回...", True, COLORS['darkgray'])
except:
hint = hint_font.render("Press any key to return...", True, COLORS['darkgray'])
records_screen.blit(hint, (270 - hint.get_width() // 2, 620))
pygame.display.flip()
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
pygame.quit()
sys.exit()
elif event.type == pygame.KEYDOWN or event.type == pygame.MOUSEBUTTONDOWN:
running = False
pygame.display.set_mode(SIZE)
pygame.display.set_caption("数独游戏")
def draw_reset_confirm_dialog():
s = pygame.Surface(SIZE, pygame.SRCALPHA)
s.fill((0, 0, 0, 128))
screen.blit(s, (0, 0))
dialog_rect = pygame.Rect(120, 250, 300, 150)
pygame.draw.rect(screen, COLORS['white'], dialog_rect)
pygame.draw.rect(screen, COLORS['black'], dialog_rect, 2)
try:
title = font_small.render("确认重置游戏吗?", True, COLORS['black'])
except:
title = font_small.render("Confirm Reset Game?", True, COLORS['black'])
screen.blit(title, (dialog_rect.centerx - title.get_width() // 2, dialog_rect.y + 20))
confirm_rect = pygame.Rect(dialog_rect.x + 50, dialog_rect.y + 80, 80, 40)
pygame.draw.rect(screen, COLORS['lightgreen'], confirm_rect)
pygame.draw.rect(screen, COLORS['black'], confirm_rect, 1)
try:
confirm_text = font_tiny.render("确认", True, COLORS['black'])
except:
confirm_text = font_tiny.render("Yes", True, COLORS['black'])
screen.blit(confirm_text, (confirm_rect.centerx - confirm_text.get_width() // 2, confirm_rect.centery - confirm_text.get_height() // 2))
cancel_rect = pygame.Rect(dialog_rect.x + 170, dialog_rect.y + 80, 80, 40)
pygame.draw.rect(screen, COLORS['lightcoral'], cancel_rect)
pygame.draw.rect(screen, COLORS['black'], cancel_rect, 1)
try:
cancel_text = font_tiny.render("取消", True, COLORS['black'])
except:
cancel_text = font_tiny.render("No", True, COLORS['black'])
screen.blit(cancel_text, (cancel_rect.centerx - cancel_text.get_width() // 2, cancel_rect.centery - cancel_text.get_height() // 2))
return confirm_rect, cancel_rect
if __name__ == "__main__":
pygame.init()
try:
font = pygame.font.SysFont('Microsoft YaHei', 36)
font_small = pygame.font.SysFont('Microsoft YaHei', 24)
font_tiny = pygame.font.SysFont('Microsoft YaHei', 20)
font_large = pygame.font.SysFont('Microsoft YaHei', 48)
except:
try:
font = pygame.font.SysFont('SimHei', 36)
font_small = pygame.font.SysFont('SimHei', 24)
font_tiny = pygame.font.SysFont('SimHei', 20)
font_large = pygame.font.SysFont('SimHei', 48)
except:
font = pygame.font.SysFont(None, 36)
font_small = pygame.font.SysFont(None, 24)
font_tiny = pygame.font.SysFont(None, 20)
font_large = pygame.font.SysFont(None, 48)
current_difficulty = "初级"
DIFFICULTY_SETTINGS = DIFFICULTY_LEVELS[current_difficulty]
SIZE = (540, 700)
screen = pygame.display.set_mode(SIZE)
pygame.display.set_caption("数独游戏")
show_loading_screen()
initialize_game_in_background()
cur_i, cur_j = 0, 0
reset_confirm_active = False
running = True
load_best_times()
while running:
game_state = game_states[current_difficulty]
if not game_state:
continue
DIFFICULTY_SETTINGS = DIFFICULTY_LEVELS[current_difficulty]
if game_state.get("hint_end_time", 0) > 0 and pygame.time.get_ticks() > game_state["hint_end_time"]:
game_state["hint_cell"] = None
game_state["hint_end_time"] = 0
draw_background()
draw_difficulty_buttons()
draw_number()
draw_choose()
draw_context()
confirm_rect = cancel_rect = None
if reset_confirm_active:
confirm_rect, cancel_rect = draw_reset_confirm_dialog()
pygame.display.flip()
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
break
if reset_confirm_active:
if event.type == pygame.MOUSEBUTTONDOWN:
x, y = event.pos
if confirm_rect.collidepoint(x, y):
game_state = reset_game(current_difficulty)
try:
draw_message("游戏已重置", COLORS['blue'])
except:
draw_message("Game Reset", COLORS['blue'])
reset_confirm_active = False
elif cancel_rect.collidepoint(x, y) or not confirm_rect.collidepoint(x, y):
reset_confirm_active = False
continue
if event.type == pygame.MOUSEBUTTONDOWN:
x, y = event.pos
if y <= 40:
if x < 180:
current_difficulty = "初级"
elif x < 360:
current_difficulty = "中级"
else:
current_difficulty = "高级"
cur_i, cur_j = 0, 0
DIFFICULTY_SETTINGS = DIFFICULTY_LEVELS[current_difficulty]
try:
draw_message(f"已切换到{current_difficulty}难度", COLORS['blue'])
except:
draw_message(f"Switched to {current_difficulty}", COLORS['blue'])
elif 40 <= y < 580:
cur_j = x // 60
cur_i = (y - 40) // 60
elif 350 <= x <= 430 and 585 <= y <= 615:
reset_confirm_active = True
elif 440 <= x <= 520 and 585 <= y <= 615:
show_records()
elif 350 <= x <= 430 and 625 <= y <= 650:
show_hint()
elif 440 <= x <= 520 and 625 <= y <= 650:
show_help_screen()
elif event.type == pygame.KEYUP:
if event.key == pygame.K_UP and cur_i > 0:
cur_i -= 1
elif event.key == pygame.K_DOWN and cur_i < 8:
cur_i += 1
elif event.key == pygame.K_LEFT and cur_j > 0:
cur_j -= 1
elif event.key == pygame.K_RIGHT and cur_j < 8:
cur_j += 1
elif event.key in [pygame.K_1, pygame.K_2, pygame.K_3, pygame.K_4, pygame.K_5, pygame.K_6, pygame.K_7, pygame.K_8, pygame.K_9] and (cur_i, cur_j) in game_state["blank_ij"]:
if game_state["matrix"][cur_i][cur_j] != int(chr(event.key)):
game_state["matrix"][cur_i][cur_j] = int(chr(event.key))
game_state["cur_blank_size"] = sum(1 for row in game_state["matrix"] for cell in row if cell == 0)
game_state["cur_change_size"] += 1
elif event.key in [pygame.K_DELETE, pygame.K_BACKSPACE, pygame.K_SPACE, pygame.K_0] and (cur_i, cur_j) in game_state["blank_ij"]:
if game_state["matrix"][cur_i][cur_j] != 0:
game_state["matrix"][cur_i][cur_j] = 0
game_state["cur_blank_size"] = sum(1 for row in game_state["matrix"] for cell in row if cell == 0)
game_state["cur_change_size"] += 1
elif event.key == pygame.K_r:
reset_confirm_active = True
elif event.key == pygame.K_t:
show_hint()
elif event.key == pygame.K_h:
show_help_screen()
elif event.key == pygame.K_ESCAPE and reset_confirm_active:
reset_confirm_active = False
if not reset_confirm_active and check_win(game_state["matrix_answer"], game_state["matrix"]):
game_state["completed"] = True
elapsed = (pygame.time.get_ticks() - game_state["start_time"]) / 1000.0
if elapsed < best_times[current_difficulty]:
best_times[current_difficulty] = elapsed
save_best_times()
message = f"恭喜!新纪录:{elapsed:.1f}秒"
else:
message = f"完成时间:{elapsed:.1f}秒"
draw_message(message, COLORS['green'])
pygame.time.delay(3000)
game_state = reset_game(current_difficulty)
pygame.quit()
import random
import time
def print_matrix(matrix):
print('—' * 19)
for row in matrix:
print('|' + ' '.join([str(col) if col != 0 else ' ' for col in row]) + '|')
print('—' * 19)
def shuffle_number(_list):
random.shuffle(_list)
return _list
def check(matrix, i, j, number):
if number in matrix[i]:
return False
for row in matrix:
if row[j] == number:
return False
group_i, group_j = i // 3, j // 3
for x in range(group_i * 3, group_i * 3 + 3):
for y in range(group_j * 3, group_j * 3 + 3):
if matrix[x][y] == number:
return False
return True
def solve_sudoku(matrix):
for i in range(9):
for j in range(9):
if matrix[i][j] == 0:
for num in shuffle_number(number_list[:]):
if check(matrix, i, j, num):
matrix[i][j] = num
if solve_sudoku(matrix):
return matrix
matrix[i][j] = 0
return None
def generate_full_sudoku():
empty_grid = [[0] * 9 for _ in range(9)]
first_row = shuffle_number(number_list[:])
empty_grid[0] = first_row
solution = solve_sudoku(empty_grid)
return solution
def give_me_a_game(blank_size=30):
solution = generate_full_sudoku()
if solution is None:
solution = [
[5, 3, 4, 6, 7, 8, 9, 1, 2],
[6, 7, 2, 1, 9, 5, 3, 4, 8],
[1, 9, 8, 3, 4, 2, 5, 6, 7],
[8, 5, 9, 7, 6, 1, 4, 2, 3],
[4, 2, 6, 8, 5, 3, 7, 9, 1],
[7, 1, 3, 9, 2, 4, 8, 5, 6],
[9, 6, 1, 5, 3, 7, 2, 8, 4],
[2, 8, 7, 4, 1, 9, 6, 3, 5],
[3, 4, 5, 2, 8, 6, 1, 7, 9]
]
blank_grid = [row[:] for row in solution]
blank_size = min(max(blank_size, 10), 60)
all_positions = [(i, j) for i in range(9) for j in range(9)]
blank_positions = random.sample(all_positions, blank_size)
for i, j in blank_positions:
blank_grid[i][j] = 0
time.sleep(0.001)
print_matrix(solution)
return solution, blank_grid, blank_positions
number_list = [1, 2, 3, 4, 5, 6, 7, 8, 9]