遊戲能打了、會輸會贏、有震動有紀錄。但昨天測試的時候我發現一件事:不輸入名字、不按出征,直接按攻擊也能玩。
而畫面上明明寫著「請先輸入名字,然後按下出征!」。
這種問題在測試工作裡很常見,而且比單純的 bug 更麻煩 —— 因為你得先決定哪一邊才是對的。
那行字到底是「必填說明」還是「友善建議」?程式從來沒有表態。
兩條路都說得通:
| 做法 | 理由 |
|---|---|
| 改程式:沒出征就不能攻擊 | 文字說了必填,就該真的必填 |
| 改文字:承認名字是選填 | 不輸入就用預設的「勇者」,降低進入門檻 |
我選了改程式。理由是:遊戲只有一個輸入框,連這個都不填就開打,那個輸入框存在的意義是什麼? 而且既然要做「最少回合紀錄」,名字是玩家在這個遊戲裡唯一的身分。
if (!state.ready) {
addLog("請先輸入勇者名字,並按下「出征!」", "log-warning");
nameInput.focus();
return;
}
沿用 Day 25 學到的原則:擋下來,並且說明原因。而且多做一件事 —— focus() 把游標移到該填的地方。不只告訴玩家哪裡錯,還帶他過去。

Day 21 我找 bug 的時候,得到一個自己覺得最有價值的結論:
一個 bug 要能被「發現」,前提是有人知道「正確的行為應該是什麼」。
當時我說:血量變紅那個 bug,對一般玩家來說最難發現,因為「沒有遊戲說明,玩家不知道遊戲機制,不會覺得有問題」。
現在該還這筆債了。
<details id="howto">
<summary>怎麼玩?</summary>
<ul>...</ul>
</details>
<details> + <summary> 是 HTML 原生的摺疊區塊,點一下就展開,完全不需要 JavaScript。想看的人點開,不想看的人不會被佔版面。學了這麼多天的 JS,今天用一個純 HTML 標籤解決了問題,感覺有點好笑但也蠻好的。

初稿我寫:「血量低於三成時,血條會變紅」。
看完之後的反應是:要就寫全,不然就不寫。
因為血條其實有兩個門檻 —— 六成以下變黃、三成以下變紅。我只寫了紅色。
而漏掉的那個,正好是玩家最先看到的那個。如果只寫紅色,玩家看到血條變黃會困惑:「說明沒提到黃色,是不是壞了?」
不完整的說明,比沒有說明更糟 —— 因為它讓人以為自己掌握了全貌,於是把「說明沒寫到的東西」當成異常。
這件事讓我想通一個更普遍的道理:寫說明會逼你把隱含的規則講出來。那些「我知道,但從來沒寫下來」的規則,在動筆的時候才會浮出來。
而那正是 Day 21 說的:沒寫下來的規則,就是沒有人能驗證的規則。
寫說明的時候也遇到反方向的問題:要寫多細?
「傷害每次都會有些浮動」—— 要不要寫出範圍是多少?
我的判斷是不要。留一點空間讓玩家自己摸索,比把數字攤開來有趣。玩家會自己發現「同樣的攻擊,這次打 7 點、下次打 12 點」,那個發現本身就是遊戲體驗的一部分。
至於鞭屍那個彩蛋,說明裡一個字都沒提。寫出來就不叫彩蛋了。
所以說明的取捨其實有三層:
| 類型 | 處理 |
|---|---|
| 規則(操作方式、勝負條件、血條顏色) | 寫,而且要寫全 |
| 數值細節(傷害範圍) | 不寫,留給玩家摸索 |
| 彩蛋 | 完全不提 |
差別在於:規則是「不知道就會困惑」的東西,數值是「知道了反而無聊」的東西。
原本輸贏只有戰鬥紀錄裡的一行字,很容易滑過去。現在會出現一塊橫幅,勝利綠色、失敗紅色。
resultBox.hidden = false; // 出現
resultBox.hidden = true; // 藏起來
hidden 是 HTML 的標準屬性,比自己寫 style.display = "none" 更語意化 —— 而且螢幕閱讀器看得懂「這塊現在是隱藏的」,不會把它念出來。這算是接續昨天無障礙那個話題的一個小實踐。
我刻意沒做成蓋住畫面的彈窗。 因為那樣就按不到鞭屍了 —— 一個為了「儀式感」加的彈窗,會把已經存在的樂趣擋掉。
我原本的設計是:名字已經確認過了,再戰一次不用重新按出征,直接打就好 —— 少一個步驟,比較順。
但測試的時候發現一個陷阱:
再戰一次 → 輸入框解鎖了 → 玩家改了名字 → 但沒按出征
→ 直接按攻擊 → 第一次攻擊把輸入框鎖起來
→ 新名字永遠不會被讀取,而且再也改不掉
玩家會以為自己改了名字,實際上沒有。 而且畫面上的輸入框顯示的是新名字,血條旁邊顯示的是舊名字 —— 兩個地方對不起來。
所以改成每次再戰都要重新出征。多一個步驟,但換來一個保證:畫面上的名字,永遠等於實際使用的名字。
這個取捨我覺得值得:少一次點擊 vs 一個會讓人困惑又無法挽回的狀態,後者的代價大多了。
今天搞懂的事:
focus() 帶玩家到該處理的地方<details> + <summary> 做摺疊說明,不需要任何 JavaScripthidden 屬性比 style.display = "none" 更語意化遊戲的功能到這裡就完整了。明天開始收尾:排版、手機、還有一些我用 QA 眼睛看出來的小問題。