当前位置: 首页 > article >正文

python八皇后游戏

程序功能:

  • 用户通过点击棋盘格子放置/移除皇后
  • 实时检测皇后冲突(同列/对角线)
  • 提供自动求解功能(显示一个随机解)
  • 支持新游戏开始
  • 国际象棋棋盘配色(浅棕/深棕交替)
  • 红色边框高亮冲突皇后
  • 使用 Unicode 皇后符号 ♛ 表示棋子
  • 实时显示已放置皇后数量
  • 基于回溯算法的自动求解器
  • 冲突检测算法(O(n²) 复杂度)
  • 解决方案缓存机制

代码结构:

class EightQueensGame:
    def __init__(self, master):  # 初始化游戏界面和变量
    def draw_board(self):         # 绘制棋盘和棋子
    def draw_queen(self):         # 绘制皇后图标
    def on_click(self):           # 处理鼠标点击事件
    def has_conflicts(self):      # 冲突检测逻辑
    def highlight_conflicts(self):# 高亮冲突棋子
    def update_status(self):      # 更新状态栏信息
    def new_game(self):           # 重置游戏状态
    def show_solution(self):      # 显示解决方案
    def find_solutions(self):     # 回溯算法求解所有解

代码分析:

棋盘绘制

   # 交替颜色绘制棋盘
   color = "#DDB88C" if (row + col) % 2 == 0 else "#A0522D"
   self.canvas.create_rectangle(x1, y1, x2, y2, fill=color)

冲突检测算法

   # 检查两个皇后是否在同一列或对角线上
   if c1 == c2 or abs(r1 - r2) == abs(c1 - c2):
       return True

回溯求解算法

   def backtrack(row, cols, diag1, diag2):
       if row == self.board_size:
           self.solutions.append(cols[:])
           return
       for col in range(self.board_size):
           d1 = row - col  # 主对角线标识
           d2 = row + col  # 副对角线标识
           if col not in cols and d1 not in diag1 and d2 not in diag2:
               backtrack(row+1, cols+[col], diag1+[d1], diag2+[d2])

具体代码

import tkinter as tk
from tkinter import messagebox
import random

