[Hero Of UnderGround 地下城] — 6F SECONDS CHALLENGE 倒數遊戲

成果 & 程式碼

Demo:點我

Code Source:點我

Introduction & 前言

混了一個禮拜(誤,這次要勇闖6F,記得剛看到這層的時候也是抱著一樣的想法,完蛋了。感覺需要用到大量JS,但時常發現,會弄到的東西,就差不多那一些了(或許是我還太菜?!

6F的大魔王- 60秒算數遊戲

Summary & 摘要

由於JS地下城每個BOSS的弱點都不一樣,每一層都要由弱點去進行攻略,本次BOSS的弱點有二 項。

  • 【特定技術】遊戲規則
    -> 020 秒為 1位數計算 (5–3),2140 秒為 2 位數計算 (30*19),4160 秒為 3 位數計算 (332+312),加減乘除規則請用隨機產生,不可寫死題目,60 秒內可無限次數答題。
    -> 0
    40 秒答對加一分,41~60 秒答對加五分,答錯扣一分,最多僅能扣到零分

  • 【特定技術】不可設計跳轉頁面,都得在同一頁內部切換頁面完成。

額外條件

  1. 你攻略此 BOSS 的攻略過程心得

  2. 如果你是駭客,是否能透過 console 執行 JS ,逆向工程讓自己在遊戲上獲得 999 分以上

  3. 承 2,如何寫出具備資訊安全的 JS 程式?可思考純 JS 解法,或結合後端設計

  4. 延伸擴充功能,例如線上排行榜、雙人遊戲


這邊使用display:none方式

畫面製作

一開始看見BOSS的弱點不可設計跳轉頁面就決定要使用 display:none 來做視覺上的頁面切換了,我把它分為三部分。

  1. Step1 → before-play
  2. Step2 → play
  3. Step3 → end-game

這邊還學到了 marquee 跑馬燈的方法,每次切新的版面就會花大把時間在美觀上呀…(參數設定請參考這邊

1
<marquee 這裡放參數設定>這裡放要跑的文字</marquee>

後更

跑馬燈部分有部分瀏覽器不支持及安全性問題,不建議使用,如果需要建議自己使用 JS 寫一個跑馬燈。這邊特別感謝 曾琬庭 大大的留言,她自己寫了一個跑馬燈,點我查看。

關於開始及setTimeout

1
2
3
4
5
6
7
8
9
10
11
12
$('body').keydown(function(e) {   // body可替換成你要的目標
if (e.keyCode == 32) { // 空白鍵的keyCode為32
$('.step1-box').hide();
$('.before-star-box').show();
beforeStarCount(); // 進入倒數畫面
}
}); // e為event
$('.step1-box').hide();
$('.before-star-box').show();
beforeStarCount(); // 進入倒數畫面
}
}); // e為event

這邊想到了上次在3F的計算機有人使用了鍵盤監聽的功能,便拿一開始的開始鍵做嘗試啦,關於 KeyCode點我查看

因為怕玩家沒有準備還有畫面太單調,我在開始前加入了倒數的畫面,並且使用了 SetTimeout() 以及音樂播放。

