3_pics.h

  name="google_ads_frame" marginwidth="0" marginheight="0" src="http://pagead2.googlesyndication.com/pagead/ads?client=ca-pub-5572165936844014&dt=1194442938015&lmt=1194190197&format=336x280_as&output=html&correlator=1194442937843&url=file%3A%2F%2F%2FC%3A%2FDocuments%2520and%2520Settings%2Flhh1%2F%E6%A1%8C%E9%9D%A2%2FCLanguage.htm&color_bg=FFFFFF&color_text=000000&color_link=000000&color_url=FFFFFF&color_border=FFFFFF&ad_type=text&ga_vid=583001034.1194442938&ga_sid=1194442938&ga_hid=1942779085&flash=9&u_h=768&u_w=1024&u_ah=740&u_aw=1024&u_cd=32&u_tz=480&u_java=true" frameborder="0" width="336" scrolling="no" height="280" allowtransparency="allowtransparency"> #define IDM_EXIT           100
#define IDM_TEST           200
#define IDM_ABOUT          301

LRESULT CALLBACK WndProc  (HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK About    (HWND, UINT, WPARAM, LPARAM);

from tkinter import * from tkinter.messagebox import * import random from collections import deque import heapq import time class PuzzleSolver: def __init__(self, root, title, x_pos, y_pos, initial_state=None): # 创建独立窗口 self.window = Toplevel(root) self.window.title(title) self.window.geometry(f"350x500+{x_pos}+{y_pos}") # 常量定义 self.WIDTH, self.HEIGHT = 312, 450 self.IMAGE_WIDTH, self.IMAGE_HEIGHT = self.WIDTH // 3, self.HEIGHT // 3 self.ROWS, self.COLS = 3, 3 self.GOAL_STATE = ((0, 1, 2), (3, 4, 5), (6, 7, None)) # 加载图片 self.Pics = [] for i in range(9): filename = f"cx_{i}.png" try: self.Pics.append(PhotoImage(file=filename)) except: # 创建空白图像作为替代 self.Pics.append(PhotoImage(width=100, height=100)) print(f"警告:图片 {filename} 不存在,使用空图像替代") # 拼图状态 self.board = [[None for _ in range(self.COLS)] for _ in range(self.ROWS)] self.results = {"steps": 0, "search_space": 0, "time": 0} self.initial_state = initial_state # 用于同步初始状态 # 创建界面 self.create_ui() # 初始化拼图 self.init_board() # 图像块类 class Square: def __init__(self, orderID): # 严格验证ID有效性 if not (isinstance(orderID, int) and 0 <= orderID <= 7): raise ValueError(f"无效拼图ID: {orderID},必须是0-7的整数") self.orderID = orderID # 获取当前状态(确保类型安全) def get_current_state(self): state = [] for i in range(self.ROWS): row = [] for j in range(self.COLS): val = self.board[i][j].orderID if self.board[i][j] is not None else None row.append(val) state.append(tuple(row)) return tuple(state) # 设置拼图状态 def set_board_state(self, state): # 验证状态合法性 for i in range(self.ROWS): for j in range(self.COLS): val = state[i][j] if val is not None and not (isinstance(val, int) and 0 <= val <= 7): raise ValueError(f"无效状态值: {val},必须是0-7的整数或None") self.board = [[None for _ in range(self.COLS)] for _ in range(self.ROWS)] for i in range(self.ROWS): for j in range(self.COLS): val = state[i][j] if val is not None: self.board[i][j] = self.Square(val) self.update_display() # 找到空白块位置 def find_empty(self, state): for i in range(self.ROWS): for j in range(self.COLS): if state[i][j] is None: return i, j return -1, -1 # 理论上不会触发 # 生成新状态 def generate_new_state(self, state, i1, j1, i2, j2): if not (0 <= i1 < self.ROWS and 0 <= j1 < self.COLS and 0 <= i2 < self.ROWS and 0 <= j2 < self.COLS): return state # 转换为列表进行修改 state_list = [list(row) for row in state] # 交换两个位置 state_list[i1][j1], state_list[i2][j2] = state_list[i2][j2], state_list[i1][j1] return tuple(tuple(row) for row in state_list) # 初始化拼图(使用相同的初始状态) def init_board(self): if self.initial_state is not None: # 使用提供的初始状态 self.set_board_state(self.initial_state) return # 生成新的可解状态 while True: # 生成0-7和None的随机序列 nums = list(range(8)) + [None] random.shuffle(nums) state = (tuple(nums[:3]), tuple(nums[3:6]), tuple(nums[6:9])) # 可解性检查 flat = [x for row in state for x in row if x is not None] inversions = 0 for i in range(len(flat)): for j in range(i + 1, len(flat)): if flat[i] > flat[j]: inversions += 1 blank_row = self.find_empty(state)[0] # 可解条件:逆序数 + 空白块行号为偶数 if (inversions + blank_row) % 2 == 0: self.initial_state = state # 保存初始状态供另一个拼图使用 self.set_board_state(state) break # 绘制拼图 def draw_board(self): self.canvas.delete(&#39;all&#39;) # 画外框 self.canvas.create_polygon((0, 0, self.WIDTH, 0, self.WIDTH, self.HEIGHT, 0, self.HEIGHT), width=1, outline=&#39;Black&#39;) # 画拼图块 for i in range(self.ROWS): for j in range(self.COLS): if self.board[i][j] is not None: self.canvas.create_image( self.IMAGE_WIDTH * (j + 0.5), self.IMAGE_HEIGHT * (i + 0.5), image=self.Pics[self.board[i][j].orderID] ) # 更新显示 def update_display(self): self.draw_board() self.window.update() # 创建界面元素 def create_ui(self): self.canvas = Canvas(self.window, bg=&#39;green&#39;, width=self.WIDTH, height=self.HEIGHT) self.status_label = Label(self.window, text="等待求解...", fg="blue") self.result_label = Label(self.window, text="结果将显示在这里", justify=LEFT, wraplength=300) self.canvas.pack() self.status_label.pack(pady=5) self.result_label.pack(pady=5) # BFS求解 def bfs_solve(self): start_state = self.get_current_state() if start_state == self.GOAL_STATE: showinfo("提示", "已是完成状态!") return self.status_label.config(text="BFS求解中...") start_time = time.time() queue = deque([(start_state, [])]) visited = set([start_state]) found = False try: while queue: current_state, path = queue.popleft() if current_state == self.GOAL_STATE: self.results["steps"] = len(path) self.results["search_space"] = len(visited) self.results["time"] = time.time() - start_time # 展示求解过程 self.set_board_state(start_state) self.window.update() time.sleep(1) for move in path: self.set_board_state(move) time.sleep(0.5) self.status_label.config(text="BFS求解完成") self.result_label.config( text=f"BFS结果:\n步数: {self.results[&#39;steps&#39;]}\n搜索空间: {self.results[&#39;search_space&#39;]}\n耗时: {self.results[&#39;time&#39;]:.4f}秒") found = True break i, j = self.find_empty(current_state) # 尝试四个方向移动 for di, dj in [(-1, 0), (1, 0), (0, -1), (0, 1)]: ni, nj = i + di, j + dj if 0 <= ni < self.ROWS and 0 <= nj < self.COLS: new_state = self.generate_new_state(current_state, i, j, ni, nj) if new_state not in visited: visited.add(new_state) queue.append((new_state, path + [new_state])) if not found: self.status_label.config(text="BFS未找到解") except Exception as e: self.status_label.config(text=f"BFS出错") showinfo("错误", f"BFS算法出错: {str(e)}") # A*求解 - 修复后的版本 def astar_solve(self): start_state = self.get_current_state() if start_state == self.GOAL_STATE: showinfo("提示", "已是完成状态!") return self.status_label.config(text="A*求解中...") start_time = time.time() # 曼哈顿距离启发函数(确保始终返回整数) def manhattan_distance(state): distance = 0 for i in range(self.ROWS): for j in range(self.COLS): val = state[i][j] # 只处理整数拼图块(空白块None跳过) if isinstance(val, int): target_i = val // 3 target_j = val % 3 distance += abs(i - target_i) + abs(j - target_j) return distance # 确保返回整数 # 优先队列初始化 initial_g = 0 initial_h = manhattan_distance(start_state) initial_f = initial_g + initial_h # 添加节点ID防止比较冲突 next_node_id = 0 priority_queue = [] heapq.heappush(priority_queue, (initial_f, next_node_id, initial_g, start_state, [])) next_node_id += 1 visited = {start_state: initial_g} found = False try: while priority_queue: # 弹出f值最小的状态 current_f, _, current_g, current_state, path = heapq.heappop(priority_queue) # 检查是否达到目标状态 if current_state == self.GOAL_STATE: self.results["steps"] = len(path) self.results["search_space"] = len(visited) self.results["time"] = time.time() - start_time # 展示求解过程 self.set_board_state(start_state) self.window.update() time.sleep(1) for move in path: self.set_board_state(move) time.sleep(0.5) self.status_label.config(text="A*求解完成") self.result_label.config( text=f"A*结果:\n步数: {self.results[&#39;steps&#39;]}\n搜索空间: {self.results[&#39;search_space&#39;]}\n耗时: {self.results[&#39;time&#39;]:.4f}秒") found = True break # 找到空白块位置 empty_i, empty_j = self.find_empty(current_state) # 尝试四个方向移动 for di, dj in [(-1, 0), (1, 0), (0, -1), (0, 1)]: ni, nj = empty_i + di, empty_j + dj if 0 <= ni < self.ROWS and 0 <= nj < self.COLS: new_state = self.generate_new_state(current_state, empty_i, empty_j, ni, nj) new_g = current_g + 1 # 步数+1 # 验证启发值计算正确 try: new_h = manhattan_distance(new_state) new_f = new_g + new_h except Exception as e: print(f"启发式计算错误: {e}") continue # 检查是否发现更优路径 if new_state not in visited or new_g < visited[new_state]: visited[new_state] = new_g # 添加唯一节点ID防止比较冲突 heapq.heappush(priority_queue, (new_f, next_node_id, new_g, new_state, path + [new_state])) next_node_id += 1 if not found: self.status_label.config(text="A*未找到解") except Exception as e: self.status_label.config(text=f"A*出错") showinfo("错误", f"A*算法出错: {str(e)}") # 主程序 if __name__ == "__main__": root = Tk() root.title("拼图算法比较") root.geometry("400x150") # 存储两个拼图实例和共享的初始状态 puzzle_bfs = None puzzle_astar = None shared_initial_state = None # 创建两个相同初始状态的拼图 def create_identical_puzzles(): global puzzle_bfs, puzzle_astar, shared_initial_state # 先创建BFS拼图并获取其初始状态 puzzle_bfs = PuzzleSolver(root, "BFS算法求解", 100, 100) shared_initial_state = puzzle_bfs.initial_state # 使用相同的初始状态创建A*拼图 puzzle_astar = PuzzleSolver(root, "A*算法求解", 500, 100, shared_initial_state) # 启用求解按钮 btn_solve_bfs.config(state=NORMAL) btn_solve_astar.config(state=NORMAL) # 显示对比结果 def show_comparison(): if not puzzle_bfs or not puzzle_astar: showinfo("提示", "请先创建拼图") return bfs = puzzle_bfs.results astar = puzzle_astar.results if bfs["steps"] == 0 or astar["steps"] == 0: showinfo("提示", "请先完成两种算法的求解") return result = "算法效率对比(相同初始状态):\n\n" result += f"BFS:\n 步数: {bfs[&#39;steps&#39;]}\n 搜索空间: {bfs[&#39;search_space&#39;]}\n 耗时: {bfs[&#39;time&#39;]:.4f}秒\n\n" result += f"A*:\n 步数: {astar[&#39;steps&#39;]}\n 搜索空间: {astar[&#39;search_space&#39;]}\n 耗时: {astar[&#39;time&#39;]:.4f}秒\n\n" # 计算效率提升 space_ratio = bfs["search_space"] / astar["search_space"] time_ratio = bfs["time"] / astar["time"] if astar["time"] > 0 else 0 result += f"A*搜索空间约为BFS的{1 / space_ratio:.2%}\n" result += f"A*速度约为BFS的{time_ratio:.2f}倍" showinfo("算法对比结果", result) # 主界面按钮 Label(root, text="拼图搜索算法比较", font=("Arial", 16)).pack(pady=10) frame = Frame(root) frame.pack(pady=10) btn_create = Button(frame, text="创建相同初始状态拼图", command=create_identical_puzzles, width=20) btn_solve_bfs = Button(frame, text="BFS求解", command=lambda: puzzle_bfs.bfs_solve() if puzzle_bfs else None, width=10, state=DISABLED) btn_solve_astar = Button(frame, text="A*求解", command=lambda: puzzle_astar.astar_solve() if puzzle_astar else None, width=10, state=DISABLED) btn_compare = Button(root, text="显示算法对比", command=show_comparison, width=20) btn_create.grid(row=0, column=0, padx=5) btn_solve_bfs.grid(row=0, column=1, padx=5) btn_solve_astar.grid(row=0, column=2, padx=5) btn_compare.pack(pady=10) root.mainloop() 对这个代码进行模块划分
最新发布
09-21
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值