Jev Cards 教學可以從一個很生活的念頭開始:把三杯茶放在畫面上,問朋友「哪一杯液面最高?」再讓 AI 回答同一張圖。你不必先做出大型遊戲;先完成十張自己看得懂、也說得清答案的繁中題卡,就有了可以反覆改進的小作品。
這篇寫給第一次用 Claude Code 改開源專案的讀者。我們會從固定原版程式開始,拆開題卡、答案與計分,再把「新增十題、選題材、答對優先」變成可直接交給 Claude Code 的任務與驗收條件。需要能開終端機、安裝專案套件;每個步驟都會說明看見什麼才算完成。
截至 2026 年 10 月 22 日,原作者 README已說明線上入口轉往 Opper 的 v2。以下固定的是原版儲存庫的維護快照 8e67173770ab4bbd51db1a525463db818a6d660c,不是聲稱回到首發當刻的全部部署狀態。
先說結論:好玩的看圖遊戲=自己的題卡+可信答案+一致規則
Claude Code 是幫你改作品的工程夥伴;Jev 是遊戲裡看圖作答的對手。兩者負責不同工作。先做好題目與判分,再接上即時模型,才容易知道出錯的是哪一段。
- 先在本機保留原版,用新分支修改;把外部服務的 API Key 放在伺服器環境。
- 先做一張能建置、能點選的題卡,再擴成十張;題幹、選項與解答都用繁中。
- 若作品目標是獎勵答對,排名先比答對題數,相同才比耗時;題材篩選後另開練習紀錄。
一、Jev Cards 教學先拆四個零件
把遊戲想成一場桌遊:題卡是桌上的圖,答案本是裁判手裡的解答,發牌規則決定誰看哪幾題,計分規則決定誰贏。原版題卡格式把畫面與答案寫在同一份 CardSpec,再由建置工具產生圖片與題庫。這比另外手填一份答案表更容易維持一致。
- ①「圖畫紙」:
svg是向量圖原稿,尺寸為 960×720;改圖後要重新產生 PNG。 - ②「選哪個或點哪裡」:
pick在圖上選物件,buttons按圖下選項,兩者對模型是choice;point點位置,模型回傳box,用框的中心判定。 - ③「裁判答案本」:完整題庫在
cards/deck.json;瀏覽器用的public/cards/deck.json由forPage()移除answer、target與explain,作答後再向伺服器取判定。 - ④「同一張計分紙」:
shared/game.ts放共用規則,伺服器另外檢查發牌與作答紀錄;最後畫面也必須使用相同規則。
這裡的「真值」就是你能說明、能檢查的正確答案。把 AI 猜的結果填成答案,會把猜錯也變成標準;先用可從圖形座標、數量或自有照片直接核對的小題,會比較容易開始。模型背景可接著讀Clef vs Jev 的繁中與圖片評選方法。
二、固定版本啟動:先保護鑰匙,再看到首頁
先備妥 Git、專案要求的 Node.js ≥22.18,以及可使用 Claude Code 的帳號。Node 需求來自這個快照的 package.json;Claude Code 安裝與登入依 Anthropic 官方 Quickstart操作,安裝後以 claude --version 檢查,再進入專案執行 claude。
- 執行
git clone https://github.com/Jose-Sabater/jevcards.git jevcards-zh,再執行cd jevcards-zh。 - 執行
git checkout 8e67173770ab4bbd51db1a525463db818a6d660c,再執行git switch -c zh-mini-game;用git rev-parse HEAD對照完整版本號。 - 執行
npm ci安裝鎖定套件,再用cp .env.example .env建立設定。先把BOARDS=off加入設定,讓改版練習與原版排行榜分開。 - 修改程式期間,讓
OPPER_API_KEY與TYPESAFE_API_KEY保持空白;先建置、測試與查看首頁,這一階段不要求啟用付費對戰。 - 依序執行
npm run deck、npm run dev -- --host 127.0.0.1,在同一台電腦打開終端機顯示的網址,預設為http://localhost:5173。 - 另開終端機執行
npm test與npm run build;首頁能載入、測試與建置通過,才進入下一步。
原版開發指令透過 Vite 設定一起掛上 API;正式版則以 npm run build 後的 npm start 啟動 Node 伺服器。只把靜態頁上傳到網站空間,並不等於把裁判 API 一起架好。

