專案名稱: Dice Tarot(骰塔羅)
專案簡介:
Dice Tarot 是一個結合傳統塔羅牌與 TRPG 多面骰機制的互動式 Web App。
一般線上塔羅網站通常讓使用者直接點選牌面,再揭曉抽牌結果。
Dice Tarot 則採用不同的方式:先將完整的78張塔羅牌隨機洗牌,再由使用者擲出 D100 百分骰,利用骰子點數決定抽取牌堆中的哪一張牌。
系統保留塔羅牌原有的正逆位機制,骰子只負責決定抽牌位置。
專案主要目標是透過擲骰、抽牌及翻牌動畫,增加線上塔羅的互動性與趣味性,同時確保隨機抽樣程序具有明確、可檢查的邏輯。
開發狀態: V1.0 已完成,GitHub 開源並部署至 Vercel,開放公開體驗。
GitHub: https://github.com/richchang0721-boop/dice-tarot
線上 Demo: https://dice-tarot.vercel.app/
這個專案的起點,其實來自某天偶然滑到的一支塔羅占卜影片。
影片中的博主正在分析2027年不同生肖的運勢。
因為解讀內容與我原本的一些生活規劃產生了不少巧合,便引起了我的興趣。
後來,我又找了線上塔羅網站,自己試著抽牌。
一般網站大多透過滑鼠點選牌面,再由系統揭曉結果。
雖然操作簡單,但我突然想到:
如果把 TRPG 的多面骰也加入抽牌流程,會不會更有趣?
在桌上角色扮演遊戲中,骰子經常用來決定行動結果。
玩家決定採取什麼行動,骰子則決定行動的隨機結果。
如果套用到塔羅,便可以形成另一種互動方式:
使用者提出問題,系統完成洗牌,最後由骰子決定抽牌位置。
例如,一副78張的塔羅牌已完成洗牌。
使用者擲出37點。
系統便從牌堆中抽出第37張牌。
如果使用三張牌陣,就連續進行三次擲骰與抽牌。
這就是 Dice Tarot 的基本概念。
本專案不是為了證明塔羅具有預測能力,而是希望將傳統塔羅與桌遊機制結合,設計出一個具有儀式感的互動式網頁。
第一階段預計採用純前端架構,不建立後端伺服器。
主要技術規劃如下:
| 技術 | 預定用途 |
|---|---|
| React | 使用者介面與元件管理 |
| TypeScript | 抽牌規則、狀態及型別管理 |
| Vite | 專案建置工具 |
| Tailwind CSS | 響應式UI設計 |
| Web Crypto API | 產生擲骰及洗牌亂數 |
| Fisher–Yates Shuffle | 78張塔羅牌的隨機排列 |
| Three.js | 3D多面骰動畫 |
| IndexedDB | 本機占卜紀錄儲存 |
| GitHub | 原始碼與版本管理 |
| Vercel | 網站部署 |
整體架構預計分成四個主要模組。
塔羅牌管理模組
負責載入78張塔羅牌、洗牌、正逆位設定、牌堆狀態及已抽牌管理。
骰子模組
負責D100點數產生、有效範圍檢查、重新擲骰及動畫顯示。
牌陣管理模組
負責單張牌、三張牌陣及抽牌順序。
紀錄模組
負責保存抽牌日期、問題、骰子結果、牌面及正逆位。
各模組獨立設計,避免將抽牌邏輯與動畫程式綁定在一起。
標準塔羅牌共有78張,但常見桌遊骰子沒有D78。
因此,本專案選用D100百分骰。
D100可以透過兩顆十面骰組成,產生1至100的結果。
然而,若直接使用D100點數對78取餘數,會產生抽樣偏差。
因為100無法被78整除,某些抽牌位置會比其他位置更容易出現。
因此,預計採用拒絕採樣(Rejection Sampling)。
第一次抽牌只接受1至78。
如果擲出79至100,就重新擲骰。
第二次抽牌時,牌堆剩下77張,因此有效範圍變成1至77。
第三次則為1至76。
只要D100本身產生均勻分布的數字,這種方式就能讓每張剩餘牌具有相同的抽取機率。
傳統塔羅具有正位與逆位。
最初曾考慮讓額外骰子決定正逆位,但這會增加操作步驟。
因此,決定將正逆位交由洗牌階段處理。
系統完成洗牌後,每張牌的順序與方向便固定下來。
後續擲骰只決定抽牌位置。
不會重新決定正逆位,也不會因問題內容調整牌面。
三張牌陣需要連續抽取三張不同的塔羅牌。
因此,抽中的牌必須立即從剩餘牌堆移除。
例如:
第一次擲出37,抽出第37張。
原本78張牌減少為77張。
第二次擲出12,便從剩餘77張牌中抽出第12張。
此時剩下76張。
第三次則從76張牌中繼續抽取。
整個過程不重新洗牌,確保牌序維持一致。
網頁動畫容易產生一個問題:
畫面上骰子滾動的結果,是否真的與程式內部的抽牌數字一致?
本專案預計讓亂數邏輯與動畫分離。
使用 Web Crypto API 產生數字,再由動畫負責呈現。
骰子動畫不能自行修改抽牌結果。
這樣能避免動畫狀態與實際抽牌資料不一致。
需要特別說明的是,這是程式亂數驅動的骰子動畫,而非以3D物理碰撞直接計算骰點。
第一版將採取以下方式:
隨機機制
採用 Web Crypto API 作為亂數來源。
使用 Fisher–Yates Shuffle 進行洗牌。
抽牌點數採用拒絕採樣,避免模數偏差。
狀態管理
使用 TypeScript 定義每張牌的資料結構。
每張牌包含唯一ID、牌名、正逆位與牌面圖片。
抽牌時從牌堆移除對應項目,並更新剩餘牌數。
互動設計
保留簡單的操作流程:
選擇牌陣 → 默念問題 → 洗牌 → 長按牌堆 → 擲骰 → 抽牌 → 查看結果。
三張牌陣重複三次擲骰與抽牌操作。
動畫設計
利用 Three.js 製作D100骰子視覺效果。
利用CSS動畫完成塔羅牌展開、抽取與翻牌。
提供跳過動畫選項,避免重複操作時造成等待。
資料保存
使用 IndexedDB 儲存占卜紀錄。
第一版不要求會員登入。
紀錄保存在使用者自己的瀏覽器中。
目前已完成:
待MVP完成後,將補充實際使用的技術架構、測試結果、開發過程中遇到的問題及修正方式。
這個專案的起點,其實只是一個突發奇想。
原本只是偶然看了一支塔羅占卜影片,後來自己也嘗試線上抽牌。
最後突然想到:
「既然都是占卜,加上骰子不是更有趣?」
於是就有了 Dice Tarot。
我希望它不是另一個只有「點選、翻牌、顯示結果」的塔羅網站,而是一個讓使用者真正參與抽牌過程的小型互動作品。
第一版不追求複雜功能,也不打算加入會員系統或商業化機制。
先把骰子、塔羅與抽牌流程做好。
至於後續能發展到什麼程度,再慢慢研究。
畢竟有時候,一個程式專案的誕生,不一定需要宏大的理由。
只是覺得這樣玩好像很有趣,那就試著做出來吧。XD