class EightQueensGame:
    def __init__(self, master):
        # 初始化主窗口
        self.master = master
        master.title("八皇后游戏")
        master.geometry("520x600")  # 设置窗口尺寸
        
        # 游戏参数初始化
        self.board_size = 8          # 棋盘尺寸8x8
        self.cell_size = 60         # 每个格子像素大小
        self.queens = []            # 存储已放置皇后坐标的列表
        self.solutions = []         # 存储所有解决方案的列表
        
        # 创建棋盘画布
        self.canvas = tk.Canvas(master, 
                               width=self.cell_size*self.board_size,
                               height=self.cell_size*self.board_size)
        self.canvas.pack(pady=10)  # 添加垂直间距
        
        # 创建控制面板
        control_frame = tk.Frame(master)
        # 状态显示标签
        self.status_label = tk.Label(control_frame, 
                                    text="已放置 0/8 个皇后", 
                                    font=('微软雅黑', 12))
        # 新游戏按钮
        self.new_game_btn = tk.Button(control_frame, 
                                     text="新游戏", 
                                     command=self.new_game)
        # 显示答案按钮
        self.solve_btn = tk.Button(control_frame,
                                  text="显示答案",
                                  command=self.show_solution)
        
        # 布局控制面板组件
        self.status_label.pack(side=tk.LEFT, padx=10)
        self.new_game_btn.pack(side=tk.LEFT, padx=5)
        self.solve_btn.pack(side=tk.LEFT, padx=5)
        control_frame.pack(pady=10)
        
        # 初始化棋盘绘制并绑定点击事件
        self.draw_board()
        self.canvas.bind("<Button-1>", self.on_click)

    def draw_board(self):
        """绘制棋盘及棋子"""
        self.canvas.delete("all")  # 清空画布
        for row in range(self.board_size):
            for col in range(self.board_size):
                # 计算格子坐标
                x1 = col * self.cell_size
                y1 = row * self.cell_size
                x2 = x1 + self.cell_size
                y2 = y1 + self.cell_size
                
                # 交替格子颜色(国际象棋棋盘样式)
                color = "#DDB88C" if (row + col) % 2 == 0 else "#A0522D"
                self.canvas.create_rectangle(x1, y1, x2, y2, 
                                            fill=color, 
                                            tags=f"cell_{row}_{col}")
                
                # 如果该位置有皇后则绘制
                if (row, col) in self.queens:
                    self.draw_queen(row, col)
        
        # 高亮显示冲突的皇后
        self.highlight_conflicts()

    def draw_queen(self, row, col):
        """在指定位置绘制皇后符号"""
        x = col * self.cell_size + self.cell_size//2  # 计算中心坐标
        y = row * self.cell_size + self.cell_size//2
        self.canvas.create_text(x, y, 
                                text="♛",            # Unicode皇后符号
                                font=('Arial', 24),  # 字体设置
                                fill='black')        # 黑色填充

    def on_click(self, event):
        """处理棋盘点击事件"""
        # 计算点击的格子坐标
        col = event.x // self.cell_size
        row = event.y // self.cell_size
        
        # 切换皇后状态(添加/移除)
        if (row, col) in self.queens:
            self.queens.remove((row, col))
        else:
            if len(self.queens) >= 8:
                messagebox.showwarning("提示", "已经放置8个皇后了!")
                return
            self.queens.append((row, col))
        
        # 更新界面和状态
        self.update_status()
        self.draw_board()
        
        # 胜利条件检查
        if len(self.queens) == 8 and not self.has_conflicts():
            messagebox.showinfo("恭喜", "你成功解决了八皇后问题!🎉")

    def has_conflicts(self):
        """检查当前皇后布局是否存在冲突"""
        for i in range(len(self.queens)):
            for j in range(i+1, len(self.queens)):
                r1, c1 = self.queens[i]
                r2, c2 = self.queens[j]
                
                # 冲突条件:同一列 或 同一对角线(行差绝对值等于列差绝对值)
                if c1 == c2 or abs(r1 - r2) == abs(c1 - c2):
                    return True
        return False

    def highlight_conflicts(self):
        """用红色边框标记冲突的皇后"""
        conflict_pairs = []
        # 找出所有冲突的皇后对
        for i in range(len(self.queens)):
            for j in range(i+1, len(self.queens)):
                r1, c1 = self.queens[i]
                r2, c2 = self.queens[j]
                
                if c1 == c2 or abs(r1 - r2) == abs(c1 - c2):
                    conflict_pairs.extend([(r1,c1), (r2,c2)])
        
        # 为每个冲突的皇后添加红色边框
        for row, col in set(conflict_pairs):
            x1 = col * self.cell_size
            y1 = row * self.cell_size
            x2 = x1 + self.cell_size
            y2 = y1 + self.cell_size
            self.canvas.create_rectangle(x1, y1, x2, y2, 
                                         outline="red", 
                                         width=3)

    def update_status(self):
        """更新状态栏显示"""
        self.status_label.config(text=f"已放置 {len(self.queens)}/8 个皇后")
        # 根据冲突状态改变文字颜色
        self.status_label.config(fg="red" if self.has_conflicts() else "black")

    def new_game(self):
        """重置游戏状态"""
        self.queens = []
        self.solutions = []
        self.draw_board()
        self.update_status()

    def show_solution(self):
        """显示一个随机解决方案"""
        if not self.solutions:
            self.find_solutions()  # 如果还没有解,先计算
        
        if self.solutions:
            # 随机选择一个解并显示
            solution = random.choice(self.solutions)
            self.queens = [(i, col) for i, col in enumerate(solution)]
            self.draw_board()
            self.update_status()
        else:
            messagebox.showinfo("提示", "没有找到解法!")

    def find_solutions(self):
        """使用回溯算法查找所有合法解"""
        def backtrack(row, cols, diag1, diag2):
            """递归回溯函数
            Args:
                row: 当前处理的行
                cols: 已占用的列
                diag1: 主对角线特征值(row - col)
                diag2: 副对角线特征值(row + col)
            """
            if row == self.board_size:
                self.solutions.append(cols[:])  # 找到合法解
                return
            for col in range(self.board_size):
                d1 = row - col  # 主对角线标识
                d2 = row + col  # 副对角线标识
                # 检查列冲突和对角线冲突
                if col not in cols and d1 not in diag1 and d2 not in diag2:
                    backtrack(row+1, cols+[col], diag1+[d1], diag2+[d2])
        
        self.solutions = []
        backtrack(0, [], [], [])  # 从第0行开始搜索
        return self.solutions

if __name__ == "__main__":
    root = tk.Tk()          # 创建主窗口
    game = EightQueensGame(root)  # 初始化游戏实例
    root.mainloop()         # 启动GUI事件循环 


http://www.kler.cn/a/572477.html

相关文章:

  • Java 第十一章 GUI编程(2)
  • 游戏引擎学习第135天
  • AI×电商数据API接口:深度融合,引领未来电商行业浪潮
  • docker默认网段和宿主机环境冲突时的处理
  • pytorch获取模型性能
  • 【GPU使用】如何在物理机和Docker中指定GPU进行推理和训练
  • 一、docker初识
  • 【在线用户监控】在线用户查询、强退用户
  • Java利用JSch进行SFTP进行SSH连接远程服务器进行目录创建与上传文件,ChannelSftp
  • 学单片机能从事什么工作?
  • 【华为OD机考】华为OD笔试真题解析(20)--投篮大赛
  • 安卓广播的使用
  • Elasticsearch:简化大数据分析,使用Elasticsearch进行高效数据聚合
  • LeetCode hot 100—轮转数组
  • visual studio 2022 手工写一个简单的MFC程序
  • [原创](Modern C++)现代C++的关键性概念: 什么是友元函数, 什么是友元类?
  • css不出现滚动条
  • T-SQL 语言基础: SQL 数据库对象元数据及配置信息获取
  • 计算机网络——子网掩码
  • 网络安全中keli是什么