[實作] 猜數字互動遊戲

學習到的知識點

JS

  • Web Speech API

簡介

Demo

猜數字遊戲

HTML

結構

1
2
3
4
5
6
7
8
<img src="img/mic.png" alt="Speak" />

<h1>Guess a Number Between 1 - 100</h1>

<h3>Speak the number into your microphone</h3>

<div id="msg" class="msg"></div>
<script src="jquery.js"></script>

CSS

背景處理

  • no-repeat left center/cover 方法
1
2
3
4
5
6
7
8
9
10
11
12
body {
background: #2f3542 url("img/bg.jpg") no-repeat left center/cover;
color: #fff;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
text-align: center;
margin: 0;
font-family: Arial, Helvetica, sans-serif;
}

JS

產生隨機數 getRandomNumber()

原生JS

  • Math.floor()函式會無條件捨去到比自身小的最大整數。ex 4.6213 回傳 4
  • Math.random()函式,會隨機產生出0~1之間的小數,出來的值永遠不會大於1。
1
2
3
4
5
6
7
8
9
const msgEl = document.getElementById("msg");
const randomNum = getRandomNumber();
console.log("Number:", randomNum);

// Generate random number
function getRandomNumber() {
// 產生的數會是1-99,所以+1,變成100。
return Math.floor(Math.random() * 100) + 1;
}

Jquery

無轉換

1
2
3
4
5
6
7
const randomNum = getRandomNumber();
console.log("Number:", randomNum);

function getRandomNumber() {
return Math.floor(Math.random() * 100) + 1;
}

Web Speech API onSpeak()

取得API,然後印出e,可以觀察到許多資訊,裡面的result裡的transcript會有我們說的內容,再對transcript進行轉換,就可以得到說的內容。

Web Speech API有兩個部分

  • speechSynthesis 語音合成(文字轉語音)
  • speechRecognition 語音識別(非同步語音識別)
  1. 先查看瀏覽器是否有支援不需要prefix(前綴)的 speechRecognition 介面,若沒有則將 webkit 標頭的 webkit.SpeechRecognition 指定給該全域變數。

可以前往 Can I use 查看

1
2
window.SpeechRecognition =
window.SpeechRecognition || window.webkitSpeechRecognition;
  1. 使用前要先建構一個物件實體放到recognition變數,使用SpeechRecognition()建構式建立
1
let recognition = new window.SpeechRecognition();
  1. 並監聽result事件。
1
recognition.addEventListener("result", onSpeak);
  1. 設定完後要使用 start() 才會開始辨識
1
recognition.start();

原生JS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
window.SpeechRecognition =
window.SpeechRecognition || window.webkitSpeechRecognition;

let recognition = new window.SpeechRecognition();

// Start recognition and game
recognition.start();

// Capture user speak
function onSpeak(e) {
console.log(e);
const msg = e.results[0][0].transcript;
console.log(msg);
}

// Speak result
// 藉由onSpeak函式取得speak result
recognition.addEventListener("result", onSpeak);

Jquery

無轉換

1
2
3
4
5
6
7
8
9
10
11
12
13
14
window.SpeechRecognition =
window.SpeechRecognition || window.webkitSpeechRecognition;

let recognition = new window.SpeechRecognition();

recognition.start();

function onSpeak(e) {
console.log(e);
const msg = e.results[0][0].transcript;
console.log(msg);
}

recognition.addEventListener("result", onSpeak);

將得到的數字,印在印在頁面上writeMessage()

原生JS

1
2
3
4
5
6
7
// Write what user speaks
function writeMessage(msg) {
msgEl.innerHTML = `
<div>You said: </div>
<span class="box">${msg}</span>
`;
}

Jquery

.innerHTML =轉成.html()

1
2
3
4
5
6
function writeMessage(msg) {
$("#msg").html(`
<div>You said: </div>
<span class="box">${msg}</span>
`);
}

判斷說出的值 checkNumber()

原生JS

  • .start()只會開啟一次辨識,設定functoin,結束時就啟動start。
  • +是將string轉成數字,等同於parseInt
  • isNaN函式會判斷某個數值是不是 NaN
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
33
34
35
36
37
38
39
40
41
42
43
44
function onSpeak(e) {
const msg = e.results[0][0].transcript;
writeMessage(msg);
// 加上這行
checkNumber(msg);
}

// Check msg against number
// 判斷輸入的內容
function checkNumber(msg) {
const num = +msg;

// Check if valid number
// 判斷是否為數字
if (Number.isNaN(num)) {
msgEl.innerHTML += "<div>That is not a valid number</div>";
return;
}

// Check in range
// 判斷數字有無超過範圍
if (num > 100 || num < 1) {
msgEl.innerHTML += "<div>Number must be between 1 and 100</div>";
return;
}

// Check number
// 如果是數字,就判斷是否與隨機數相等,不等於就判斷大於還是小於。
if (num === randomNum) {
document.body.innerHTML = `
<h2>Congrats! You have guessed the number! <br><br>
It was ${num}</h2>
<button class="play-again" id="play-again">Play Again</button>
`;
} else if (num > randomNum) {
msgEl.innerHTML += "<div>GO LOWER</div>";
} else {
msgEl.innerHTML += "<div>GO HIGHER</div>";
}
}

// End SR service
//可以持續判斷聲音,不加這行就只能判斷一次就需要reload
recognition.addEventListener("end", () => recognition.start());

Jquery

  • .innerHTML +=轉成.append()
  • .innerHTML = 轉成 .html()

append()html()乍看之下有點像,但他們其實不一樣。
append()是追加的概念,而html()是完全替換。

比如說

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<p id=”1″>
<p>123</p>
</p>

<!-- html 追加-->
$("#1").html("<span>456</span>");

<p id="1">
<span>456</span>
</p>

<!-- append 替換-->
$("#1").append("<span></span>");

<p id="1">
<p>123</p>
<span>456</span>
</p>

這部分的Code

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 checkNumber(msg) {
const num = +msg;

// Check if valid number
if (Number.isNaN(num)) {
$("#msg").append("<div>That is not a valid number</div>");
return;
}

// Check in range
if (num > 100 || num < 1) {
$("#msg").append("<div>Number must be between 1 and 100</div>");
return;
}

// Check number
if (num === randomNum) {
$("body").html(`
<h2>Congrats! You have guessed the number! <br><br>
It was ${num}</h2>
<button class="play-again" id="play-again">Play Again</button>
`);
} else if (num > randomNum) {
$("#msg").append("<div>GO LOWER</div>");
} else {
$("#msg").append("<div>GO HIGHER</div>");
}
}
recognition.addEventListener("end", () => recognition.start());

設定重新開始Button

當數字相等時,會出現reload按鈕。當按鈕(.play-again)被觸發時,整個window就reload

原生JS

1
2
3
4
5
document.body.addEventListener("click", (e) => {
if (e.target.id == "play-again") {
window.location.reload();
}
});

Jquery

.addEventListener("click")轉成.click()

1
2
3
4
5
$("body").click(function (e) {
if (e.target.id == "play-again") {
window.location.reload();
}
});

參考文章

Day 21 - Speech Detection

jquery append()方法與html()方法的區別及使用介紹


[實作] 猜數字互動遊戲
https://phoebeho.com/Portfolio/20210129/3203651574/
作者
Phoebe
發布於
2021年1月29日
許可協議