作者:Ted Lee
1979 年,在高雄某處的弓[2] 蕉園裡,埋藏了一樁天大的秘密。根據當年幸運逃出的生還者口述,那片偌大弓蕉園的深處,由一條身長數尺的「Python」千年來一直守護著一件傳說中的上古兵器「Claude」。江湖中早有傳言:「得 Claude 者得天下。」也就是這樣,在那年的某個夜晚,一群群如海水般的人潮不斷地來到了弓蕉園,開始了一場腥風血雨的人間殺戮。到底是誰最後能找到 Claude 的隱身之處呢?能解開這個謎團的,據說是一位操有標準老泉腔的少年英雄……
用哪個 ChatGPT 來生?
世界上 GPT 百百款,為何我們獨挑 Claude 這枝花?其實,根據先前使用 Copilot 生成 micro:bit Python 程式碼的經驗,我們最早是在 Copilot 上下以下咒語來生的:
(人設)你是 Python 程式專家
(任務)Tkinter 視窗版的 MP3 播放器,選擇多首 MP3 曲目後,顯示在畫面上,連續隨機播放這些曲目不停止。正在播放的曲目要用顏色標記
(輸出)Python 程式碼,要含詳細註解,並生成 Mermaid 流程圖
但是,天不從人願。工具總是有其侷限性:有一好就不一定有二好。Copilot 生出的程式碼,再怎麼叫它修改就是一直不能「自動播放」。
正當準備放棄之際,突然靈光一現:把程式碼貼給其他版本的 GPT 來幫助抓蟲呢?
於是乎產出了以下符合需求的程式碼(在陳會安老師設計的 fChart Thonny 上的執行畫面如圖 1):
MP3 Player_Coipilot+Claude.py
import tkinter as tk
from tkinter import filedialog
import pygame
import random
import os
# 初始化 Pygame 的混音器
pygame.mixer.init()
# 建立主視窗
root = tk.Tk()
root.title("弓蕉園的秘密 字詞放送 Powered by 李俊德 Lí Tsùn-ti")
# 取得螢幕寬度和高度
screen_width = root.winfo_screenwidth()
screen_height = root.winfo_screenheight()
# 設定視窗大小為螢幕的 70%
window_width = int(screen_width * 0.7)
window_height = int(screen_height * 0.7)
# 計算視窗的初始位置,使其位於畫面的中上方
x_position = int((screen_width - window_width) / 2)
y_position = int(screen_height * 0.1) # 設定為螢幕高度的 10% 處
# 設定視窗的位置和大小
root.geometry(f"{window_width}x{window_height}+{x_position}+{y_position}")
# 儲存選擇的檔案路徑和播放狀態
file_paths = []
current_index = 0
is_paused = False
is_playing = False
def select_files():
global file_paths, current_index
# 打開文件對話框讓用戶選擇 MP3 檔案
new_files = list(filedialog.askopenfilenames(filetypes=[("MP3 Files", "*.mp3")]))
if new_files:
file_paths = new_files
# 隨機排列播放順序
random.shuffle(file_paths)
current_index = 0
update_file_listbox()
load_and_play_current()
def load_and_play_current():
global is_playing
if file_paths:
# 加載當前 MP3 檔案
pygame.mixer.music.load(file_paths[current_index])
# 播放音樂
pygame.mixer.music.play()
is_playing = True
highlight_current_track()
def pause_music():
global is_paused
if not is_playing:
return
if is_paused:
pygame.mixer.music.unpause()
pause_button.config(text="暫停")
else:
pygame.mixer.music.pause()
pause_button.config(text="繼續")
is_paused = not is_paused
def exit_program():
pygame.mixer.music.stop()
root.destroy()
def play_next():
global current_index, is_playing
if not file_paths:
return
current_index = (current_index + 1) % len(file_paths)
if is_playing:
load_and_play_current()
def update_file_listbox():
file_listbox.delete(0, tk.END)
for path in file_paths:
# 只顯示檔案名稱而不是完整路徑
filename = os.path.basename(path)
file_listbox.insert(tk.END, filename)
def highlight_current_track():
for i in range(file_listbox.size()):
if i == current_index:
file_listbox.itemconfig(i, {'bg':'yellow'})
else:
file_listbox.itemconfig(i, {'bg':'white'})
def check_music_end():
if is_playing and not pygame.mixer.music.get_busy() and not is_paused:
# 當前曲目播放結束且不是暫停狀態時,播放下一首
play_next()
# 每 100 毫秒檢查一次播放狀態
root.after(100, check_music_end)
# 建立選擇檔案按鈕
select_button = tk.Button(root, text="選擇 MP3 檔案", command=select_files)
select_button.pack(pady=10)
# 顯示選擇的檔案路徑
file_listbox = tk.Listbox(root, selectmode=tk.SINGLE)
file_listbox.pack(pady=10, fill=tk.BOTH, expand=True)
# 建立暫停按鈕
pause_button = tk.Button(root, text="暫停", command=pause_music)
pause_button.pack(pady=10)
# 建立結束按鈕,放在右上方
exit_button = tk.Button(root, text="結束", command=exit_program)
exit_button.place(relx=1.0, x=-10, y=10, anchor='ne')
# 啟動檢查播放結束事件的循環
root.after(100, check_music_end)
# 啟動主迴圈
root.mainloop()

