網頁標題: 《讓網頁會說話》 Javascript 的文字轉換語音應用——網頁數獨

Warning: fopen(/home/crazy/www/cmsb/bcj/has_read.php): failed to open stream: Permission denied in /home/crazy/www/compose/reading.php on line 2070

Warning: fputs() expects parameter 1 to be resource, bool given in /home/crazy/www/compose/reading.php on line 2072

Warning: fclose() expects parameter 1 to be resource, bool given in /home/crazy/www/compose/reading.php on line 2073
 
﹗﹗﹗觀看留言:此文章已經有2則留言 ﹗﹗﹗


 接續上次找到 Javascript 文字轉語音的 API 以後,我做了一個網頁版的數獨,裡面使用該功能讓玩家能直接聽讀同橫排、同直排及同九宮格內的數字。提出來與大家分享,有任何意見也請不吝賜教!

 我自己的測試環境:

  • Windows XP/7
  • Internet Explorer 6/10/11, Mozilla Firefox 45.0.1
  • NVDA 2016.1, 導盲鼠 7.14/8.00

 NVDA 使用者請先用 NVDA+Space 切換成「焦點模式」,方可與頁面上的元件直接互動,導盲鼠或晴光不用特別設定。頁面上有 9*9=81 個按鈕,排成橫排、直排各九個,也可當九個九宮格來排列。可以用方向鍵在按鈕間上下左右移動。畫面上另有「難度」下拉方塊,提供五種難度,越高級則要修改的格子越多。

 每個按鈕上均有一個數字介於 0 到 9, 但是 0 表示該按鈕需被修改,如果將所有需修改處調整後能讓每個橫排、每個直排跟每個九宮格,都恰好是 1 到 9 各出現一次,玩家即獲勝。當勝利時也會顯示所花時間,為了盡量節省時間,請善用按鈕上的工具提示 (HTML 裡的 title) 與報讀功能。工具提示包含座標與可否修改的資訊,若座標之後的字母為 F 表示不能修改,按鈕將以黑字呈現,M 則可以修改,按鈕將以紅字呈現。遇到可修改按鈕就可點選開啟對話,在編輯區內打上自己的數字,按「確定」即修改完成。請玩家注意不可以改成跟同橫排、同直排、同九宮格有一樣的數字,否則修改動作將被阻止。報讀跟其他方面的操作請見下表所列的功能按鍵:

