キャラクターが音声で応援してくれる脳トレーニングアプリを作ってみよう
ロジックコードを記述する
※コードが長くなるため、今回のテーマと肝となる「数値をランダムに表示させる」並びに「音声認識」の部分をメインに解説しています。名前空間の読み込み、メンバー変数の宣言も省略しています。全てのコードを見る場合は、サンプルをダウンロードして見てください。
リスト2 (MainWindow.xaml.vb)
‘ RandomInfoというクラス内に、「乱数」という数値型のプロパティを定義しておきます。
Public Class RandomInfo Public Property 乱数 As Integer End Class
ランダムな数値を表示する処理
新しいRandomのインスタンスRndオブジェクトを作成します。
数値型の変数myRndを宣言し0で初期化します。添え字が31の数値型配列変数myArray(31)を宣言します。
RandomInfoクラス型の新しいリストである、myRandomInfo変数を宣言します。
最初に、繰り返し変数iで1から31までを繰り返し、配列変数myArrayに格納しておきます。
同様に、繰り返し変数iで1から31までを繰り返し、以下の処理を行います。
myRnd = Rnd.Next(i, 31)
ここで、最少がiで最大が31までのランダムな数を生成し、変数myRndに格納します。
このままでは、重複した乱数が表示されるため、myRndで初期化された配列変数myArrayをtemp変数に格納します。myRndを配列に持つmyArrayにmyArray(i)の値を代入します。最後にmyArray(i)にtempの値を代入します。これで重複しない1から31までの数値が表示されます。しかし、数値は30までの表示でいいので、繰り返し変数iが31より小さかった時だけ、RandomInfoクラスの「乱数」プロパティにmyArray(i)の値を指定して、AddメソッドでmyRandomInfoに追加していきます。
最終的には30までの数字しか表示しないので、1から30までの繰り返しでいいのでは、と思われるかもしれませんが、それでは、必ず30の値が常に、最後に表示されてしまいます。1から29まではランダムに並びますが、30は常に最後に表示されます。そこで、31までの乱数を発生させて、その中から30までのランダムな数字を表示させています。
GridViewのItemsSourceプロパティにmyRandomInfoオブジェクトを指定します。これで、1から30までのランダムな数字が表示されます。
Private Sub DataShow() myCount = 0 Rnd = New Random Dim myRnd As Integer = 0 Dim temp As Integer = 0 Dim myArray(31) As Integer Dim myRandomInfo As New List(Of RandomInfo) For i As Integer = 1 To 31 myArray(i) = i Next For i As Integer = 1 To 31 myRnd = Rnd.Next(i, 31) temp = myArray(myRnd) myArray(myRnd) = myArray(i) myArray(i) = temp If i < 31 Then myRandomInfo.Add(New RandomInfo With {.乱数 = myArray(i)}) End If Next GridView1.ItemsSource = myRandomInfo End Sub
ランダムに並んでいる数字を選択した時の処理
メンバー変数noの値を1ずつ増加させます。変数myNoに、GridView1から選択された項目を、RandamInfoクラスにキャストして、その「乱数」プロパティの値を取得して格納しておきます。
取得した乱数の値が1ずつ増加するメンバー変数noと同じなら、非表示になっているdummyTextBox内にその値を表示させます。そうでない場合は、エラー音を発生させて、1ずつ増加させていたメンバー変数noの値を1ずつ減少させます。
メンバー変数myCountの値が、ComboBoxから選択された値を格納しているメンバー変数mySecondと同じか小さく、且つ、「乱数」プロパティの値が「30」で、且つメンバー変数noの値が「30」なら、クリアしたことになるので、EndMessageメソッドを実行します。メンバー変数_secondの値を0で初期化します。_secondメンバー変数にはComboBoxから選択された秒数が格納されているメンバー変数です。
Private Sub GridView1_SelectionChanged(sender As Object, e As SelectionChangedEventArgs) Handles GridView1.SelectionChanged Try no += 1 flagNo = no Dim myNo = DirectCast(GridView1.SelectedItem, RandomInfo).乱数 If myNo = no Then dummyTextBox.Text = flagNo Else MediaElement1.Play() no -= 1 End If If myCount <= mySecond AndAlso DirectCast(GridView1.SelectedItem, RandomInfo).乱数 = "30" AndAlso no = 30 Then EndMessage() _second = 0 End If Catch Exit Sub End Try End Sub
[開始]ボタンがタップされた時の処理
メッセージを表示させるmessageTextBlockを非表示にします。ComboBoxからの秒数の選択を不可とします。
ランダムな数値を表示させるDataShowメソッドを実行します。[開始]ボタンの使用を不可とします。
新しいDispatcherTimerクラスのインスタンスmyTimerオブジェクトを作成します。Intervalに「1秒」を指定します。
AddHandlerステートメントで、指定したタイマーの間隔が経過し、タイマーが有効である場合に発生するTickイベントに、myTimer_Tickイベントハンドラを指定します。Startメソッドでタイマーを開始します。
Private Sub StartButton_Click(sender As Object, e As RoutedEventArgs) Handles StartButton.Click messageTextBlock.Visibility = Windows.UI.Xaml.Visibility.Collapsed ComboBox1.IsEnabled = False DataShow() StartButton.IsEnabled = False myTimer = New DispatcherTimer myTimer.Interval = New TimeSpan(0, 0, 1) AddHandler myTimer.Tick, AddressOf myTimer_Tick myTimer.Start() End Sub
指定したタイマーの間隔が経過し、タイマーが有効である場合に発生するTickイベント処理
指定した秒数内でクリアできた場合はEndMessageメソッドを実行します。指定した秒数内にクリアできなかった場合は、FalseMessageメソッドを実行します。このFalseMessageメソッド処理は省略しています。ダウンロードしたサンプルのソースコードを参照してください。
それ以外の場合は、秒数を1ずつ減算し、メンバー変数myCountを1ずつ増加させます。timeTextBlockに秒数がマイナスされながら表示されます。
Private Sub myTimer_Tick() If myCount <= mySecond AndAlso no.Equals(dummyTextBox.Text) Then EndMessage() _second = 0 timeTextBlock.Text = "残り" & _second & "秒" Exit Sub ElseIf myCount > mySecond AndAlso Not no.Equals(dummyTextBox.Text) Then _second = 0 timeTextBlock.Text = "残り" & _second & "秒" FalseMessage() Exit Sub Else timeTextBlock.Text = "残り" & _second & "秒" _second -= 1 myCount += 1 End If End Sub
クリアできた時の処理
タイマーを停止。ランダムに表示されていた数字をクリアします。
キャラクターに喋らせる言葉を格納するメンバー変数readingTextに値を指定しています。
syokoVoiceタスクを実行。messageTextBlockに「おめでとうございます!」と表示し、非表示から表示状態に切り替えます。
メンバー変数noを0で初期化します。秒数が格納されているメンバー変数_secondを0で初期化します。
timeTextBlockに残り時間を表示し、選択された数値を表示させていたdummyTextBox(非表示)内を空にします。ComboBox1の選択を可能にし、ComboBox1で選択されていた項目を解除します。
非同期処理で行われるため、メソッドの先頭にAsyncを追加します。
Private Async Sub EndMessage() myTimer.Stop() GridView1.ItemsSource = Nothing 'GridView1.IsEnabled = False readingText = "おめでとうございます。時間内にクリアできました。" Await syokoVoice() messageTextBlock.Text = "おめでとうございます!" messageTextBlock.Visibility = Windows.UI.Xaml.Visibility.Visible no = 0 _second = 0 timeTextBlock.Text = "残り" & _second & "秒" dummyTextBox.Text = String.Empty ComboBox1.IsEnabled = True ComboBox1.SelectedIndex = -1 'RemoveHandler myTimer.Tick, AddressOf myTimer_Tick End Sub
結果をキャラクターが音声で喋る処理
この処理は、ここでは省略しているEndMessageやFalseMessageメソッドから呼び出しています。詳しくはダウンロードしたサンプルのソースコードを参照してください。
MediaElement型のmyMedia変数を宣言し、syokoMediaElementで初期化しておきます。
音声機能へのアクセスを提供する、新しいSpeechSynthesizerのインスタンス、synthオブジェクトを作成します。
SynthesizeTextToStreamAsyncメソッドで、指定した文字列から、音声出力を非同期に生成します。
SetSourceメソッドで、指定されたストリームおよびMIME型を使用してSourceプロパティを設定します。Playメソッドで音声を再生します。
音声にどんな言語で、どのような声で喋らすかは、SpeechSynthesizerのVoiceプロパティで参照できます。下記のURLを参照してください。
> SpeechSynthesizer.Voice | voice property
上記ページによると、Japanese JA は性別が「Female」で、名前は「Haruka」という女性が読み上げるようです。
非同期処理で行われるため、メソッドの先頭にAsyncを追加します。
Private Async Function syokoVoice() As Task Dim myMedia As MediaElement = Me.syokoMediaElement Dim synth = New Windows.Media.SpeechSynthesis.SpeechSynthesizer Dim stream = Await synth.SynthesizeTextToStreamAsync(readingText) myMedia.SetSource(stream, stream.ContentType) myMedia.Play() End Function
今回はここまでです。次回の記事をお楽しみに。
キャラクターが音声で応援する脳トレーニングアプリのサンプルプログラム
『Windows 8.1+Visual Studio 2013によるWindows ストア・アプリ開発実例集』 第1回のサンプルプログラムです。
連載バックナンバー
Think ITメルマガ会員登録受付中
全文検索エンジンによるおすすめ記事
- 制限時間内に指定した画像を見つけ出す脳トレーニングアプリを作ろう
- 画面上を流れる数字を暗算して正解を求めるアプリを作ろう(その2)
- Kinectで音声を録音・再生するサンプル
- 時刻とともに、その日の出来事をキャラクターが音声で教えてくれるアプリを作る
- 四文字熟語の意味をキャラクターが声で教えてくれるアプリを作る
- 撮影した写真の管理ができるマイフォトアプリを作る
- タブレットPCの加速度センサーを使って目的の画像を直感的に探せるプログラムを作る
- CountDownControlを使ってカウントダウン後にカメラのシャッターを切る
- ListBoxを使った画像表示と、MediaElementに動画を表示するサンプル
- Webカメラで撮影した写真をセピア調に演出するアプリを作る