圖 1:Copilot+Claude 生成的「弓蕉園的秘密 字詞放送(MP3 Player_Coipilot+Claude.py)」播放器
因此,我們得到了一個結論:
哪個 GPT 最好:混成的(hybrid)[3] 上讚啦!
Claude 生成的程式碼
將以上的相同咒語輸入到 Claude 中,我們可以得到下列以物件導向程式(Object-Oriented Programming,OOP)風格的程式碼,其執行的畫面如圖 2 所示。
OOP.py
import tkinter as tk
from tkinter import ttk, filedialog
import pygame
import random
import os
#from mutagen.mp3 import MP3
from threading import Thread
import time
class MP3Player:
def __init__(self):
# 初始化播放器
pygame.mixer.init()
# 創建主窗口
self.root = tk.Tk()
self.root.title("MP3 播放器")
self.root.geometry("1700x1300")
# 播放列表相關變量
self.playlist = [] # 儲存音樂文件路徑
self.current_playing = None # 當前播放的索引
self.is_playing = False
self.setup_ui()
self.setup_threads()
def setup_ui(self):
"""設置用戶界面"""
# 創建按鈕框架
button_frame = ttk.Frame(self.root)
button_frame.pack(pady=10)
# 添加控制按鈕
ttk.Button(button_frame, text="添加音樂", command=self.add_music).pack(side=tk.LEFT, padx=5)
ttk.Button(button_frame, text="開始播放", command=self.start_playing).pack(side=tk.LEFT, padx=5)
ttk.Button(button_frame, text="停止播放", command=self.stop_playing).pack(side=tk.LEFT, padx=5)
# 創建播放列表
self.playlist_box = tk.Listbox(self.root, width=70, height=20)
self.playlist_box.pack(pady=10)
# 創建當前播放標籤
self.current_label = ttk.Label(self.root, text="當前未播放")
self.current_label.pack(pady=10)
def setup_threads(self):
"""設置後台線程"""
self.playing_thread = Thread(target=self.playing_loop, daemon=True)
self.playing_thread.start()
def add_music(self):
"""添加音樂文件到播放列表"""
files = filedialog.askopenfilenames(
filetypes=[("MP3 Files", "*.mp3")],
title="選擇音樂文件"
)
for file in files:
self.playlist.append(file)
# 只顯示文件名而不是完整路徑
self.playlist_box.insert(tk.END, os.path.basename(file))
def start_playing(self):
"""開始播放"""
if not self.is_playing and self.playlist:
self.is_playing = True
def stop_playing(self):
"""停止播放"""
self.is_playing = False
pygame.mixer.music.stop()
self.current_playing = None
self.update_current_playing()
def playing_loop(self):
"""播放循環(在後台線程中運行)"""
while True:
if self.is_playing and not pygame.mixer.music.get_busy():
if self.playlist:
# 隨機選擇下一首
next_index = random.randint(0, len(self.playlist) - 1)
# 加載並播放音樂
try:
pygame.mixer.music.load(self.playlist[next_index])
pygame.mixer.music.play()
self.current_playing = next_index
self.update_current_playing()
except:
print(f"無法播放文件: {self.playlist[next_index]}")
time.sleep(0.1) # 避免過度佔用 CPU
def update_current_playing(self):
"""更新界面顯示當前播放歌曲"""
# 重置所有項目的顏色
for i in range(self.playlist_box.size()):
self.playlist_box.itemconfig(i, {'bg': 'white'})
if self.current_playing is not None:
# 設置當前播放項目的背景色
self.playlist_box.itemconfig(self.current_playing, {'bg': 'light blue'})
self.current_label.config(text=f"正在播放: {os.path.basename(self.playlist[self.current_playing])}")
else:
self.current_label.config(text="當前未播放")
def run(self):
"""運行應用程序"""
self.root.mainloop()
if __name__ == "__main__":
player = MP3Player()
player.run()

