Python Tkinter战舰游戏完成玩家2回合后无法切回玩家1求助
战舰游戏界面切换问题解决方案
问题根源
- 界面组件未隐藏:切换玩家界面时,未将当前显示的棋盘按钮隐藏,导致新界面按钮被旧按钮覆盖,视觉上无法完成切换。
- 按钮列表创建冗余:
buttons1和buttons2的创建多了一层for i in range(2)循环,生成了20行按钮(远超棋盘需要的10行),属于无效代码且易引发逻辑混乱。 - 重复创建next按钮:每次切换界面都会新建一个next按钮,旧按钮仍存在于界面中,可能导致事件冲突或视觉遮挡。
修复后的代码
import tkinter as tk import random window = tk.Tk() ship_sizes = [5,4,3,2,2] board_size = 10 # 初始化玩家棋盘 board1 = [[0 for _ in range(board_size)] for _ in range(board_size)] board2 = [[0 for _ in range(board_size)] for _ in range(board_size)] # 为玩家1随机放置战舰 for ship in ship_sizes: while True: x = random.randint(0, board_size-1) y = random.randint(0, board_size-1) orien = random.choice(['hor','vert']) if orien == 'hor' and x + ship <= board_size: valid = all(board1[x+i][y] == 0 for i in range(ship)) if valid: for i in range(ship): board1[x+i][y] = ship break elif orien == 'vert' and y + ship <= board_size: valid = all(board1[x][y+i] == 0 for i in range(ship)) if valid: for i in range(ship): board1[x][y+i] = ship break # 为玩家2随机放置战舰 for ship in ship_sizes: while True: x = random.randint(0, board_size-1) y = random.randint(0, board_size-1) orien = random.choice(['hor','vert']) if orien == 'hor' and x + ship <= board_size: valid = all(board2[x+i][y] == 0 for i in range(ship)) if valid: for i in range(ship): board2[x+i][y] = ship break elif orien == 'vert' and y + ship <= board_size: valid = all(board2[x][y+i] == 0 for i in range(ship)) if valid: for i in range(ship): board2[x][y+i] = ship break def button_click1(x,y): if board1[x][y] == 0: buttons1[x][y].config(text="Miss", bg="white") else: buttons1[x][y].config(text="Hit", bg="darkkhaki") # 标记已击中,防止重复点击 board1[x][y] = 1 def button_click2(x,y): if board2[x][y] == 0: buttons2[x][y].config(text="Miss", bg="white") else: buttons2[x][y].config(text="Hit", bg="darkkhaki") # 标记已击中,防止重复点击 board2[x][y] = 1 # 创建玩家1的棋盘按钮(修复循环冗余) buttons1 = [] for j in range(board_size): row = [] for k in range(board_size): button = tk.Button(master=window, text="", bg="deepskyblue", width=2, height=1, command=lambda x=j, y=k: button_click1(x, y)) row.append(button) buttons1.append(row) # 创建玩家2的棋盘按钮(修复循环冗余) buttons2 = [] for j in range(board_size): row = [] for k in range(board_size): button = tk.Button(master=window, text="", bg="deepskyblue", width=2, height=1, command=lambda x=j, y=k: button_click2(x, y)) row.append(button) buttons2.append(row) # 全局next按钮,避免重复创建 next_btn = None def hide_all_boards(): # 隐藏玩家1和玩家2的所有按钮 for i in range(board_size): for j in range(board_size): buttons1[i][j].grid_forget() buttons2[i][j].grid_forget() # 隐藏之前的next按钮 global next_btn if next_btn: next_btn.grid_forget() def frame1(): hide_all_boards() # 显示玩家1的棋盘 for i in range(board_size): for j in range(board_size): buttons1[i][j].grid(row=i, column=j) # 创建/显示next按钮 global next_btn next_btn = tk.Button(master=window, text="next", bg="green", width=5, height=2, command=frame2) next_btn.grid(row=11, column=11) def frame2(): hide_all_boards() # 显示玩家2的棋盘 for i in range(board_size): for j in range(board_size): buttons2[i][j].grid(row=i, column=j) # 创建/显示next按钮 global next_btn next_btn = tk.Button(master=window, text="next", bg="green", width=5, height=2, command=frame1) next_btn.grid(row=11, column=11) frame1() window.mainloop()
关键修改点
- 新增
hide_all_boards函数:切换界面时先隐藏所有棋盘按钮和旧的next按钮,彻底避免组件重叠问题。 - 修复按钮列表创建循环:移除多余的
for i in range(2)循环,确保buttons1和buttons2仅生成10行(匹配棋盘尺寸)。 - 全局next按钮管理:将next按钮设为全局变量,每次切换时先隐藏旧按钮再创建新的,避免重复创建引发的冲突。
- 优化点击逻辑:击中后将棋盘对应位置设为1,防止重复点击同一位置时重复触发状态变化,同时简化了原代码中冗余的按钮属性设置操作。
内容的提问来源于stack exchange,提问作者H0tp0tat0
相关产品推荐
相关产品推荐

