问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

数独游戏开发与优化:使用 Tkinter 实现数独界面和智能生成算法

创作时间:
作者:
@小白创作中心

数独游戏开发与优化:使用 Tkinter 实现数独界面和智能生成算法

引用
CSDN
1.
https://blog.csdn.net/qq_44793283/article/details/146058499

在本篇博文中,我们将带您逐步实现一个数独游戏,使用 Python 的 Tkinter 库进行图形界面设计,并结合先进的数独生成和验证算法,确保每局游戏都能提供一个有挑战性的体验。我们不仅优化了数独题目生成的逻辑,还在界面设计上做了美化,使用户的游戏体验更加友好和流畅。

代码解读

首先,我们从数独生成和验证算法开始。这部分负责生成具有唯一解的数独棋盘,并在每次启动新游戏时随机移除数字,生成新的数独题目。

1. 数独生成器 (SudokuGenerator)

class SudokuGenerator:
    def __init__(self):
        self.board = [[0] * 9 for _ in range(9)]
        self.solution = None

数独生成器的核心是 board,它存储了 9x9 的数独棋盘。我们还保持了一个 solution 属性,用来存储已生成的解。

def generate(self, difficulty):
    self.board = [[0] * 9 for _ in range(9)]  # 重置棋盘
    self._fill_diagonal()
    self._solve()  # 使用更可靠的解法
    self.solution = [row[:] for row in self.board]
    self._remove_numbers_safely(difficulty)  # 改进的挖洞算法
    return self.board

generate() 方法负责生成数独题目。它通过填充对角线和使用回溯算法填充空白位置,确保棋盘有一个解。然后根据选择的难度移除适当数量的数字,保持题目有唯一解。

2. 数独验证与优化

def _has_unique_solution(self):
    temp = [row[:] for row in self.board]
    solutions = 0
    def count_solutions(row, col):
        nonlocal solutions
        if row == 9:
            solutions += 1
            return
        next_row = row + 1 if col == 8 else row
        next_col = (col + 1) % 9
        if temp[row][col] != 0:
            count_solutions(next_row, next_col)
            return
        for num in range(1, 10):
            if solutions > 1:
                return
            if self._is_valid_temp(temp, row, col, num):
                temp[row][col] = num
                count_solutions(next_row, next_col)
                temp[row][col] = 0
    count_solutions(0, 0)
    return solutions == 1

为了确保题目有唯一解,我们在每次删除数字后,会检查当前数独是否依然有唯一解。如果删除某个数字后解不唯一,就恢复该数字。

3. 数独界面 (SudokuGame)

接下来,我们构建了数独的图形界面。我们使用 Tkinter 库来实现数独的交互界面,并通过 Entry 小部件创建了 9x9 的数独网格。

class SudokuGame(tk.Tk):
    def __init__(self):
        super().__init__()
        self.title("数独游戏")
        self.geometry("500x600")
        self.resizable(False, False)
        self.history_file = "sudoku_history.json"
        self.history = self._load_history()
        self.generator = SudokuGenerator()
        self.solution = None
        self.start_time = None
        self.timer_id = None
        self.username = None
        self._create_widgets()
        self._setup_grid()
        self.update_history_display()

4. 创建数独网格

SudokuGame 类中, _setup_grid 方法会创建数独的 9x9 网格。每个单元格是一个 Entry 小部件,可以接受用户输入。

def _setup_grid(self):
    """创建数独网格(用Frame包裹每个3x3宫格)"""
    self.cells = []
    # 先创建9个3x3宫格的Frame容器
    for block_row in range(3):
        for block_col in range(3):
            # 每个宫格用一个Frame包裹,并设置边框
            block_frame = tk.Frame(
                self.grid_frame,
                relief="groove",  # 边框样式(可选:solid, groove, raised等)
                borderwidth=2,  # 边框粗细
                bg="black"  # 边框颜色(需通过背景色模拟)
            )
            block_frame.grid(
                row=block_row,
                column=block_col,
                padx=(1 if block_col != 0 else 0, 1),  # 宫格之间的间距
                pady=(1 if block_row != 0 else 0, 1)
            )
            # 在宫格Frame内创建3x3单元格
            for i_in_block in range(3):
                for j_in_block in range(3):
                    # 计算全局行列号
                    global_row = block_row * 3 + i_in_block
                    global_col = block_col * 3 + j_in_block
                    cell = tk.Entry(
                        block_frame,
                        width=2,
                        font=("微软雅黑", 18),
                        justify="center",
                        relief="solid",
                        bg="white",
                        borderwidth=1,
                    )
                    cell.grid(row=i_in_block, column=j_in_block)
                    cell.bind("<KeyRelease>", self._check_input)
                    # 将单元格保存到全局网格中
                    if len(self.cells) <= global_row:
                        self.cells.append([])
                    self.cells[global_row].append(cell)

5. 计时器与历史记录

游戏中加入了计时器功能,可以实时显示玩家用时。当玩家完成数独时,会显示时间,并更新历史记录,保存每个难度的最佳时间。

def _update_timer(self):
    if self.start_time:
        elapsed = int(time.time() - self.start_time)
        self.timer_label.config(text=f"时间: {elapsed}秒")
        self.timer_id = self.after(1000, self._update_timer)

每一局的时间会实时更新,用户完成数独时系统会检查是否创造了新的纪录。

优化与体验

为了提升用户体验,我们在界面上做了一些细节优化:

  1. 背景色和样式:输入框的背景色会根据正确与否实时变化,帮助玩家确认输入是否有效。
  2. 用户自定义用户名:玩家可以在游戏中设置用户名,个性化体验。
  3. 动态更新历史记录:每个难度的最佳时间会显示在界面上,激励玩家挑战更高的记录。

总结

通过这篇博文,我们展示了如何使用 Tkinter 创建一个互动式数独游戏,并结合优化的数独生成与验证算法,确保每次游戏都能提供一个具有挑战性的解答。你可以在此基础上进一步优化游戏的玩法和界面,加入更多功能,如音效、提示等,提升玩家的沉浸感。

示例

if __name__ == "__main__":
    app = SudokuGame()
    app.mainloop()

通过运行上述代码,您将看到一个完整的数独游戏界面,玩家可以根据不同难度开始新游戏,实时挑战自己的数独解题能力。

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号