# ========== 功能函數 ========== def set_cycle_rule(rule_str):     global N, rule_text     default = list(range(N))     parts = [s.strip() for s in rule_str.split(".") if s.strip() != ""]     if len(parts) == 0:         # 空或全是空白 -> 設為預設         rule_text.value = ".".join(map(str, default))         return default     try:         lst = [int(x) for x in parts]     except Exception:         # 解析非整數 -> 設為預設         rule_text.value = ".".join(map(str, default))         return default     # 檢查每個數值是否在 0..N-1 範圍內     if any((v < 0 ) for v in lst):         rule_text.value = ".".join(map(str, default))         return default     # 成功解析且都在合法範圍     return lst def cycle_value(val):     """根據 cycle_rule 回傳下一個值"""     if val not in cycle_rule:         return cycle_rule[0]     idx = cycle_rule.index(val)     return cycle_rule[(idx + 1) % len(cycle_rule)] def apply_button(r, c):     """按下按鈕 A[r,c],變色四個相鄰的 B 方格"""     global steps, board     r0, c0 = r - 1, c - 1     if r0 + 1 >= N or c0 + 1 >= N:         return     for dr in [0, 1]:         for dc in [0, 1]:             rr, cc = r0 + dr, c0 + dc             board[rr, cc] = cycle_value(board[rr, cc])     steps += 1     redraw_board() def reset_board(_=None):     """重設棋盤"""     global board, steps     board = initial_board.copy()     steps = 0     redraw_board() def generate_initial_board():     """生成 NxN 棋盤,黑格=0,白格=white_value"""     b = np.zeros((N, N), dtype=int)     for r in range(N):         for c in range(N):             if (r + c) % 2 == 0:                 b[r, c] = black_value             else:                 b[r, c] = white_value     return b def draw_board():     """畫出棋盤 + 按鈕"""     fig, ax = plt.subplots(figsize=(5, 5))     ax.set_xlim(0, N)     ax.set_ylim(0, N)     ax.set_xticks([])     ax.set_yticks([])     ax.set_aspect('equal')     ax.invert_yaxis()     # 畫格子 (顯示數字)     for r in range(N):         for c in range(N):             ax.add_patch(plt.Rectangle((c, r), 1, 1, color="white", ec='black', linewidth=2))             ax.text(c + 0.5, r + 0.5, str(board[r, c]), ha='center', va='center', fontsize=12, color='black')     # 畫綠色按鈕 A[r,c]     for r, c in valid_buttons:         cx, cy = c, r         circle = plt.Circle((cx, cy), 0.3, color=button_color)         ax.add_patch(circle)         ax.text(cx, cy, f'A{r},{c}', ha='center', va='center', fontsize=8, color='red')     # 畫步數     ax.text(N/2, -0.3, f"{steps}", ha='center', va='center', fontsize=14, color='black')     plt.show() def redraw_board():     """只更新棋盤,不清除輸入框"""     with board_output:         clear_output(wait=True)         draw_board() def update_board(_=None):     """讀取輸入框 → 更新棋盤"""     global N, cycle_rule, white_value, steps, board, initial_board, valid_buttons, button_grid     # 更新參數     try:         N = int(N_text.value)     except:         N = 3     cycle_rule = set_cycle_rule(rule_text.value)     try:         white_value = int(white_text.value)     except:         white_value = 1     steps = 0     board = generate_initial_board()     initial_board = board.copy()     valid_buttons = [(r, c) for r in range(1, N) for c in range(1, N)]     # 建立互動按鈕     button_widgets = []     for (r, c) in valid_buttons:         def make_handler(r=r, c=c):             def on_click(b):                 apply_button(r, c)             return on_click         b = widgets.Button(description=f'A{r},{c}', layout=widgets.Layout(width='70px', height='30px'))         b.on_click(make_handler(r, c))         button_widgets.append(b)     # 更新互動按鈕區     button_grid.children = button_widgets     button_grid.layout = widgets.Layout(grid_template_columns=f"repeat({N-1}, 80px)")     redraw_board()