圖 2:OOP.py 的執行畫面
程式碼簡化1:非OOP版
我們讓 Claude 將第三小節的 OOP 方式改成非 OOP 程式如下,其執行畫面如圖 3 所示。
Non-OOP.py
import tkinter as tk
from tkinter import ttk, filedialog
import pygame
import random
import os
#from mutagen.mp3 import MP3
from threading import Thread
import time
# 全域變數
playlist = [] # 儲存音樂檔案路徑
current_playing = None # 當前播放的索引
is_playing = False # 播放狀態
def setup_ui(root, playlist_box, current_label):
"""設置使用者介面"""
# 建立按鈕框架
button_frame = ttk.Frame(root)
button_frame.pack(pady=10)
# 新增控制按鈕
ttk.Button(
button_frame,
text="新增音樂",
command=lambda: add_music(playlist_box)
).pack(side=tk.LEFT, padx=5)
ttk.Button(
button_frame,
text="開始播放",
command=lambda: start_playing()
).pack(side=tk.LEFT, padx=5)
ttk.Button(
button_frame,
text="停止播放",
command=lambda: stop_playing(playlist_box, current_label)
).pack(side=tk.LEFT, padx=5)
def add_music(playlist_box):
"""新增音樂檔案到播放清單"""
files = filedialog.askopenfilenames(
filetypes=[("MP3 Files", "*.mp3")],
title="選擇音樂檔案"
)
for file in files:
playlist.append(file)
# 只顯示檔案名而不是完整路徑
playlist_box.insert(tk.END, os.path.basename(file))
def start_playing():
"""開始播放"""
global is_playing
if not is_playing and playlist:
is_playing = True
def stop_playing(playlist_box, current_label):
"""停止播放"""
global is_playing, current_playing
is_playing = False
pygame.mixer.music.stop()
current_playing = None
update_current_playing(playlist_box, current_label)
def update_current_playing(playlist_box, current_label):
"""更新介面顯示當前播放歌曲"""
# 重置所有項目的顏色
for i in range(playlist_box.size()):
playlist_box.itemconfig(i, {'bg': 'white'})
if current_playing is not None:
# 設置當前播放項目的背景色
playlist_box.itemconfig(current_playing, {'bg': 'light blue'})
current_label.config(
text=f"正在播放: {os.path.basename(playlist[current_playing])}"
)
else:
current_label.config(text="當前未播放")
def playing_loop(playlist_box, current_label):
"""播放循環(在背景執行緒中執行)"""
global current_playing
while True:
if is_playing and not pygame.mixer.music.get_busy():
if playlist:
# 隨機選擇下一首
next_index = random.randint(0, len(playlist) - 1)
# 載入並播放音樂
try:
pygame.mixer.music.load(playlist[next_index])
pygame.mixer.music.play()
current_playing = next_index
update_current_playing(playlist_box, current_label)
except Exception as e:
print(f"無法播放檔案: {playlist[next_index]}")
print(f"錯誤訊息: {str(e)}")
time.sleep(0.1) # 避免過度佔用 CPU
def main():
"""主程式"""
# 初始化播放器
pygame.mixer.init()
# 建立主視窗
root = tk.Tk()
root.title("MP3 播放器")
root.geometry("1200x1000")
# 建立播放清單
playlist_box = tk.Listbox(root, width=70, height=20)
playlist_box.pack(pady=10)
# 建立當前播放標籤
current_label = ttk.Label(root, text="當前未播放")
current_label.pack(pady=10)
# 設置使用者介面
setup_ui(root, playlist_box, current_label)
# 啟動播放執行緒
playing_thread = Thread(
target=lambda: playing_loop(playlist_box, current_label),
daemon=True
)
playing_thread.start()
# 開始主迴圈
root.mainloop()
if __name__ == "__main__":
main()

