import tkinter as tk from tkinter import messagebox class NumberChess: def __init__(self, root): self.root = root self.root.title("数字棋") self.board = [[None for _ in range(3)] for _ in range(3)] self.current_player = "红" self.buttons = [[None for _ in range(3)] for _ in range(3)] self.selected_cell = None self.penalty_highlight = None self.is_penalty_window_open = False self.create_board() def create_board(self): for i in range(3): for j in range(3): button = tk.Button(self.root, text="", width=10, height=3, bg="white", command=lambda i=i, j=j: self.on_click(i, j)) button.grid(row=i, column=j) self.buttons[i][j] = button def on_click(self, i, j): cell = self.board[i][j] if self.selected_cell is None: if cell is None: self.board[i][j] = (1, self.current_player) self.update_button(i, j) if self.check_win(): messagebox.showinfo("游戏结束", f"{self.current_player} 方获胜!") self.reset_game() else: punishment_triggered = self.check_special_rule() if not punishment_triggered: self.switch_player() else: number, player = cell if player == self.current_player: self.selected_cell = (i, j) self.highlight_selected(i, j) else: if self.move_selected_to(i, j): if self.check_win(): messagebox.showinfo("游戏结束", f"{self.current_player} 方获胜!") self.reset_game() else: punishment_triggered = self.check_special_rule() if not punishment_triggered: self.switch_player() self.clear_selection() def move_selected_to(self, i, j): si, sj = self.selected_cell if abs(si - i) + abs(sj - j) != 1: return False selected_number, selected_player = self.board[si][sj] target_cell = self.board[i][j] if (target_cell is None or target_cell[1] != selected_player) and (abs(i - si) + abs(j - sj) == 1): new_number = selected_number if target_cell is not None: new_number += target_cell[0] self.board[i][j] = (new_number, selected_player) self.board[si][sj] = None self.update_button(si, sj) self.update_button(i, j) return True return False def highlight_selected(self, i, j): for x in range(3): for y in range(3): if (x, y) == (i, j): self.buttons[x][y].config(bg="yellow") else: self.update_button(x, y) def clear_selection(self): self.selected_cell = None for i in range(3): for j in range(3): self.update_button(i, j) def update_button(self, i, j): cell = self.board[i][j] if cell is None: self.buttons[i][j].config(text="", bg="white") else: number, player = cell bg_color = "red" if player == "红" else "blue" fg_color = "black" cell_text = str(number) if self.penalty_highlight and (i, j) in self.penalty_highlight: index = self.penalty_highlight.index((i, j)) + 1 cell_text += f"_{index}" bg_color = "lightgreen" # 使用绿色背景突出显示 self.buttons[i][j].config(text=cell_text, bg=bg_color, fg=fg_color) def switch_player(self): self.current_player = "蓝" if self.current_player == "红" else "红" def check_win(self): for row in self.board: for cell in row: if cell and cell[0] >= 10: return True return False def check_special_rule(self): if not self.has_empty_cell(): self.apply_special_rule() return True return False def has_empty_cell(self): for row in self.board: if None in row: return True return False def apply_special_rule(self): current_player_cells = [] for i in range(3): for j in range(3): cell = self.board[i][j] if cell and cell[1] == self.current_player: current_player_cells.append(cell) if not current_player_cells: return max_number = max(cell[0] for cell in current_player_cells) max_cells = [(i,j) for i in range(3) for j in range(3) if self.board[i][j] and self.board[i][j][1] == self.current_player and self.board[i][j][0] == max_number] if len(max_cells) == 1: i, j = max_cells[0] self.apply_number_reduction(i, j, None) # 传入 None 表示无窗口 else: self._max_cells = max_cells.copy() self.penalty_highlight = self._max_cells.copy() self.ask_player_to_choose(max_cells) def ask_player_to_choose(self, max_cells): if self.is_penalty_window_open: return self.is_penalty_window_open = True self._max_cells = max_cells self.ask_window = tk.Toplevel(self.root) self.ask_window.title("选择一个数字减1") self.ask_window.grab_set() self.ask_window.protocol("WM_DELETE_WINDOW", self.on_window_close) label_text = f"请选择 {self.current_player} 方要减1的数字:" label = tk.Label(self.ask_window, text=label_text) label.pack(padx=10, pady=10) for idx, (i, j) in enumerate(max_cells): cell = self.board[i][j] color = "red" if cell[1] == "红" else "blue" frame = tk.Frame(self.ask_window, highlightbackground=color, highlightthickness=2) coord_label = tk.Label(frame, text=f"({i+1}, {j+1})") coord_label.pack() button = tk.Button(frame, text=str(cell[0]), width=5, height=2, command=lambda i=i, j=j: self.apply_number_reduction(i, j, self.ask_window)) button.pack(padx=2, pady=2) frame.pack(side=tk.LEFT, padx=5, pady=5) def on_window_close(self): messagebox.showwarning("警告", "必须选择一个棋子才能继续操作!", parent=self.ask_window) self.ask_window.grab_set() def apply_number_reduction(self, i, j, window): number, player = self.board[i][j] if number == 1: self.board[i][j] = None else: self.board[i][j] = (number - 1, player) self.penalty_highlight = None self.update_button(i, j) # 只有当 window 存在时才销毁 if window: window.destroy() self.is_penalty_window_open = False self.switch_player() def reset_game(self): self.board = [[None for _ in range(3)] for _ in range(3)] for i in range(3): for j in range(3): self.buttons[i][j].config(text="", bg="white") self.current_player = "红" self.penalty_highlight = None self.is_penalty_window_open = False if __name__ == "__main__": root = tk.Tk() game = NumberChess(root) root.mainloop()