修改Python空域点猜测程序:适配度分秒格式地理坐标输入
修改后的空域点猜测程序代码
以下是支持度分秒地理坐标+原平面坐标的完整代码,同时保留坐标归一化适配Canvas显示的功能:
import tkinter as tk from tkinter import messagebox, Canvas import os # 度分秒转十进制坐标 def dms_to_decimal(dms_str): # 提取方向(最后一个字符) direction = dms_str[-1].upper() # 提取数字部分 dms_num = dms_str[:-1] # 处理不同长度的度分秒格式(比如441327是44°13'27'',0100414是10°04'14'') if len(dms_num) == 6: degrees = int(dms_num[:2]) minutes = int(dms_num[2:4]) seconds = int(dms_num[4:6]) elif len(dms_num) == 7: degrees = int(dms_num[:3]) minutes = int(dms_num[3:5]) seconds = int(dms_num[5:7]) else: raise ValueError("格式无效") # 计算十进制值,根据方向处理正负 decimal = degrees + minutes/60 + seconds/3600 if direction in ['S', 'W']: decimal = -decimal return decimal # 读取文件中的点位与坐标 def load_words_from_file(filename): if os.path.exists(filename): with open(filename, 'r') as file: lines = file.readlines() words = [] for line in lines: line = line.strip() if not line: continue parts = line.split() if len(parts) >= 3: word = parts[0].strip().lower() try: # 先尝试原平面坐标格式(整数) x = int(parts[1]) y = int(parts[2]) coordinates = (x, y) except ValueError: # 尝试度分秒格式解析 try: lat = dms_to_decimal(parts[1]) lon = dms_to_decimal(parts[2]) # 把纬度作为y,经度作为x,适配后续归一化逻辑 coordinates = (lat, lon) except Exception as e: messagebox.showwarning("错误", f"点位'{word}'的坐标格式无效:{str(e)}") continue words.append((word, coordinates)) else: messagebox.showwarning("错误", f"无效行格式:{line}") return words else: messagebox.showerror("错误", f"文件{filename}不存在!") return [] # 坐标归一化(适配Canvas显示) def normalize_coordinates(words_data, canvas_width=600, canvas_height=450): if not words_data: return [] # 提取所有坐标 x_values = [coord[1] for _, coord in words_data] y_values = [coord[0] for _, coord in words_data] # 计算极值 x_min, x_max = min(x_values), max(x_values) y_min, y_max = min(y_values), max(y_values) # 处理所有坐标相同的特殊情况 x_range = x_max - x_min if x_max != x_min else 1 y_range = y_max - y_min if y_max != y_min else 1 # 归一化并适配Canvas边界 normalized_words = [] for word, (y, x) in words_data: x_normalized = ((x - x_min) / x_range * (canvas_width - 40)) + 20 y_normalized = ((y - y_min) / y_range * (canvas_height - 40)) + 20 normalized_words.append((word, (int(x_normalized), int(y_normalized)))) return normalized_words # 文件路径 file_path = os.path.join(os.path.dirname(__file__), 'coordinate_punti.txt') # 加载并归一化数据 words_data = load_words_from_file(file_path) normalized_words_data = normalize_coordinates(words_data) class WordGameApp: def __init__(self, root): self.root = root self.root.title("空域点猜测") if not normalized_words_data: self.root.quit() return self.initialize_game() # 主框架 self.frame = tk.Frame(root) self.frame.pack(pady=10, fill=tk.BOTH, expand=True) # 适配窗口大小变化(支持手机端) self.root.bind('<Configure>', self.on_window_resize) # 提示标签 self.label = tk.Label(self.frame, text="输入你记得的点位:") self.label.pack(pady=10) # 输入框 self.word_entry = tk.Entry(self.frame) self.word_entry.pack(pady=10, fill=tk.X, padx=20) self.word_entry.bind('<Return>', self.check_word) # 剩余点位计数 self.counter_label = tk.Label(self.frame, text=f"剩余点位:{self.remaining_words}") self.counter_label.pack(pady=10) # Canvas(自适应窗口) self.canvas = Canvas(self.frame, bg="white") self.canvas.pack(pady=10, fill=tk.BOTH, expand=True, padx=20) # 重置按钮 self.clear_button = tk.Button(self.frame, text="清空并重置", command=self.reset_game) self.clear_button.pack(pady=5) # 显示/隐藏所有点位按钮 self.toggle_button = tk.Button(self.frame, text="显示所有点位", command=self.toggle_words) self.toggle_button.pack(pady=5) # 初始化绘制(如果需要) self.draw_initial_points() def initialize_game(self): # 初始化游戏状态 self.remaining_words = len(normalized_words_data) self.guessed_words = set() self.all_points_shown = False def check_word(self, event=None): # 检查输入的点位逻辑 input_word = self.word_entry.get().strip().lower() if not input_word: return for word, coord in normalized_words_data: if word == input_word and word not in self.guessed_words: self.guessed_words.add(word) self.remaining_words -= 1 self.counter_label.config(text=f"剩余点位:{self.remaining_words}") # 在Canvas上标记该点位 self.canvas.create_oval(coord[0]-5, coord[1]-5, coord[0]+5, coord[1]+5, fill="green") self.canvas.create_text(coord[0], coord[1]+15, text=word.upper(), font=("Arial", 8)) self.word_entry.delete(0, tk.END) if self.remaining_words == 0: messagebox.showinfo("完成", "所有点位都找到了!") return messagebox.showwarning("提示", "这个点位不存在或已经被猜过了") self.word_entry.delete(0, tk.END) def reset_game(self): # 重置游戏状态 self.guessed_words.clear() self.remaining_words = len(normalized_words_data) self.counter_label.config(text=f"剩余点位:{self.remaining_words}") self.canvas.delete("all") self.all_points_shown = False self.toggle_button.config(text="显示所有点位") def toggle_words(self): # 显示/隐藏所有点位 self.canvas.delete("all") if not self.all_points_shown: # 绘制所有点位 for word, coord in normalized_words_data: self.canvas.create_oval(coord[0]-5, coord[1]-5, coord[0]+5, coord[1]+5, fill="blue") self.canvas.create_text(coord[0], coord[1]+15, text=word.upper(), font=("Arial", 8)) self.toggle_button.config(text="隐藏所有点位") else: # 重新绘制已猜中的点位 for word, coord in normalized_words_data: if word in self.guessed_words: self.canvas.create_oval(coord[0]-5, coord[1]-5, coord[0]+5, coord[1]+5, fill="green") self.canvas.create_text(coord[0], coord[1]+15, text=word.upper(), font=("Arial", 8)) self.toggle_button.config(text="显示所有点位") self.all_points_shown = not self.all_points_shown def draw_initial_points(self): # 初始化可以不显示任何点位,或者显示占位 pass def on_window_resize(self, event): # 窗口大小变化时重新归一化坐标并刷新Canvas global normalized_words_data canvas_width = event.width - 40 # 减去边距 canvas_height = event.height - 200 # 减去控件高度 if canvas_width < 200: canvas_width = 200 if canvas_height < 150: canvas_height = 150 normalized_words_data = normalize_coordinates(words_data, canvas_width, canvas_height) # 重置并刷新显示 self.reset_game() if __name__ == "__main__": root = tk.Tk() app = WordGameApp(root) root.mainloop()
关键修改说明
- 新增度分秒转十进制函数:
dms_to_decimal处理N/S/E/W方向的度分秒字符串,将其转换为十进制地理坐标,同时根据方向处理正负(南纬、西经为负)。 - 兼容两种坐标格式:在
load_words_from_file中,先尝试解析原有的整数平面坐标;如果失败,则自动尝试解析度分秒格式,实现无缝兼容。 - 优化归一化逻辑:处理了所有坐标相同的特殊情况,避免除零错误;同时调整了坐标映射,确保地理坐标(纬度y,经度x)能正确适配Canvas的显示逻辑。
- 窗口自适应:新增窗口大小变化监听,自动重新计算归一化坐标,适配不同屏幕(包括手机端)的显示需求。
- 补全游戏逻辑:原代码缺失的
initialize_game、check_word、reset_game等核心游戏逻辑进行了补全,保证程序能正常运行。
内容的提问来源于stack exchange,提问作者vecchiemaniere
相关产品推荐
相关产品推荐