圖 3:Non-OOP.py 的執行畫面。
程式碼簡化 2:非多執行緒版
我再讓 Claude 將第四小節的非 OOP 版本以非多執行緒的方式產生如下的程式碼,以便進行第六到八小節的細部拆解[4]。
No-threading.py
import tkinter as tk
from tkinter import ttk, filedialog
import pygame
import random
import os
# 全域變數
playlist = [] # 儲存音樂檔案路徑
current_playing = None # 當前播放的索引
is_playing = False # 播放狀態
def setup_ui(root, playlist_box, current_label):
"""設置使用者介面"""
# 建立按鈕框架
button_frame = ttk.Frame(root)
button_frame.pack(pady=10)
# 新增控制按鈕
ttk.Button(
button_frame,
text="新增音樂",
command=lambda: add_music(playlist_box)
).pack(side=tk.LEFT, padx=5)
ttk.Button(
button_frame,
text="開始播放",
command=lambda: start_playing()
).pack(side=tk.LEFT, padx=5)
ttk.Button(
button_frame,
text="停止播放",
command=lambda: stop_playing(playlist_box, current_label)
).pack(side=tk.LEFT, padx=5)
def add_music(playlist_box):
"""新增音樂檔案到播放清單"""
files = filedialog.askopenfilenames(
filetypes=[("MP3 Files", "*.mp3")],
title="選擇音樂檔案"
)
for file in files:
playlist.append(file)
# 只顯示檔案名而不是完整路徑
playlist_box.insert(tk.END, os.path.basename(file))
def start_playing():
"""開始播放"""
global is_playing
if not is_playing and playlist:
is_playing = True
def stop_playing(playlist_box, current_label):
"""停止播放"""
global is_playing, current_playing
is_playing = False
pygame.mixer.music.stop()
current_playing = None
update_current_playing(playlist_box, current_label)
def update_current_playing(playlist_box, current_label):
"""更新介面顯示當前播放歌曲"""
# 重置所有項目的顏色
for i in range(playlist_box.size()):
playlist_box.itemconfig(i, {'bg': 'white'})
if current_playing is not None:
# 設置當前播放項目的背景色
playlist_box.itemconfig(current_playing, {'bg': 'light blue'})
current_label.config(
text=f"正在播放: {os.path.basename(playlist[current_playing])}"
)
else:
current_label.config(text="當前未播放")
def check_and_play(root, playlist_box, current_label):
"""檢查並播放音樂(替代原本的執行緒)"""
global current_playing
if is_playing and not pygame.mixer.music.get_busy():
if playlist:
# 隨機選擇下一首
next_index = random.randint(0, len(playlist) - 1)
# 載入並播放音樂
try:
pygame.mixer.music.load(playlist[next_index])
pygame.mixer.music.play()
current_playing = next_index
update_current_playing(playlist_box, current_label)
except Exception as e:
print(f"無法播放檔案: {playlist[next_index]}")
print(f"錯誤訊息: {str(e)}")
# 每100毫秒檢查一次
root.after(100, lambda: check_and_play(root, playlist_box, current_label))
def main():
"""主程式"""
# 初始化播放器
pygame.mixer.init()
# 建立主視窗
root = tk.Tk()
root.title("MP3 播放器")
root.geometry("1200x1000")
# 建立播放清單
playlist_box = tk.Listbox(root, width=70, height=20)
playlist_box.pack(pady=10)
# 建立當前播放標籤
current_label = ttk.Label(root, text="當前未播放")
current_label.pack(pady=10)
# 設置使用者介面
setup_ui(root, playlist_box, current_label)
# 啟動檢查播放狀態的循環
check_and_play(root, playlist_box, current_label)
# 開始主迴圈
root.mainloop()
if __name__ == "__main__":
main()
程式碼拆解 1:開視窗
寫程式就像是玩拼圖(圖 4),最後產出的軟體專案也都是由一小塊、一小塊的程式積木拼湊而成的。

圖 4:程式如拼圖
因此,我們依續將第二節的原始專案 MP3 Player_Copilot+Claude.py 細部分解如圖 5 所示:

圖 5:MP3 Player_Copilot+Claude.py 拆解
- Window.py:第六節。使用 Python 標準的 UI 套件 Tkinter 撰寫的視窗(圖 6)。
- UI.py:第七節。在 Window.py 裡頭擺放各種 UI 元件(圖 7)。
- Player.py:第八節。使用 Pygame 套件來播放 MP3 音檔(圖 8)。
Window.py
import tkinter as tk
from tkinter import ttk
def main():
root = tk.Tk()
root.title("MP3 播放器")
root.geometry("1200x1000")
# 開始主迴圈
root.mainloop()
if __name__ == "__main__":
main()

圖 6:Window.py 開出來的視窗畫面
程式碼拆解 2:UI 佈局
UI.py 使用了包含在 Python 的 Tkinter(Tools Kit Interface)視窗套件(package)[5]中的TTK(Themed Tkinter)及 File Dialog 模組(module),我們將整個程式邏輯佈局以圖 7 的紅字註解來標示。

圖 7:視窗程式的 UI 佈局設計
UI.py
import tkinter as tk
from tkinter import ttk, filedialog
import pygame
import random
import os
#from mutagen.mp3 import MP3
from threading import Thread
import time
# 全域變數
playlist = [] # 儲存音樂檔案路徑
current_playing = None # 當前播放的索引
is_playing = False # 播放狀態
def setup_ui(root, playlist_box, current_label):
"""設置使用者介面"""
# 建立按鈕框架
button_frame = ttk.Frame(root)
button_frame.pack(pady=10)
# 新增控制按鈕
ttk.Button(
button_frame,
text="新增音樂",
command=lambda: add_music(playlist_box)
).pack(side=tk.LEFT, padx=5)
ttk.Button(
button_frame,
text="開始播放",
command=lambda: start_playing()
).pack(side=tk.LEFT, padx=5)
ttk.Button(
button_frame,
text="停止播放",
command=lambda: stop_playing(playlist_box, current_label)
).pack(side=tk.LEFT, padx=5)
def add_music(playlist_box):
"""新增音樂檔案到播放清單"""
pass
def start_playing():
"""開始播放"""
pass
def stop_playing(playlist_box, current_label):
"""停止播放"""
pass
def main():
"""主程式"""
# 初始化播放器
pygame.mixer.init()
# 建立主視窗
root = tk.Tk()
root.title("MP3 播放器")
root.geometry("1200x1000")
# 建立播放清單
playlist_box = tk.Listbox(root, width=70, height=20)
playlist_box.pack(pady=10)
# 建立當前播放標籤
current_label = ttk.Label(root, text="當前未播放")
current_label.pack(pady=10)
# 設置使用者介面
setup_ui(root, playlist_box, current_label)
# 開始主迴圈
root.mainloop()
if __name__ == "__main__":
main()
程式碼拆解 3:MP3 播放
更進一步地,我們在 Claude 下達以下咒語:
抽出程式碼中使用 pygame 來播放 mp3 檔最基本的程式碼,不用 UI
它就能將 MP3 Player_Coipilot+Claude.py 當中使用 Pyagme 套件來播放 MP3 音檔的原型抽取為下列的 Player.py,其執行畫面如圖 8 所示。
Player.py
import pygame
import time
def play_mp3(file_path):
"""播放單一 MP3 檔案"""
# 初始化 pygame mixer
pygame.mixer.init()
try:
# 載入音樂檔案
pygame.mixer.music.load(file_path)
# 開始播放
pygame.mixer.music.play()
# 等待音樂播放完畢
while pygame.mixer.music.get_busy():
time.sleep(0.1)
except Exception as e:
print(f"播放時發生錯誤: {str(e)}")
finally:
# 結束播放
pygame.mixer.music.stop()
pygame.mixer.quit()
if __name__ == "__main__":
# 使用範例
file_path = "18.拄著.mp3" # 替換成您的 MP3 檔案路徑
play_mp3(file_path)

