引き続きVoiceflow TIPSです。
ランダムな数字を取得したい、かつ重複しないようにしたいことってありますよね?例えばクイズスキルとかでランダムな問題を重複しないように、というようなケースが考えられます。これをVoiceflowでやってみました。
全体像
全体はこんな感じです。
変数の作成
まず変数を作成します。ランダムな数字をセッション跨いで必要とするケースはそんなにない気がしたので、今回は TIPS #3で紹介したフロー変数を使ってみました。
変数名 | 説明 |
---|---|
arrRndNum | ランダムな数字郡を保持しておくための配列です |
startNum | ランダムな数字の最小値。ユーザが定義する。 |
endNum | ランダムな数字の最大値。ユーザが定義する。 |
rndNum | ランダムな数字が一つ入ります |
例えば、0〜9からランダムな数字が取得したければ、startNumが0、endNumが9というような感じになります。
① Set Blockでユーザが定義する値を初期化
ここでstartNumとendNumを初期化します。別に後ろのCode Blockで初期化してもいいのですが、コードを直接編集せずに、ユーザが定義するところだけはわかりやすいSet Blockを使いました。例では1〜10でランダムな値を取得する感じですね。
② Code Blockで配列などの初期化
ここはコードそのものです。ちょっと見えにくいので以下にコードを貼ります。
var arrRndNum = []; var rndNum = 0; for (var i = startNum; i <= endNum; i++) { arrRndNum.push(i); } for (var j = arrRndNum.length -1; j > 0; j--) { var r = Math.floor(Math.random() * (j + 1)); var tmp = arrRndNum[j]; arrRndNum[j] = arrRndNum[r]; arrRndNum[r] = tmp; }
中身はこんな感じです。
- 最初に、arrRndNumとrndNumを初期化しておきます。
- 最初のforでユーザが定義したstartNumとendNumからarrRndNumに数字を入れていって配列をつくります。
- 2番めのforでarrRndNumをシャッフルして配列内の数字をランダムに組み替えます。Fisher–Yatesアルゴリズムを使ってみました。
必要なときに都度ランダムを引いてもよいのですが、ここでは初期化の一環としてランダムな配列を作っておきました。ここまでが初期化です。
③ Code Blockで配列から数字を取得
ここからがメインのフローになります。arrRndNumから数字を一つ取り除いてrndNumに入れます。②でarrRndNumが既にランダムになっているので、単に一つpopするだけでランダムな数字が得られます。もちろん、ここでランダムにとるようにしてもよいと思います。
コードも貼っときます。
if(arrRndNum.length > 0){ rndNum = arrRndNum.pop(); }else{ throw new Error("配列が空です"); }
なお、pop()で取得した場合、配列が既に空になっていると0を返すので、ここでは最初に配列内の要素数をチェックして1以上でなければ、エラーをthrowするようにしました。こうしておくとCode Blockのfailに流れるのでわかりやすいです。
④ Speak Blockでランダムに取得した数字をAlexaに発話させる
ここでAlexaにランダムに取得した数字を発話させます。ついでにもう一度引く場合の質問も投げかけています。
⑤⑥⑦ Interaction Blockで繰り返しの確認
Interaction Blockで繰り返すかどうかを「はい」「いいえ」でユーザに答えさせます。Choice Block使ってもよいのですが、「はい」「いいえ」はYesIntent/NoIntentがありますので、ビルトインされているInteraction Blockを使ったほうが確実ですね。
ここで「はい」の場合は、1のフローに流れて、③に戻って再度ランダムな数字を引き直します。
「いいえ」の場合は、2のフローに流れて、終了のメッセージを発話して終わります。
「はい」「いいえ」以外の場合は、Elseに流れて、再度質問し直します。
⑧ 配列が空になった場合
③で書いたように、ランダムな数値を保持している配列arrRndNumが空っぽになった場合はエラーになりFailに流れるので、ここでもう配列が空だということを告げて終わります。ケースによってはここで再度②に流して、配列を初期化してもよいかもしれませんね。
これで一通り完了です。
テスト
2回実行した結果を以下に貼っときます。
- 毎回、順番が違うこと
- 同じ数字が1回のセッションで選ばれていないこと
を見ていただければわかるかと思います。
今回、以下の記事を参考に、少しコードの書き方などは修正させていただきました。Thanks! > Mark!
Markさんの他の記事にもいろいろVoiceflowのTIPSなどありますのでぜひ御覧ください(英語)
是非ご活用下さい〜