API Key 就像替遊戲付帳的鑰匙。保留在伺服器讀取的環境變數,別貼進聊天、題卡或 src/。Vite 官方文件明確說明 VITE_ 前綴會把值放進前端程式;因此不要改成 VITE_OPPER_API_KEY。也用 git check-ignore .env 確認忽略設定,提交前檢查 git diff --cached。
寫程式時,Claude Code 會依任務讀取專案內容並連接外部服務;官方資料使用文件區分消費與商業帳號的資料設定。這次只給它公開程式、自繪素材與假資料,被 Git 忽略的檔案仍可能被代理讀取,所以開發時設定檔也先留空。權限與資料流可搭配Agent 密鑰安全指南理解。
三、Jev Cards 教學實作:先做一張,再擴成十張繁中題卡
①「先對齊語言」:讓人與模型回答同一個問題
先請 Claude Code 讀 cards/lib.ts、scripts/build-deck.ts、shared/game.ts 與一個現有題卡模組,列出它打算改的檔案。接著貼這段任務:
請新增 cards/zh-mini.ts,沿用 CardSpec 與 defineCard。先做一題自繪「哪一杯茶液面最高」。prompt、explain、jev.context、jev.instructions 都用繁中;pick 選項的 jev 只描述左、中、右位置,不能把正確答案塞進選項描述。保留答案只在伺服器的流程,先給我一張題卡驗收。
只翻譯玩家題幹,卻讓模型收到不同意思的英文題目,兩邊就像拿到不同考卷。這裡也要分開「選項名稱」與「答案暗示」:玩家答完可看見「中杯」,模型選項則只知道「中間的杯子」,不提前知道哪杯最高。
②「圖與答案一起寫」:茶杯題的最小範例
下面這份新增檔案可以直接存成 cards/zh-mini.ts。三個杯子大小相同,中杯填色從較高的位置開始;答案就是 middle。這份題卡已在本文固定快照下完成建置,原版也通過 15 項測試與正式建置;即時 Jev 對戰未列入這次本機驗證。
import { defineCard, svgDoc, rectPx } from './lib.ts';
export default defineCard({
id: 'zh-tea-level', title: '茶杯液面', category: 'food', difficulty: 1,
prompt: '哪一杯茶的液面最高?', kind: 'pick', source: 'drawn',
svg: svgDoc(`<g fill="none" stroke="#263238" stroke-width="12">
<path d="M120 180v420h180V180M390 180v420h180V180M660 180v420h180V180"/>
</g><g fill="#D97757"><rect x="126" y="400" width="168" height="194"/>
<rect x="396" y="240" width="168" height="354"/>
<rect x="666" y="330" width="168" height="264"/></g>`),
options: [
{ id: 'left', label: '左杯', region: rectPx(120,180,180,420), jev: '左邊的杯子' },
{ id: 'middle', label: '中杯', region: rectPx(390,180,180,420), jev: '中間的杯子' },
{ id: 'right', label: '右杯', region: rectPx(660,180,180,420), jev: '右邊的杯子' },
],
answer: 'middle', explain: '三杯等高;中杯液面距杯口最近。',
jev: { context: '三個相同大小、裝有茶的透明杯子。',
instructions: '看 `card`,選出液面最高的杯子。' },
});
儲存後執行 npm run deck -- zh-mini,再重新載入頁面。建置腳本會產出 public/cards/zh-tea-level.png 並更新完整與公開題庫;這個帶檔名的指令會保留既有其他題卡,因此下一節還要做練習題組篩選。