圖 8:Player.py 的執行畫面
功能擴充 1:暫停
圖 2 或圖 3 以 Claude 自動生成的程式碼的結果是比較符合我們想要的結果(比起圖 1 來說)。
於是,我們更進一步追問 Claude:
再加上一個「暫停」按鈕,按一下暫停播放,再按一下重上一個暫停點續播
Claude 立刻生出 Pause.py 了(圖 9)。
Pause.py
import tkinter as tk
from tkinter import ttk, filedialog
import pygame
import random
import os
#from mutagen.mp3 import MP3
from threading import Thread
import time
# 全域變數
playlist = [] # 儲存音樂檔案路徑
current_playing = None # 當前播放的索引
is_playing = False # 播放狀態
is_paused = False # 暫停狀態
def setup_ui(root, playlist_box, current_label):
"""設置使用者介面"""
# 建立按鈕框架
button_frame = ttk.Frame(root)
button_frame.pack(pady=10)
# 新增控制按鈕
ttk.Button(
button_frame,
text="新增音樂",
command=lambda: add_music(playlist_box)
).pack(side=tk.LEFT, padx=5)
ttk.Button(
button_frame,
text="開始播放",
command=lambda: start_playing()
).pack(side=tk.LEFT, padx=5)
ttk.Button(
button_frame,
text="暫停/繼續",
command=lambda: toggle_pause(current_label)
).pack(side=tk.LEFT, padx=5)
ttk.Button(
button_frame,
text="停止播放",
command=lambda: stop_playing(playlist_box, current_label)
).pack(side=tk.LEFT, padx=5)
def toggle_pause(current_label):
"""切換暫停/繼續狀態"""
global is_paused
if is_playing: # 只有在播放狀態才能暫停/繼續
is_paused = not is_paused
if is_paused:
pygame.mixer.music.pause()
current_label.config(
text=f"已暫停: {os.path.basename(playlist[current_playing])}"
)
else:
pygame.mixer.music.unpause()
current_label.config(
text=f"正在播放: {os.path.basename(playlist[current_playing])}"
)
def add_music(playlist_box):
"""新增音樂檔案到播放清單"""
files = filedialog.askopenfilenames(
filetypes=[("MP3 Files", "*.mp3")],
title="選擇音樂檔案"
)
for file in files:
playlist.append(file)
# 只顯示檔案名而不是完整路徑
playlist_box.insert(tk.END, os.path.basename(file))
def start_playing():
"""開始播放"""
global is_playing, is_paused
if not is_playing and playlist:
is_playing = True
is_paused = False # 重置暫停狀態
def stop_playing(playlist_box, current_label):
"""停止播放"""
global is_playing, current_playing, is_paused
is_playing = False
is_paused = False
pygame.mixer.music.stop()
current_playing = None
update_current_playing(playlist_box, current_label)
def update_current_playing(playlist_box, current_label):
"""更新介面顯示當前播放歌曲"""
# 重置所有項目的顏色
for i in range(playlist_box.size()):
playlist_box.itemconfig(i, {'bg': 'white'})
if current_playing is not None:
# 設置當前播放項目的背景色
playlist_box.itemconfig(current_playing, {'bg': 'light blue'})
status = "已暫停" if is_paused else "正在播放"
current_label.config(
text=f"{status}: {os.path.basename(playlist[current_playing])}"
)
else:
current_label.config(text="當前未播放")
def playing_loop(playlist_box, current_label):
"""播放循環(在背景執行緒中執行)"""
global current_playing
while True:
if is_playing and not is_paused and not pygame.mixer.music.get_busy():
if playlist:
# 隨機選擇下一首
next_index = random.randint(0, len(playlist) - 1)
# 載入並播放音樂
try:
pygame.mixer.music.load(playlist[next_index])
pygame.mixer.music.play()
current_playing = next_index
update_current_playing(playlist_box, current_label)
except Exception as e:
print(f"無法播放檔案: {playlist[next_index]}")
print(f"錯誤訊息: {str(e)}")
time.sleep(0.1) # 避免過度佔用 CPU
def main():
"""主程式"""
# 初始化播放器
pygame.mixer.init()
# 建立主視窗
root = tk.Tk()
root.title("MP3 播放器")
root.geometry("1400x1200")
# 建立播放清單
playlist_box = tk.Listbox(root, width=70, height=20)
playlist_box.pack(pady=10)
# 建立當前播放標籤
current_label = ttk.Label(root, text="當前未播放")
current_label.pack(pady=10)
# 設置使用者介面
setup_ui(root, playlist_box, current_label)
# 啟動播放執行緒
playing_thread = Thread(
target=lambda: playing_loop(playlist_box, current_label),
daemon=True
)
playing_thread.start()
# 開始主迴圈
root.mainloop()
if __name__ == "__main__":
main()

