ボタンをクリックしてしりとりをスタート! ー 第2章❷ HTMLボタンと「しりとり関数」をつなげる ー 『JavaScriptでやる1分間プログラミング』
第1回ではコンピューターに向かって言葉をしゃべり(音声認識)、さらにしゃべったことをそのままコンピューターにオウム返しさせる(音声合成)プログラミングを解説しました。
当然ですが、オウム返しではしりとりになりません。「リンゴ」と言ったら、それを聞き取ったコンピューターは考えて、「ご」から始まる言葉を言わないといけません。そこでどうやったら「ご」で始まることば、例えば「ゴリラ」をピックアップできるのでしょうか。
SiriもGoogle Assistantもしりとりはしない
ちょっと意外ですが、iPhoneなどに搭載されている音声エージェントのSiriはしりとりをしません。Google Assistantも一見しりとりをやりそうですが、「しりとりをしよう」と言っても自分だけでしりとりをやるか、いきなり「ん」で終わる言葉を言ってしりとりが終わってしまいます。
これはなぜだか分かりますか?
理由はいくつかあると思いますが、もっとも単純な理由は、コンピューターとしりとりをやったら勝ち目がないということでしょう。コンピュータには辞書にある言葉全部を覚えさせることも可能ですし、ネットをつなげればもっと膨大な言葉のデータを取得できます。負けない相手としりとりをやって面白いかどうかは考えものです。
そこでコンピューターとしりとりをやる場合、ちょっとルールを変更しないといけません。
新しいしりとりのルールを考えよう
コンピューターが言葉をほぼ無限に使えることが問題なので、まずはそれを「有限」にします。つまり、コンピュータが”知っている”(選択できる)言葉をある程度限定します。例えば特定の分野の言葉しか言わないようにしてはどうでしょう。
✅ 果物の名前
✅ 花の名前
✅ 動物の名前
✅ 都市や国の名前
ある程度数がそろえばOKです。ちなみに皆さんのほうはどんなジャンルの言葉を言っても構いません。言葉を限定するのはあくまでコンピューターだけです。
ところが、言葉を限定すると逆にコンピューターがすぐに話す言葉がなくなってしまうこともあります。そこで、「コンピューターが負けたらあなたが負け」というルールにします。つまり、コンピューターがもう言葉を言えないようにするのがゲームの目的ではなく、逆にコンピューターに言葉を言い続けてもらうことを目的とします。ですので、できるだけみなさんはコンピューターと長くしりとりをするように言葉を選んでください。具体的には次の二点をよく考えて言葉を選んでいきます。
✅ コンピューターが「ん」で終わる言葉を選択しないようにする
✅ コンピューターが言える言葉がもうないという状態を極力避ける
例えばコンピューターは「花の名前」だけを言うようにデザインしたとします。この時、「す」で終わる言葉、例えば「リス」と言ってしまうと「スズラン」が選ばれてコンピュータが負ける可能性が高いです。ここは「り」で始まって、少なくとも「す」で終わる言葉は避けないといけません。もちろん「ん」で終わる花はほかにもたくさんあります。「かりん」、「ぼたん」などなど。もちろん「ん」で終わらない花もたくさんあります。そこはどれだけ花の名前を知っていて、どの文字が最も「ん」で終わる確率が小さいかを考えないといけません。
こうしたルールでしりとりをやるとかなり頭を使います。たかがしりとりとは言え、できるだけ長く続けるとなると大人でも結構難しくなります。
ということでこの「新しりとりルール」に基づいてしりとりのアルゴリズムを考えてみます。
まずはボタンをクリックしてスタート
ではどんな感じでコンピューターとしりとりをするか、その「アプリのデザイン」を考えるところから始めます。ここではブラウザの中でしりとりをやります。ということでそのしりとりゲームのサイトのデザインはこんな感じになります。
❶ サイトを開くと「しりとりゲーム」のページが開かれる
❷ 「Shiriに言葉を言う」というボタンをクリックする。「ピー」という音が鳴ったら選んだ言葉を話す。
❸ マイクで拾った音声を認識し、その言葉を画面に表示する。
❹ 言葉の最後の文字をもとにして、続く言葉を「言葉リスト」の中から選択する。
❺ 選択した言葉を音声でしゃべる。
ページにボタンを追加する
ということで、ページにまずは「Shiriに言葉を話す」と表示されたボタンを追加します。ボタンをページに表示させるコードはこうなります。
<button type="button">Shiriに言葉を言う</button>
このbuttonのタグが付いた一行をタイトルの行(<h1>タグが入った場所)のすぐ下に追加してください。index.html全体はこうなります。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Shiriとりゲーム</title>
<script src="shiritori.js"></script>
</head>
<body>
<h1>Shiriとりゲーム</h1>
<button type="button">Shiriに言葉を言う</button>
<script>
MagicRecognize((text)=>{MagicSpeak(text);});
</script>
</body>
</html>
これでファイルを保存し、ブラウザを更新すると次のようなページになります。
さあ、こんな感じでボタンができたので、しりとりで言葉を言う場合はこのボタンを一回クリックして何かを言います。ただし、今はボタンをクリックしても何も起こりません。それはこのbuttonタグを見れば一目瞭然。buttonとしか書かれていませんよね。
<button type="button">Shiriに言葉を言う</button>
これではボタンをクリックしても何も起きないはずです。ここに何かコードを書かないといけないのは容易に想像がつきます。そこでこのボタンに「機能」を加えるわけです。そうです、第1章でやったfunction(関数)です!
<button type="button" onclick="SayToShiri();">Shiriに言葉を言う</button>
このonclickというのは「オンデマンド(要求された時に)」の「オン」と同じ意味で、「クリックの時に」ということ。つまりここにクリックされた時に呼び出す関数を指定します。ここで指定したのがSayToShiriという関数。とりあえず今はこの関数の中に、前回書いたオウム返しのコードを書いてみましょう。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Shiriとりゲーム</title>
<script src="shiritori.js"></script>
</head>
<body>
<h1>Shiriとりゲーム</h1>
<button type="button" onclick="SayToShiri();">Shiriに言葉を言う</button>
<script>
function SayToShiri() {
MagicRecognize((text)=>{MagicSpeak(text);});
}
</script>
</body>
</html>
ポイントはここです。
function SayToShiri() {
MagicRecognize((text)=>{MagicSpeak(text);});
}
ボタンがクリックされたらこのSayToShiri関数が呼び出され、それが実行されます。その中ではMagicRecognize関数が呼ばれ、これによってマイクから音声を聞く状態になります。あなたが何か言うと、その結果のテキストを今度はMagicSpeak関数に渡し、そのテキストが音声で読まれるということになります。これは前回と同様、オウム返しのロジックです。
どうですか、ボタンを押すと同じことをオウム返しするようになりましたか?
ここまででしりとりのやりとりの部分の基礎ができました。そこで今度は音声認識して言葉が理解されたら、それをオウム返しするのではなく、しりとりの言葉として返すようにすれば実はしりとりゲームはほぼ完成です。
さあここからが本格的なプログラミングです!
音声認識のコールバック関数を作る
まず、今オウム返しになっている原因は当然ですがMagicRecognize関数に渡すコールバック関数(音声認識が完了したら自動で呼び出される”書き置き”関数)がMagicSpeakになっているからです。
MagicRecognize((text)=>{MagicSpeak(text);});
ここのMagicRecognizeに渡す”書き置き関数”をMagicSpeakではなく、しりとりをやる別の関数、Shirotori() に変更してみましょう。
MagicRecognize(Shiritori);
こうするとMagicRecognizeがあなたの言葉を聞き取ったら、聞き取ったテキストをこのShiritori関数に渡すことになります。
あとはこのShiritori関数の中で、様々なしりとりロジックを書いて、最終的にあなたが言った言葉をもとにしりとりで返す言葉がパソコンがしゃべることでこの関数は完了します。
次のコードをご覧ください。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Shiriとりゲーム</title>
<script src="shiritori.js"></script>
</head>
<body>
<h1>Shiriとりゲーム</h1>
<button type="button" onclick="SayToShiri();">Shiriに言葉を言う</button>
<script>
//ボタンがクリックされた呼び出される関数
function SayToShiri() {
MagicRecognize(Shiritori);
}
//音声認識が終わったら呼び出される関数
function Shiritori(text) {
//・・ここにしりとりロジックを書く
alert(text);
}
</script>
</body>
</html>
新たにShiritori関数を追加しました。
//音声認識が終わったら呼び出される関数
function Shiritori(text) {
//・・ここにしりとりロジックを書く
alert(text);
}
MagicRecognizeで音声認識されるとこの関数が呼び出され、認識テキストはtextという変数に入っています。ここにしりとりの複雑なロジックを書いていくのですが、とりあえず今はalert機能を使って認識された言葉をポップアップ表示させてみます。
コードを変更したら保存し、ブラウザを更新してみてください。今度は音声でオウム返しではなく、警告メッセージでオウム返しをしてきます。
ポップアップを閉じて何回かためしてみてください。
さて、ロジック面ではあまり進歩はないのですが、ボタンクリックでしりとりがスタートするところまでは完成です!
次回はこの関数の中でShiriが選択できる言葉のリストを配列を使って作ってみます。
配列については第1章で学習したのを覚えていますか?
次回のプログラミングで配列について詳しく触れますので、別途メモを作成しました。
次回までにしっかりと配列の概念について理解しておいてください。
では次回、乞うご期待!
この記事が気に入ったらサポートをしてみませんか?