想改成點位置題,就用 kind: 'point' 與 target: rectPx(...);不要把 API 的 box 當成 CardSpec 的 kind。座標從圖左上角起算,rectPx() 會轉成 0–1 比例。判定函式會以模型框中心是否落入目標來評分,含原版 0.01 比例容差;框蓋住目標的一角,不保證中心也在裡面。
③「十張各有目的」:用小題單擴充
接著把下面十題當作製作清單。全部用自己畫的幾何圖、自己寫的文字,先避開難以說明授權的網路照片。它們是這次作品的設計目標,不是原版內建的繁中題庫。
- 茶杯:點出液面最高的一杯,
food/pick。 - 湯匙:點出柄最長的一支,
objects/pick。 - 燈籠:點出三個之中唯一的紅燈籠,
colors/pick。 - 筷子:畫六根平行線,問有幾雙,
counting/buttons。 - 點心盤:畫四個圓形點心、兩個三角形,問三角形數量,
counting/buttons。 - 飲料牌:自行寫「無糖/半糖/全糖」,問哪個是無糖,
reading/pick。 - 價目牌:列三個明確數字,問哪個價格最低,
math/buttons。 - 路線圖:畫三條路,點出終點的小方格,
logic/point。 - 方格紙:點出第三欄第二列,
geometry/point。 - 營業牌:自行寫「營業中/休息中」,問目前哪家開門,
reading/pick。
請 Claude Code 把題目擴成同一模組的陣列,每張使用獨立 zh- 開頭 ID;沿用現有 category 值,另用檔案群組或 ID 前綴辨識這批作品。若要新增「生活題材」標籤,連同型別、介面與發牌驗證一起修改。圖內中文字要指定可用的繁中字型,並開啟產出的 PNG 檢查缺字。
四、讓題材篩選真的改變發牌,也讓答對先贏
④「篩牌也要讓裁判知道」:先做不排名的練習模式
題材選單像點餐:畫面勾了「飲食」,廚房也要收到同一份單。只在瀏覽器把題卡藏起來,伺服器仍可能發出別的題目。原版的 發牌與驗證會重建已簽署題組,所以篩選狀態也要跟著驗證。
新增「繁中練習」入口,只用 zh-mini 群組;可勾選 food、objects、colors、counting、reading、math、logic、geometry。把已驗證的篩選條件納入伺服器發牌資料與簽署內容,發牌、mark、ask、結果重播都套用同一題組;回應實際題數。空題組阻止開始,題數不足不要偷偷混入其他題。此模式不進原版排行榜,介面清楚標「練習」。
驗收時只勾一個題材,逐張核對 ID 與分類,再試空選、五題、十題與重新整理。共用發牌函式原本會輪流抽不同分類;新篩選要先縮小可用題庫,再交給同一發牌流程。更改題組後,比的是你這批題目的遊玩結果。
⑤「答對是主菜,速度是甜點」:改用兩層比較
2026 年 10 月 20 日的 Show HN 留言曾有玩家回報,全對約 45 秒,快速亂點只對 20% 卻拿到 42 秒;作者回覆會調整。這是那位玩家對當時線上版本的觀察,不是本文的模型能力測試。固定快照的 Sprint 程式則明寫每錯一題加 5 秒。
依這個公式做一個算術示例:十題全對、共 45 秒,得分 45 秒;只對兩題、作答共 2 秒,得到 2+8×5=42 秒。因為秒數越低越好,後者反而排前。多加幾秒罰分能改變這個例子,卻仍是在速度和答錯之間交換;若你的作品承諾「答對優先」,直接把比較順序寫清楚更容易驗收。
function comparePlayers(a, b) {
return b.correct - a.correct || a.totalMs - b.totalMs;
}
// 用 Array.sort(comparePlayers):答對多的先排;同分才比總耗時。
這段是比較器示意,省略伺服器驗證、超時與未完成局處理;整合時須保留 原版 Games 的作答檢查,從伺服器已判定紀錄累計 correct 與 totalMs,拒絕負數、非有限數與重複提交。不要直接相信瀏覽器送來的答對數。
在繁中練習模式用「答對題數遞減、相同再以總作答毫秒遞增」排序。前端結算、伺服器結果、勝負文案、分享摘要都共用比較器;不要只換 Sprint 畫面。保留原模式的儲存格式,練習模式另外版本化。所有人須完成同一題組才比較;API 錯誤顯示未完成,別當成模型答錯。
- 十題全對 45 秒,必須勝過兩題答對 2 秒。
- 同樣八題答對,30 秒應排在 35 秒前;題數與耗時都相同才平手。
- 點兩次同一題、重新送出結果、送負耗時,都不能多拿分;空題組與未完成局不能變成有效勝場。
把這些案例先交給 Claude Code 寫成測試,再讓它實作。驗收的是你訂的遊戲規則,不是讓 AI 自己決定什麼叫好玩。想理解這種「先定成功,再改系統」的思路,可讀AI Evals 入門。
五、桌機與手機各玩一輪:看得到,也要點得到
完成修改後,再跑 npm test、npm run build、npm run deck -- zh-mini。確認變更完成後先退出 Claude Code,由自己在編輯器填入一個遊戲供應商 Key,核對該帳戶費率與餘額,再重啟遊戲伺服器。要重新開啟代理改程式前,先清空設定裡的 Key;別讓代理代填或列印它。桌機先完成一輪十題,刻意答錯一次,確認顯示的正解、解釋與最後答對數一致;接著用瀏覽器裝置模擬檢查窄螢幕。
實體手機要另外驗:同一個可信私人網路內,才把開發伺服器改用 npm run dev -- --host 0.0.0.0,手機開電腦的區網 IP 與對應連接埠。這會讓區網裝置可連入,完成測試後按 Ctrl+C 停止;先維持排行榜關閉,且別建立公開轉發。
- 畫面:直向與橫向各看一次,題幹完整、中文無缺字、選項不被截斷。
- 點選:點杯子中心、邊緣、空白處;圖片縮放後仍對應原來的 0–1 座標,留白不要算進圖面。
- 答案:查看瀏覽器 Network 的公開題庫,確認三個答案欄位被移除;在
/api/mark回應才看到正解。 - 整局:測一局全對、一局快速亂點,以及一次網路失敗;核對結算與伺服器紀錄。改動圖形後重建題卡,再跑同一輪。
固定鏡頭與固定題組能讓前後差異比較容易看見;Claude 遊戲視覺回歸教學介紹如何保留基準畫面。本文保留的是原版建置、測試與新增茶杯卡產物;十題擴充、改版計分與實體手機遊玩,按上述案例完成後再記錄你自己的結果。
準備分享作品時,把授權也當成出貨的一部分。此儲存庫程式採 AGPL-3.0-or-later;對外提供修改版網路遊戲時,要依其條款向互動使用者提供對應原始碼。原版題卡、聲音與預覽圖另採 CC BY 4.0,沿用時保留作者、授權、來源及修改說明;字型與其他素材另看 NOTICE.md。自己的照片也先排除未獲同意的人臉、地址與私人文件。
FAQ:八個新手常問的問題
1. 一定要會寫 TypeScript 才能做嗎?
不必先精通,但要能核對結果。先讓 Claude Code 解釋每個欄位,自己驗一張,再擴成十張;看到畫面不等於答案與判分都正確。
2. Claude Code 和 Jev 是同一筆費用嗎?
分開看。Claude Code 是製作工具,Jev 呼叫由遊戲伺服器設定的供應商帳戶支付;先看各自帳號用量,別把寫程式的方案當成遊戲 API 額度。
3. 只把 prompt 翻成繁中就完成了嗎?
還沒完成這份作品的語言驗收。連同模型收到的題意、作答後解釋與按鈕一起對照,確保人與模型在回答同一件事。
4. point 卡要填 kind: box 嗎?
不用。這份 CardSpec 用 point;box 是模型回答的型別,伺服器取框中心檢查是否落在 target。
5. 重跑單一模組會只剩自己的十題嗎?
不會依這份腳本的預設行為自動變成純十題題庫。單一模組建置會保留其他既有題卡;請透過已驗證的練習題組篩選控制發牌。
6. 罰秒提高,就等於答對優先嗎?
不等同。罰秒仍把正確與時間合成單一數值;兩層比較則明確規定先比較答對題數,只有相同時才看耗時。
7. 公開題庫刪掉答案,就完全防作弊了嗎?
不能把這一步當成完整防護。作答後會收到解答,玩家也可能記住題目;有競賽需求時,還要限制重玩、管理題庫與驗證伺服器紀錄。
8. 贏過這十題,就證明人比模型強嗎?
不成立。它只描述這個題組、版本、提示與規則下的結果;換題材、語言或計分方式,回答的問題也跟著改變。
給新手的三個重點
- 先縮小作品:一張茶杯題卡能說清圖、答案與點選範圍,再擴成十題。
- 先寫贏的定義:答對優先就明確分兩層比較;篩選後另開練習紀錄。
- 先留驗收證據:版本號、產出圖片、測試結果與桌手機完成紀錄,都比一句「AI 已做好」更能幫你接手。
接著閱讀
左右滑動查看更多推薦
下一步:今天先完成一張能解釋的題卡
回到那個把手:好玩的看圖遊戲=自己的題卡+可信答案+一致規則。今天先存好茶杯卡、跑出 PNG,再請一位朋友說明他為什麼選中杯。等圖、題意與解答都對得上,再擴題材、改計分。想把這種小作品逐步變成自己的 AI 工作流程,可以從AlphaLab 課程接著練。