圖 9:Pause.py 的執行畫面
功能擴充 2:動態顯示詞條內容
我們使用本文生成的播放器所播放的台語泉腔發音的 18 字詞內容為:
- 請你莫講,你莫烏白呸喙瀾!
- 魔神仔,聽講深山林內有足濟(tsēre)魔神仔。
- 便看,欲(berh)按怎做,等對方條件開出來才便看。
- 歇熱,恁學校當時開始歇熱?
- 傳,我的代誌,你莫烏白去宣傳。
- 出業,讀冊讀半死 出業做苦力 (ku-lí)。
- 橫(huînn)直,毋管你按怎講,橫(huînn)直我毋信。
- 順紲,你若欲(berh)去(khìr)買菜,順紲去(khìr)共我納電火(hér)錢。
- 抑無,你若是無法度一擺總納,抑無,看欲(berh)分做幾期?
- 毋是勢,等一下看毋是勢,你就緊走。
- 明年,伊明年就出業矣。
- 賴賴趖,救蟲,賴賴趖;救人,無功勞。
- 搜揣(tshēr),欲(berh)了解這个議題(terê),你聽(thing)好先上網搜揣(tshēr)相關的資料。
- 允准,無我的允准,你袂(buē)使來阮兜。
- 拍毋見,昨日我拍毋見一千箍。
- 判 ,法院的判決無公平(pînn),伊欲(berh)閣上訴。
- 夠額,阮公司的員工已經夠額,無欲(berh)閣倩矣。
- 拄著,伊近(kūn)來定定去拄著麻煩。
如果能在圖 9 的畫面加上播放音檔時能自動顯示對應的字詞和其例句,定能使這個播放器更精緻實用。這部份就留給讀者們去找 Claude 協助囉。如果您能成功完成這個任務,也歡迎留言分享給我們!
[1]六種授權條款。
[2]華語的「香蕉」,在台語漢字是念及書寫成「弓蕉」。而「弓」的白音是 king。台灣各地在不同音變下,本文是使用筆者自小的「新─老泉腔」語感而念成「kin」(老泉則以央元音 ir 而發成「kirn」)。
[3]除了 OpenAI 的版本外,目前較常見的 GPT 版本有:Google Gemini、MS Copilot、Claude、Chat Everywhere……。
[4]程式的拆解技巧可參考拙著《Python玩AI,你也可以 — 從CVZone入門吧!》。
[5]Tkinter 的教材可參考拙著《Scratch到Python輕鬆學》。其中,帳密的申請請讀者 自行接洽全華業務。
(作者為本刊專欄作家,本文同步表於作者部落格,原文連結;責任編輯:謝涵如)
- 用GenAI生成連連看樣板 - 2025/05/15
- 細談「春仔產生器」的專案拆解 - 2025/04/17
- 用生成式AI打造「春仔」產生器 - 2025/03/12
訂閱MakerPRO知識充電報
與40000位開發者一同掌握科技創新的技術資訊!