今天我妹突然拿了个题目给我写,不难,但挺有意思的

经典的数独游戏
突发奇想尝试写了个py脚本,调用gui库实现面板功能,求数独:
import tkinter as tk
from tkinter import messagebox
def is_valid(board, row, col, num):
for i in range(9):
if board[row][i] == num:
return False
for i in range(9):
if board[i][col] == num:
return False
start_row = (row // 3) * 3
start_col = (col // 3) * 3
for i in range(3):
for j in range(3):
if board[start_row + i][start_col + j] == num:
return False
return True
def solve_sudoku(board):
for row in range(9):
for col in range(9):
if board[row][col] == '*':
for num in range(1, 10):
num = str(num)
if is_valid(board, row, col, num):
board[row][col] = num
if solve_sudoku(board):
return True
board[row][col] = '*'
return False
return True
def get_board_from_input(entries):
board = []
for row in range(9):
board_row = []
for col in range(9):
value = entries[row][col].get().strip()
if value == '' or value == '*':
board_row.append('*')
else:
board_row.append(value)
board.append(board_row)
return board
def show_result(board):
result = '\n'.join([' '.join(row) for row in board])
messagebox.showinfo("数独解", f"解答结果:\n{result}")
def on_submit(entries):
board = get_board_from_input(entries)
solve_sudoku(board)
show_result(board)
def create_gui():
window = tk.Tk()
window.title("数独解答器")
entries = []
for row in range(9):
row_entries = []
for col in range(9):
entry = tk.Entry(window, width=5, font=("Arial", 14), justify='center')
entry.grid(row=row, column=col, padx=5, pady=5)
row_entries.append(entry)
entries.append(row_entries)
default_board = [
['8', ' ', '6', ' ', ' ', '3', ' ', '9', ' '],
[' ', '4', ' ', ' ', '1', ' ', ' ', '6', '8'],
['2', ' ', ' ', '8', '7', ' ', ' ', ' ', '5'],
['1', ' ', '8', ' ', ' ', '5', ' ', '2', ' '],
[' ', '3', ' ', '1', ' ', ' ', ' ', '5', ' '],
['7', ' ', '5', ' ', '3', ' ', '9', ' ', ' '],
[' ', '2', '1', ' ', ' ', '7', ' ', '4', ' '],
['6', ' ', ' ', ' ', '2', ' ', '8', ' ', ' '],
[' ', '8', '7', '6', ' ', '4', ' ', ' ', '3']
]
for i in range(9):
for j in range(9):
entries[i][j].insert(0, default_board[i][j])
submit_button = tk.Button(window, text="确定", font=("Arial", 14), command=lambda: on_submit(entries))
submit_button.grid(row=9, column=4, columnspan=2, pady=10)
window.mainloop()
create_gui()
gui样式:

以下为代码详解:
1. 导入库
import tkinter as tk
from tkinter import messagebox
tkinter是 Python 标准库中的一个 GUI 库,用于创建图形界面。这里导入tkinter和其中的messagebox模块,后者用来显示弹出式消息框。
2. 检查数独是否合法
def is_valid(board, row, col, num):
for i in range(9):
if board[row][i] == num:
return False
for i in range(9):
if board[i][col] == num:
return False
start_row = (row // 3) * 3
start_col = (col // 3) * 3
for i in range(3):
for j in range(3):
if board[start_row + i][start_col + j] == num:
return False
return True
这个函数用来检查当前数独棋盘上放置的数字是否符合数独规则。
数独规则要求:
- 同一行不能有重复的数字。
- 同一列不能有重复的数字。
- 同一个 3x3 的小宫格里不能有重复的数字。
3. 求解数独(回溯法)
def solve_sudoku(board):
for row in range(9):
for col in range(9):
if board[row][col] == '*':
for num in range(1, 10):
num = str(num)
if is_valid(board, row, col, num):
board[row][col] = num
if solve_sudoku(board):
return True
board[row][col] = '*'
return False
return True
回溯法是用来求解数独的常见算法,当然,你也基本上可以把它理解为穷举法
它的基本思路是:
- 从数独的每个空格(
*)开始,尝试填入一个合法的数字(1 到 9)。 - 如果填入的数字合法(通过
is_valid函数验证),继续递归填充下一个空格。 - 如果所有空格都成功填充完毕,则返回
True,表示找到了一个解。 - 如果某个数字不合法,回溯到上一步,尝试其他可能的数字。
- 如果没有数字可填,则返回
False。
非常的简单对吧,就是穷举,简单暴力~
4. 获取用户输入的棋盘数据
def get_board_from_input(entries):
board = []
for row in range(9):
board_row = []
for col in range(9):
value = entries[row][col].get().strip()
if value == '' or value == '*':
board_row.append('*')
else:
board_row.append(value)
board.append(board_row)
return board
这个函数用于从 GUI 界面的输入框中获取数独棋盘的值。每个输入框的值通过 .get() 方法获得,并去掉两端的空格(.strip())。
代码逻辑解释:
- 如果用户没有输入值,或输入的是
*,就将这个位置标记为空格(*)。 - 如果用户输入的是数字,就将该数字作为当前格子的值。
(用户使用”*“来填写到空缺位作为标记,以免看错看掉)
5. 显示解答结果
def show_result(board):
result = '\n'.join([' '.join(row) for row in board])
messagebox.showinfo("数独解", f"解答结果:\n{result}")
show_result函数用于将数独的解答通过弹窗的方式展示给用户。- 该函数将
board(数独棋盘)中的每一行转换成字符串,并用换行符连接各行,形成最终的字符串result。 - 然后通过
messagebox.showinfo显示弹出窗口,告诉用户解答结果。
6. 处理用户点击“确定”按钮的事件
def on_submit(entries):
board = get_board_from_input(entries)
solve_sudoku(board)
show_result(board)
on_submit函数会在用户点击“确定”按钮时触发。- 首先调用
get_board_from_input从界面输入框中获取数独棋盘数据。 - 然后调用
solve_sudoku来求解数独。 - 最后,调用
show_result显示解答结果。
7. 创建 GUI 界面
def create_gui():
window = tk.Tk()
window.title("数独解答器")
create_gui函数创建了一个Tk窗口实例,作为数独游戏的主界面。- 窗口标题设置为“数独解答器”。
8. 创建输入框和“确定”按钮
entries = []
for row in range(9):
row_entries = []
for col in range(9):
entry = tk.Entry(window, width=5, font=("Arial", 14), justify='center')
entry.grid(row=row, column=col, padx=5, pady=5)
row_entries.append(entry)
entries.append(row_entries)
- 这段代码创建了一个 9x9 的输入框网格。每个输入框用于输入数独棋盘中的数字。
tk.Entry创建了一个单独的输入框,设置宽度为 5,字体为 Arial,字号为 14,并且文字居中。- 使用
grid布局方法将输入框放置在窗口中,padx和pady控制输入框之间的间距。 entries是一个二维列表,用来存储每个输入框的引用。
9. 填充默认数独棋盘
default_board = [
['8', ' ', '6', ' ', ' ', '3', ' ', '9', ' '],
[' ', '4', ' ', ' ', '1', ' ', ' ', '6', '8'],
['2', ' ', ' ', '8', '7', ' ', ' ', ' ', '5'],
['1', ' ', '8', ' ', ' ', '5', ' ', '2', ' '],
[' ', '3', ' ', '1', ' ', ' ', ' ', '5', ' '],
['7', ' ', '5', ' ', '3', ' ', '9', ' ', ' '],
[' ', '2', '1', ' ', ' ', '7', ' ', '4', ' '],
['6', ' ', ' ', ' ', '2', ' ', '8', ' ', ' '],
[' ', '8', '7', '6', ' ', '4', ' ', ' ', '3']
]
default_board是一个预设的数独棋盘,用户可以修改这些空格。
10. 确定按钮
submit_button = tk.Button(window, text="确定", font=("Arial", 14), command=lambda: on_submit(entries))
submit_button.grid(row=9, column=4, columnspan=2, pady=10)
- 创建了一个“确定”按钮,点击时调用
on_submit(entries)函数。 command参数将按钮的点击事件与on_submit函数绑定起来。
11. 启动 GUI 界面
window.mainloop()
window.mainloop()启动了tkinter的事件循环,显示窗口并等待用户与界面交互。
OK,就这,over。

Comments NOTHING