0%

JS地下城6F-60秒算數

作品

60秒算數

主要功能

  • 亂數出題
  • 答案檢查
  • 分數累計
  • 秒數區間判斷
    • 對應不同位數
    • 累計不同分數
  • 線上排行榜
  • 畫面切換

亂數出題

規則

  1. 00~20秒,一位數,e.g. 1+15-3
  2. 21~40秒,二位數,e.g. 11+1155-33
  3. 41~60秒,三位數,e.g. 111+111555-333
  4. 隨機產生數字以及加減乘除
  5. 不論正確與否,皆新增題目

已達成目標

  • 隨機亂數 Math.random()
  • 隨機產生不同位數
  • 隨機產生 +-*/
  • 0/0,答案為 NaN,重置題目
  • 1/0,答案為 無限,重置題目

一開始單純只產生 0~9,幾位數就放幾次函式,後來爬文學到利用亂數乘以最大減最小再加上最小值就能產生一~三位數。

1
2
3
4
5
6
7
8
9
10
11
12
13
/* 產生單一隨機亂數 */
// const randomNumber = () =>{
// return Math.floor(Math.random() * 10 )
// }

// 改寫產生方式
const randomNumber = Math.floor(Math.random() * ( max - min) + min )

/* 產生一到三位數 */
// let thirdType = `${randomNumber}${randomNumber}${randomNumber}`
let firstType = randomNumber(10, 0)
let secondaryType = randomNumber(100, 0)
let thirdType = randomNumber(1000, 0)

答案檢查

已達成目標

  • 取得輸入欄之值
  • 比對暫存題目之結果
  • 除法由於會有小數點,預設計算為整數並四捨五入

在不同的時間區間內產生不同位數題目,當玩家在輸入欄按下 “Enter” 輸入答案後,此時判斷輸入值是否為正確答案,以及是否為空值,因為空值在比對時會可能會自動轉型為 0,要是題目答案剛好為 0,會造成不正常增加分數。

而除法會有小數點的問題,嘗試重置題目,若一時找不到沒有小數點的題目就會造成畫面延遲,待想到更好的解法再來更新。


分數累計

規則

  1. 00~40秒,每答對一題 +1 分,錯誤 -1 分,最多扣到 0 分
  2. 41~60秒,每答對一題 +5 分,錯誤 -1 分,最多扣到 0 分

已達成目標

  • 設定變數來暫存分數
  • 檢查答案正確與否後,累計該變數值並重新渲染目前已累計分數內容
  • 結果顯示時抓取該變數值

時間依據

已達成目標

  • 每秒鐘顯示一次秒數
  • 第 60 秒時,顯示 1:00
  • 取得現在時間毫秒數 Date.now() ,作為 timestamp
  • 取得 60 秒後 Date.now() + 60*1000
  • 建立陣列儲存 [當下時間,60秒後時間],作為後續檢查用

利用 Date.now() 作為 timestamp,檢查遊戲是否開始,若利用 console 去執行開始函式,會檢查 Date.now() 是否在遊戲開始後的時間區間內。若在區間內 :

  • 執行內部變數值初始化
  • 時間開始計時
  • 出題

畫面切換

規則

  1. 點擊遊戲主畫面按鈕後,顯示題目畫面
  2. 遊戲時間結束後,顯示結果畫面
  3. 結果畫面顯示最後分數與再玩一次按鈕
  4. 延伸功能,結果畫面顯示排行榜按鈕

已達成目標

  • 遊戲開始時 :
    • 渲染時間
    • 渲染分數
    • 渲染題目
    • 答案輸入欄位,換題時清空
  • 遊戲結束後 :
    • 顯示結果頁
    • 再玩一次按鈕,按下後回到題目畫面
    • 排行榜按鈕,按下後顯示排行榜
  • 按下再玩一次按鈕時 :
    • 初始化所有暫存變數值(像是分數、暫存時間戳等)
  • 顯示排行榜時 :
    • 讀取試算表資料
    • 若在時間區間外且未上傳,可輸入姓名上傳至試算表。
    • 若要上傳姓名與分數,上傳欄位填完姓名並按下送出後自動消失,剩餘再玩一次按鈕。

安全問題

在初次寫完函式功能後,測試是否能利用開發者模式去執行函式,發現有需要傳入參數值的函式,直接取用該函式並傳入值,就會影響現有畫面內容,像是這樣 :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
const game = function(){
// 時間秒數,當遊戲開始時秒數開始增加
let time = 0
let vm = this
this.start = () => {
time = 0
for (let x = 1; x <= 59 ; x++) {
setTimeout(()=>{
time++
}, 1000*z)
}
this.render(time)
}
// 判斷目前秒數並渲染題目至畫面
this.render = (number) => {
if ( number <= 20) {
// 產生一位數,並改變題目
} else if ( number >= 21 && number <= 40) {
// 產生二位數,並改變題目
} else if ( number <= 59) {
// 產生三位數,並改變題目
}
}
}
const newGame = new game()
// 在開發者模式中直接執行該函式,就會不斷的產生一位數題目
newGamer.render(1)

因此 :

  • 修正會影響暫存值之函式改為無參數傳入,皆利用閉包特性讀取變數值。
  • 利用變數宣告為 false,若不輸入答案並檢查,就無法讓題目重置。
  • 利用變數宣告為 false,當玩家已上傳紀錄後,必須是暫存時間外或是重新開始改變狀態後才能再次上傳。

延伸擴充功能

排行榜

已達成目標

  • 建立 Google 試算表之資料欄位
  • 利用 fetch get 建立讀取函式
    • 判斷是否在暫存時間外才能執行
  • 利用 fetch post 建立送出函式
    • 判斷是否在暫存時間外且布林狀態為 false 才能執行
    • 測試資料送出
    • 線上資料表建立 token,隨著讀取函式抓回來
    • 將 token 雜湊後傳送

參考來源

  1. Henry - JS30 Day 29 - Countdown Timer
  2. Mandy - JS地下城:6F-60秒算數遊戲
  3. 行銷人 ; 梅問題教學網 - 【Google Sheets】進階技巧:利用Google Script將Google試算表變成簡易資料庫
  4. Amit Agarwal - How to Handle GET and POST HTTP Requests in Google Apps Script
  5. Google Apps Script - Class Utilities