倒數畫面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function* beforeStarCount() {
setTimeout(function() {
$(‘.before-star-text’).html(starTime);
$(‘.before-star-box’).addClass(‘animated zoomIn’);
}, 500) // 這邊可以加上自己的CSS或動畫
.
.
.
setTimeout(function() {
$('.before-star-box').hide(); // 隱藏倒數畫面
$('.step2-box').show(); // 顯示遊戲畫面
BgMusic[0].play(); // 播放音樂
StarGame(); // 開始遊戲
print_number() // 產生第一組隨機數字
}, 3500)

關於setTimeout()及setInterval()

很多人認為一個是執行一次,而另一個就是自動重複執行只有這樣的差別,其實更深入的還有其他差別,但是兩種都有結束方式。

setTimeout() → 執行一次

setInterval() → 循環執行

clearTimeout() → 結束

clearInterval() → 結束

setTimeout 所設定的程式碼,會因為目前任務佇列所執行的程式碼而可能發生延誤執行的狀況,setInterval 是一開始就標定了執行時間點,當所註冊的函式(func)超過執行的時間點,結束時則會馬上觸發(func)。

兩種其實都有延遲,但是 **setTimeout **延遲了少許,在實驗中結束與開始的兼具至少是我們所設定的時間,相關文章請點我

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var interval = setInterval(() => {
count_time--; // 開始倒數
if (count_time > 9) {
$('.count-time').html('00 :' + ' ' + count_time);
} else {
$('.count-time').html('00 :' + ' 0' + count_time);
}
if (count_time <= 0) {
$('.count-time').html('00 : 00');
BgMusic[0].pause();
timeout[0].play();
clearInterval(interval); // 清除自動倒數的函式
.
.
.
}, 1000);

遊戲開始後的倒數這邊採用 **setInterval **因為我們要讓他重複執行,進而去抓取時間另外設定其他我們要做的事情。


善用Math.round()及Math.random()

關於兩者的詳細用法可以點我參考

Math.round() → 傳回四捨五入的整數

Math.random() → 傳回介於0~1間的亂數

1
2
3
4
// 產生隨機數字
function number(min, max) {
return Math.round(Math.random() * (max - min) + min);
}

簡單來說就是取你所設定的數字範圍(min~max),最後加上min是為了不讓他小於一,乘上 Math.random() 後在四捨五入,最終取得我們要的區間。

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
28
29
30
31
32
function print_number() {
let question_number_1 = 1; // 給要取得的區間一個變數
let question_number_2 = 1; // 給要取得的區間一個變數
// 判斷秒數並抓取隨機不等於零的亂數
if (count_time >= 40) {
// 取個位數
num1 = 1;
num2 = 9;
num3 = 1;
num4 = 9;
} else if (count_time >= 20) {
// 取雙數
num1 = 1;
num2 = 99;
num3 = 1;
num4 = 99;
} else if (count_time >= 0) {
// 取三位數
num1 = 1;
num2 = 999;
num3 = 1;
um4 = 999;
}
question_number_1 = number(num1, num2)
question_number_2 = number(num3, num4)
.
.
.
// 換上隨機取得的數字及符號
$('.question-number-1').html(question_number_1);
$('.question-number-2').html(question_number_2);
}

這邊可以狠狠地打擊BOSS的第一個弱點,我的想法是4060s應該是最簡單的一位數(4+4),2040s是中階二位數(10x20),最後0~20s是最難的三位數部分(200÷100),跟題目有點相反,但我想這樣比較符合玩家的流程!?

裡面還能加上自己的判斷,例如 question_number_1 < question_number_2 又是減的運算符號的話,就重抓一次,如果question_number_1 % question_number_2 != 0 的話就是不整除,一樣再重抓一次。

1
2
3
4
5
6
7
8
9
10
11
12
13
function gotsign() {
let plus = '+';
let minus = '-';
let multiplied = 'x';
let divide = '÷';
// 隨機抓取四個運算符號
let sign = ['+', '-', 'x', '÷'];
let signnumber = Math.floor(Math.random() 4)
.
.
.
return sign[signnumber];
}

另外運算符號的部分我們一樣用 Math.random() 並且採用陣列方式,不得不說陣列真的很好用啊,初學JS幾個月的我應該要更努力專研,有效大幅精簡我的程式碼。

另外我們可以再給運算符號一個變數,例如 ’+’ = 1,’-’ = 2…等,讓我們去判斷抓取的是哪一個符號,最後能在最一開始的 print_number() function 裡去判斷這個運算符號是不是抓取第二次了。

平均抽取的機率

因為我們重抓一次的關係,除號和減號可能大幅降低被選中的機率,也可以說是被濾掉了,這邊我們可以再給他另一個變數。

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
28
29
30
function print_number() {
.
.
.
if (again == false) { // 判斷是不是因為答案為負數或是除不盡而重來的變數
sign = gotsign()
} else {
sign = again_sign; // 這邊裝重來的運算符號
sign_code = again_code; // 這邊裝重來的運算符號自己取的代號
}
// 判斷是否前一個數字小於後面以至於相減為負數
if (question_number_1 < question_number_2) {
again = true; // 讓式子去判斷因為我們的條件而重來
again_sign = '-'; // 這邊裝重來的運算符號
again_code = 2; // 這邊裝重來的運算符號自己取的代號
print_number()
return;
}
// 判斷是否前一個數字小於後面以至於除不盡及相除不等於零
if (question_number_1 < question_number_2 || question_number_1 % question_number_2 != 0) {
again = true;
again_sign = '÷'; // 這邊裝重來的運算符號
again_code = 4; // 這邊裝重來的運算符號自己取的代號
print_number()
return;
}
.
.
.
}

監聽事件

送出答案的部分和我們設定開始的按鈕一模一樣,關於 KeyCode 請再次點我查看。

關於分數那點事

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
28
29
30
31
32
$('body').keydown(function(e) {
// 這邊加上第二個enter_keydown防止在其他頁面按下Enter
if (e.keyCode == 13 && enter_keydown) {
// 判斷分數的位數
if ($('.answer-input').val() == answer) {
// 判斷時間後答對加分
if (count_time >= 20) {
score++; //答對加一分
} else if (count_time > 0 && count_time < 20) {
// 小於20秒答對加五分
score += 5;
}
.
.
.
// 答錯的部分
} else {
if (count_time >= 0 && score > 0) {
score--;
if (score > 0 && score < 10) {
$('.score-box').html('00' + score);
return;
} else if (score > 9 && score < 100) {
$('.score-box').html('0' + score);
return;
} else {
$('.score-box').html('000');
return;
}
}
}
}

999大神(其實自己偷改的

最後因為結束的頁面 Class 跟我分數欄的 Class命名一樣,所以不需要特別去做設定,這邊深刻體會到命名的重要性。
而按下重玩的案件就把所有的變數回到原樣就好了,一切就會重來,而有考慮到要弄個線上排行榜出來,不過我想那個需要動到資料庫(或許我太菜?!),想想等以後比較熟悉了再回過頭來,我想那時候在看這時候自己寫的文章還有Code都會暈倒吧哈。


關於資訊安全

資訊安全

我們都聽說過 XSS(Cross Site Script,跨站點腳本編制,也稱為跨站腳本攻擊),指的是攻擊者向合法的 Web 頁面中插入惡意腳本代碼(通常是 HTML 代碼和 JavaScript 代碼)然後提交請求給服務器,隨即服務器響應頁面即被植入了攻擊者的惡意腳本代碼,攻擊者可以利用這些惡意腳本代碼進行會話劫持等攻擊…詳全文

關於資訊安全的部分,菜雞如我其實一竅不通,不過我們秉持著不懂就爬文的精神,慢慢去增廣見聞。JavaScript 其實會被攻擊也會被劫持,攻擊者不免都是要取得更多權限或取得個資等等,而我們能做的即是預防勝過治療,例如自動化檢測 JavaScript 安全漏洞,或是 JavaScript 代碼加密,甚至使用 Dojo、JQuery 等等已經壓縮代碼的第三方 JavaScript 代碼庫。
關於更多JS安全請點我前往,對於資訊安全幼幼班的我會再努力吸取新知更新並補上的。


作品出爐啦

Conclusion & 結論

這次算是免強通關吧,在通關前一樣想著大概又要掛在這層了的想法,不過勇者就是要想盡一切方法通關呀!我想這次讓我成長更多的除了更熟悉 JavaScript 之外,文章也慢慢精簡到重要部分,希望能在近期達到精簡扼要的地步,其實這篇文章打第二次了,暈倒,這邊沒有幫我儲存到…看來我對這個網站還是苦手啊。

另外每次不懂每次爬文就是一次成長,看了看其他人在看自己還是有好大一截需要努力,除了繼續努力之外還是要列出檢討的地方,然後朝下一關繼續加油,完畢。

  • JS

  • 邏輯

  • 文筆

  • 體重


我的其他範例

  • Hero Of UnderGround — 1F Multiplicatio 九九乘法表

    Demo:點我

    Code Source:點我

  • Hero Of UnderGround — 2F Clock 時鐘

    Demo:點我

    Code Source:點我

  • Hero Of UnderGround — 3F Calculator 計算機

    Demo:點我

    Code Source:點我

  • Hero Of UnderGround — 4F World Clock 各國時區

    Demo:點我

    Code Source:點我

    Blog:點我

  • Hero Of UnderGround — 5F AQI 全台空氣指標儀表板

    Demo:*點我

    Code Source:*點我

    Blog:點我

參考網站