按鍵功能
Ctrl 加方向左鍵報讀同橫排的九個數字
Ctrl 加方向上鍵報讀同直排九個數字
Ctrl 加方向右鍵報讀同九宮格的數字
Ctrl 加方向下鍵報讀這格的數字,並且說出是否可以修改該格數字
Alt 加方向上鍵增加報讀速率
Alt 加方向下鍵減少報讀速率
F2另起新局
句點 (.)停止報讀
Tab 或導盲鼠九宮格加減在數字按鈕與難度下拉方塊間切換

 當遊戲獲勝後,所有紅色可修改處將變成綠色,並且語音報讀都變成「不能修改」,但工具提示維持原先的 F 與 M. 這時候可用 F2, 改變難度或在難度下拉方塊上按 Enter 以及 F5 頁面重新整理等方法另起新局。

 頁面下方有四個 81 格的數獨答案,是本遊戲的「題庫」,發起新局時將從中抽出一個後進行隨機排列、翻轉、旋轉、數字替代等技巧產生題目。下面開始介紹其中的 Javascript 程式碼和所用到的技巧。


 以下假設讀者已經具備 Javascript 的變數、流程控制、使用者定義函數、陣列及字串處理等基礎,也知道如何替網頁上的 HTML 元件設置事件 (onClick, onChange, onKeyDown, etc.) 處理函數 (handler).
 網頁中有一個 <select> 下拉方塊,一個 <table> 表格當成 81 個數字按鈕擺放處,另一個 <table> 放「題庫」。但除題庫外其他元件的內容都變成由 Javascript 產生。下拉方塊的每個選項會提示玩家有幾個空格,用 empty_cells 函數簡單定義空格數量為難度值三倍加五。放數字按鈕的表格,由 Javascript 產生 81 個 <button> 元件,並設置好其 onClick 跟 onKeyDown 事件處理,兩個事件分別當焦點在按鈕上按 Enter 或空白啟動按鈕,以及焦點在按鈕上時按下任何鍵而觸發。

 另外網頁一開始就在 <select> 上也設置 onChange 事件處理,會當改變它被選中的選項或焦點在上面按 Enter 時觸發。以及網頁內容開始處 <body> 也設置 onLoad, 當網頁顯示完成時會觸發。
 當網頁開啟,將執行下列三個步驟:

  1. 抓取或設置好文字轉換語音的資源
  2. 填好 <select> 與 <table> 內容
  3. 隨機產生題目

 這個網頁有引入 Javascript 文字轉語音的 API, 不過它在 IE6 無法運作。因此其他瀏覽器直接引入這個 API, 可是 IE6 必須使用電腦上的 SAPI 物件,操作電腦上原有的文字轉語音功能。注意 SAPI 被視為非安全的物件,因此如果用 IE6 直接從伺服器抓來這個數獨網頁,不會聽到語音,必須自行存檔 .htm 然後開啟並應允執行「被封鎖的語法」和「不安全的 ActiveX 控制項」才有聲音。
 因為這個網頁設計成與 IE6 相容,所以文字轉語音方面的使用方式也必須包裝成一樣。然而 ActiveX 的 SAPI 物件無法用 IE6 執行修改語音速率 (rate) 的操作,必須使用 SAPI 的 XML TTS 實現調整音量和速率等客制化設定。讀者有興趣可以進入剛才的連結閱讀,其實 NVDA 也使用 XML TTS 的方式讓我們聽到語音有音量和音調、速率的變化!

 第二步是把 <select> 和 <table> 裡的 Javascript 做完,才算完成這兩個元件,整個網頁顯示完後執行 onLoad 的內容,將把難度 <select> 的值設為 1, 並用 1 為參數呼叫 initialize 函數。這個函數負責初始化整群數字按鈕,會隨機從題庫抽出題目並且混淆,流程大致如下:

  1. 自所有題庫挑選一個病讀入
  2. 攪亂題目中的數字配置,但過程中仍遵守數獨答案的規定
  3. 依據難度選擇,隨機抽出格子挖空
  4. 把數字填入 81 個按鈕,並設好顏色、工具提示、事件處理函數等

 首先用 <pre> 標籤為識別來抓出所有題目,並從四題中選一個。其實每個題目 <pre> 標籤都有被賦予 name 屬性,但是不明原因 IE6 不會正確根據 name 抓取所有題目。拿到 <pre> 後,將中間文字內容用正則表達式 (regular expression) 挑成九行,每行再用正則表達式挑成九個數字。自此產生一個二維陣列,大小 9*9.

 接著隨機攪亂該題目,才不會出題跟題庫一樣,攪亂程序含有七項:區域列 (row) 混淆、全域列混淆、區域欄 (column) 混淆、全域欄混淆、對角線鏡射、旋轉、數字取代。前四項是列與欄的重新排序,九列(欄)看成三組各三個列(欄),組內的三列(欄)重排稱為區域,三組順序重排稱為全域。「對角線鏡射」意為根據兩對角線中其一,把數字跟對稱位置的數字交換(也可能略過此步)。「旋轉」是將按鈕們順(逆)時鐘 90, 180 或 270 度重新擺置,不過這裡只採逆時鐘轉,因為順 90/180/270 度與逆 270/180/90 度相同。「數字取代」即把 1~9 數字隨機取代,如 1 換成 5, 2 換成 7, 4 換成 9 等,一一對應。
 最後隨機選出挖空處。先把所有格子都變成黑色無法修改狀態再挑選挖空處,為避免選到重複的格子,被選中的格子需立即改變顏色與工具提示,要是這次選到的格子已經被改過,就避開重選,確定是未選過的格子就也要將數字改成 0. 到此,題目產生完畢,開始計時。

 玩家會感受到焦點被拉到 (0, 0) 的按鈕上,可用方向鍵遊走於整個盤面,停在某處想要查探四週可善用 Ctrl 加方向的語音提示(可用句點叫它立刻閉嘴)。可修改的格子剛開始除了呈現紅色外,數字寫 0 且工具提示顯示 M 於座標之後。玩家必須自己找出 0 並從同橫排、同直排、同九宮格等提示推論該格答案。
 想修改按鈕上的數字時,可用空白或 Enter 啟動按鈕,若確實可修改則一個含有打字區的視窗將彈出,玩家只允許輸入一個數字。如果輸入不合規定或者故意輸入同橫排、同直排、同九宮格已有一樣數字者,就會引起錯誤訊息,提示此修改無效。注意,玩家可將內容設為 0 表示取消之前的修改,讓該格回到未知數字的狀態。

 每次修改成功時,系統會檢查所有按鈕的數字分布是否符合數獨答案,是則立即宣布玩家獲勝,並且顯示回答所花時間。一般狀況顯示時、分、秒,如果作答時間超過 24 小時就只顯示幾天(很難發生吧,除非故意開著整天,然後向別人炫耀自己解數獨的速度有多慢……)。

 此時,原本紅色可以啟動的按鈕都變綠,再也無法啟動修改,工具提示厚的 F/M 維持原狀。玩家可以直接用 F2 另起新局,或者用 Tab 跳到「難度」下拉方塊改變空格數目,一旦 Enter 確認難度改變,立刻出現另一局數獨並且開始計時!如果玩到一半想另起新局或改變難度也可以依照上述操作,不一定要等一局結束。

 最後,該網頁的 HTML 與 Javascript 程式碼如下。故鄉可能會把程式碼中的半形空白變成全形,想避免此狀況可以從「友善閱讀」或從本文一開始的連結中取得網頁原始碼。

其他參考資料:

  1. [JavaScript 物件導向介紹 | MDN]: 這裡指導如何建立 Javascript 內的物件,有助於了解 Javascript 一開始 if 判斷式中對 IE6 語音的處置
  2. [How to detach event in IE 6 7 8 9 using JavaScript]: 解決如何在 IE6~9 解除事件 handler, 如果未解除則 Tab 跳到「難度」後再次 Tab 無法回到剛才離開時的座標




本文張貼者:Bo-Cheng Jhan〔張貼時間:民國105年4月19日(星期二)16點21分〕

部落格首頁


學習的故鄉首頁
本站公告:〔您越需要我們,我們就越有創意〕 本站說明書:〔發現故鄉還有改進的地方,請來信告訴原丁們〕
觀察應用學習點數 :〔咱的故鄉有您的參與,會使我們有更大的發揮空間,展現更豐富精彩的學習畫面〕 〔期待藉由無障礙網頁設計,能讓視障小朋友更愛看書、更愛寫作且更愛學習〕:盲用電腦「心得分享」
〔為了讓我們有乾淨的學習環境,請勿任意在本站散播商業廣告與不合法文件或聯結〕:本站宣示