高通台灣AI黑客松|競賽說明會
|

用生成式AI打造「春仔」產生器

   

作者:Ted Lee

前言

時序來到了 2025 年農曆新年前夕,看到了「台語貓」很努力地用台文來設計菱形的紅色小春聯 [2]。這讓我興起了一個念頭:能否用程式來動態產生呢?

用哪個 GPT 來生程式碼?

我們用過了
1.聯發科的達哥(聯發科達哥 GPT 生成高師 Arduino 套件程式之行動研究
2.Claude台語 MP3 播放器(Claude + Python):弓蕉(kin)的台語秘密
3.MS Copilot【學習程式新工具】用 MS Copilot 生成 micro:bit 感測器程式碼
,也玩過了 Google GeminiChatGPTChat Everywhere 之後,我們決定先挑選 Claude 來試試。

Claude 生成 Python 程式碼

如圖 1,在 Claude 中輸入以下咒語:

(人設)你是 Python 高手
(任務)使用 Tkinter,畫出「春仔」:中間斗大的菱形,紅底,燙金花邊。讓使用者輸人 吉祥話 和 作者
(輸出)產生 Python 程式碼和流程圖,要詳細註解

圖 1:在 Claude 中輸入咒語

我們使用陳會安老師開發的 fCahrt 來執行生成的 Python 程式如圖 2。

圖 2:Claude 生成程式碼的執行畫面

再經過反覆地提出需求並請 Claude 修改程式後,我們可以得到圖 3 的「春仔產生器」:

圖 3:春仔產生器

完整的程式碼如下:


import tkinter as tk
import random
import os
from PIL import ImageGrab

def close_app():
    root.quit()
    root.destroy()

def get_next_filename(base_name="春仔_LTT", ext=".png"):
    """ 取得下一個可用的檔名(若檔案已存在則加上流水號)"""
    counter = 1
    filename = f"{base_name}{ext}"
    while os.path.exists(filename):
        filename = f"{base_name}_{counter}{ext}"
        counter += 1
    return filename

def capture_screen():
    x, y, w, h = canvas.winfo_rootx(), canvas.winfo_rooty(), canvas.winfo_width(), canvas.winfo_height()
    filename = get_next_filename()
    ImageGrab.grab().crop((x, y, x + w, y + h)).save(filename)
    print(f"📷 已儲存圖片:{filename}")

def restart_app():
    root.destroy()
    main()

def main():
    global root, canvas, diamond, text_id, author_id
    root = tk.Tk()
    root.title("春仔 產生器──Powered by 李俊德(Lí-tsùn-tik)")
    root.geometry("2560x1440+130+10")  # 設定為大視窗顯示
    frame = tk.Frame(root)
    frame.pack(pady=20)
   
    # 吉祥話輸入
    tk.Label(frame, font=('Arial',20,'bold'), text="吉祥話:").grid(row=0, column=0)
    message_entry = tk.Entry(frame, font=('Arial',20), width=50)
    message_entry.grid(row=0, column=1)
    message_entry.insert(0, "Siánn物攏有")
   
    def clear_msg(event):
        message_entry.delete(0, tk.END)
    message_entry.bind('', clear_msg)
   
    # 作者輸入
    tk.Label(frame, font=('Arial',20,'bold'), text="作 者:").grid(row=1, column=0)
    author_entry = tk.Entry(frame, font=('Arial',20), width=50)
    author_entry.grid(row=1, column=1)
    author_entry.insert(0, "李俊德(Lí-tsùn-tik)")
   
    def clear_author(event):
        author_entry.delete(0, tk.END)
    author_entry.bind('', clear_author)
   
    def start_app():
        message = message_entry.get() if message_entry.get() else "Siánn物攏有"
        author = author_entry.get() if author_entry.get() else "李俊德(Lí-tsùn-tik)"
        frame.destroy()
       
        global canvas, diamond, text_id, author_id
        canvas = tk.Canvas(root, bg="white")
        canvas.pack(fill=tk.BOTH, expand=True)
       
        root.update_idletasks()
        w = root.winfo_width()
        h = root.winfo_height()
       
        diamond_size = 900
        x1, y1 = (w - diamond_size) // 2, (h - diamond_size) // 2
        x2, y2 = x1 + diamond_size, y1 + diamond_size
        center_x, center_y = (x1 + x2) // 2, (y1 + y2) // 2
       
        diamond = canvas.create_polygon(
            (center_x, y1, x2, center_y, center_x, y2, x1, center_y),
            fill="red", outline="gold", width=10
        )
       
        # 設定吉祥話為金黃色加黑色外框
        text_id = canvas.create_text(
            center_x, center_y - 30, text=message, font=("Arial", 26, "bold"), fill="black", width=900, justify="center"
        )
        canvas.create_text(
            center_x - 6, center_y - 32, text=message, font=("Arial", 26, "bold"), fill="gold", width=400, justify="center"
        )
       
        # 設定作者為暗紅色
        author_id = canvas.create_text(
            center_x, center_y + 50, text=f"{author}", font=("Arial", 12), fill="#BB0000", width=400, justify="center"
        )
       
        tk.Button(root, font=('Arial',10), text="翕  相", command=capture_screen).pack(pady=10)
        tk.Button(root, font=('Arial',10), text="再生一擺", command=restart_app).pack(pady=10)
        tk.Button(root, font=('Arial',10), text="再  會", command=close_app).pack(pady=10)
       
    tk.Button(frame, font=('Arial',20), text="開始耍", command=start_app).grid(row=2, columnspan=2, pady=10)
    root.mainloop()

main()

 

程式碼的分析技巧可參考第二節的各篇拙著。
最後,在 Mermaid Chart 中貼入以下 Mermaid 語法格式的流程圖,我們就能得到以上以模組化程式設計(modular programming)風格生成的程式碼中主副程式問的完整呼叫關係圖(call graph),圖 4。


graph TD
    A[main] --> B[root.mainloop]
    A --> C[start_app]
   
    C --> D[frame.destroy]
    C --> E[canvas.create_polygon]
    C --> F[canvas.create_text]
    C --> G[Button/capture_screen]
    C --> H[Button/restart_app]
    C --> I[Button/close_app]
   
    G --> J[get_next_filename]
    G --> K[ImageGrab.grab]
    G --> L[save]
   
    H --> M[root.destroy]
    H --> A
   
    I --> N[root.quit]
    I --> M
   
    %% 事件綁定
    A --> O[clear_msg]
    A --> P[clear_author]
   
    %% 樣式定義
    classDef mainFunction fill:#f9f,stroke:#333,stroke-width:2px
    classDef uiFunction fill:#bbf,stroke:#333,stroke-width:2px
    classDef utilFunction fill:#bfb,stroke:#333,stroke-width:2px
   
    %% 套用樣式
    class A mainFunction
    class C,G,H,I uiFunction
    class J,K,L utilFunction

圖 4:程式碼對應的流程圖

Websim.ai 生成網頁

在上一節中,我們產生了 Python 版的春仔。此外,我們亦可使用 Websim.ai這個提供 AI 服務的網站來生網頁版的喔!
完整的操作步驟和上節相似,以咒語來生成 HTML+CSS+JavaScript 三位一體的網頁。更迷人的是,它可以「自動」幫我們掛到它們家的網頁伺服器(web server)呢!
相信各位讀者一定手癢難奈了吧?在您開始動手試之前,請先欣賞我們的成品(春仔 產生器,圖 5)。

圖 5:Websim.ai 生成的網頁版春仔

[1]六種授權條款
[2]這個菱形的小春聯叫做「斗方」,台語叫「春仔(tshun — á)」。

(作者為本刊專欄作家,本文同步表於作者部落格,原文連結;責任編輯:謝涵如)

Ted Lee

訂閱MakerPRO知識充電報

與40000位開發者一同掌握科技創新的技術資訊!

Author: Ted Lee

從工程師轉任中學教師,又為了捍衛教育理念,投身成為 STEAM 教育工作者,自稱「無可救藥的人文教育理想主義者」的李俊德(Ted Lee)。

Share This Post On
468 ad

Submit a Comment

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *