画面上を流れる数字を暗算して正解を求めるアプリを作ろう(その2)
次に、ソリューション・エクスプローラー内のInputAnswerPage.xamlを展開して表示される、InputAnswerPage.xaml.vbをダブルクリックしてリスト5のコードを記述します。
ロジックコードを記述する
リスト5 (InputAnswerPage.xaml.vb)
Imports Windows.Storage
‘ シーケンシャルアクセスストリームおよびランダムアクセスストロームに対する読み取りと書き込みをサポートするクラスの含まれる、 ‘ Windows.Storage.Streams名前空間をインポートします。 Imports Windows.Storage.Streams Imports Windows.UI.Popups Public NotInheritable Class InputAnswerPage Inherits Page Private myPoint As Integer Private readingText As String
ページがアクティブになった時の処理
答えを入力するTextBoxにフォーカスを移します。レベルを表示します。
Protected Overrides Sub OnNavigatedTo(e As NavigationEventArgs) TextBox1.Focus(Windows.UI.Xaml.FocusState.Keyboard) levelTextBlock.Text = myLevel MyBase.OnNavigatedTo(e) End Sub
[判定]ボタンがタップされた時の処理
答えが入力されていない場合は、警告を出して処理を抜けます。答えが入力されていた場合は、変数nenTukiHiに現在の年月日を格納します。答えを入力する欄に、「正解!」または「不正解!」と表示されていた場合は、答えの入力欄をクリアします。スコアの表示も0にします。
TextBox1に入力された値と、ランダムな数値の合計を格納している、モジュール変数SumTotalが同じであった場合は、答えの入力欄に「正解です!」と表示し、スコアを表示します。そして、キャラクタで「正解!」と喋らすsyokoVopiceタスクを実行します。正解で無い場合は「不正解です。」と表示し、音声を喋らすsyokoVoiceタスクを実行します。
変数saveXmlに現在の年月日時間分秒.xmlという名前のファイル名を格納します。
ピクチャライブラリ—のMentalArithmeticXMLフォルダーにアクセスします。
XElement型の変数resultXmlを宣言し、埋め込み式の構文である を用いて要素の値に、nenTukiHi、の値にketaValue、の値にspeedValue、の値に、mojiSizeValue、の値に、bacGroudnValue、の値に、leveltextBlock.Textの値、の値にmyPointを指定して格納します。
XElement.ParseメソッドでresulyXml.ToStringの内容を文字列として読み込みます。
変数resultに読み込んだXMLを格納します。
CreaterFileAsyncメソッドでピクチャライブラリ—のサブフォルダーMentalArithmeticXML内に、現在の年月日時間分秒.xmlを作成し、変数myXmlFileで参照します。
Await myXmlFile.OpenAsync(FileAccessMode.ReadWrite)
でXMLファイルを読み込みと書き込み専用で開き、myStream変数で参照します。
データを出力ストリームに書き込む新しいDataWriterのインスタンスwriterオブジェクトを作成します。これはmyStreamで初期化されています。
エンコードにUTF-8を指定し、WriteStringメソッドでxmldocの内容を出力ストリームに書き込みます。StoreAsyncメソッドで、パッキングストアにバッファーのデータをコミットします。
非同期処理で行われるため、メソッドの先頭にAsyncを追加します。
Private Async Sub hanteiButton_Click(sender As Object, e As RoutedEventArgs) Handles hanteiButton.Click If TextBox1.Text = String.Empty Then Dim myMessage As New MessageDialog("解答を入力してください。") Await myMessage.ShowAsync Exit Sub Else Dim nenTukiHi = DateTime.Now.ToString("yyyy年MM月dd日") If TextBox1.Text = "正解!" OrElse TextBox1.Text = "不正解!" Then TextBox1.Text = String.Empty scoreTextBlock.Text = "0" TextBox1.Focus(Windows.UI.Xaml.FocusState.Keyboard) Exit Sub End If If CInt(TextBox1.Text).Equals(SumTotal) Then TextBox1.Text = "正解です。" readingText = "正解です。せんせきを保存しました。" myPoint = myLevel * calcNo scoreTextBlock.Text = myPoint myStackPanel.Visibility = Windows.UI.Xaml.Visibility.Visible Await syokoVoice() Else TextBox1.Text = "不正解です。" readingText = "残念。不正解です。" Await syokoVoice() scoreTextBlock.Text = "0" Exit Sub End If Dim saveXml = DateTime.Now.ToString("yyyy年MM月dd日HH時mm分ss秒") & ".xml" Dim myStorageFolder As StorageFolder = Windows.Storage.KnownFolders.PicturesLibrary Dim mySubFolder = Await myStorageFolder.CreateFolderAsync("MentalArithmeticXML", CreationCollisionOption.OpenIfExists) Dim resultXml As XElement = <結果><情報><年月日><%= nenTukiHi %></年月日><桁数><%= ketaValue %></桁数><速度><%= speedValue %></速度><文字サイズ><%= mojiSizeValue %></文字サイズ><背景><%= backGroundValue %></背景><レベル><%= levelTextBlock.Text %></レベル><スコア><%= myPoint %></スコア></情報></結果> Dim xmldoc As XElement = XElement.Parse(resultXml.ToString) Dim result = xmldoc.ToString Dim myXmlFile As StorageFile = Await mySubFolder.CreateFileAsync(saveXml, CreationCollisionOption.ReplaceExisting) Using myStream As IRandomAccessStream = Await myXmlFile.OpenAsync(FileAccessMode.ReadWrite) Dim writer As DataWriter = New DataWriter(myStream) writer.UnicodeEncoding = UnicodeEncoding.Utf8 writer.WriteString(result) Await writer.StoreAsync End Using End If End Sub
結果をキャラクターが音声で喋る処理
MediaElement型のmyMedia変数を宣言し、MediaElement1で初期化しておきます。
音声機能へのアクセスを提供する、新しいSpeechSynthesizerのインスタンス、synthオブジェクトを作成します。
SynthesizeTextToStreamAsyncメソッドで、指定した文字列から、音声出力を非同期に生成します。
SetSourceメソッドで、指定されたストリームおよびMIME型を使用してSourceプロパティを設定します。Playメソッドで音声を再生します。
音声にどんな言語で、どのような声で喋らすかは、SpeechSynthesizerのVoiceプロパティで参照できます。下記のURLを参照してください。
> SpeechSynthesizer.Voice | voice property
上記URLを見るとJapanese JA は性別が「Female」で、名前は「Haruka」という女性が読み上げるようです。
非同期処理で行われるため、メソッドの先頭にAsyncを追加します。
Private Async Function syokoVoice() As Task Dim myMedia As MediaElement = Me.MediaElement1 Dim synth = New Windows.Media.SpeechSynthesis.SpeechSynthesizer Dim stream = Await synth.SynthesizeTextToStreamAsync(readingText) myMedia.SetSource(stream, stream.ContentType) myMedia.Play() End Function End Class
次に、ソリューション・エクスプローラー内のResultShowPage.xamlを展開して表示される、ResultShowPage.xaml.vbをダブルクリックしてリスト6のコードを記述します。
ロジックコードを記述する
リスト6 (ResultShowPage.xaml.vb)
Imports Windows.Storage Imports Windows.Storage.Streams ‘ DataInfoクラスに文字列型の「年月日」、「桁数」、「速度」、「文字サイズ」、「背景」、「レベル」、「スコア」プロパティ ‘ を定義しておきます。 Public Class DataInfo Public Property 年月日 As String Public Property 桁数 As String Public Property 速度 As String Public Property 文字サイズ As String Public Property 背景 As String Public Property レベル As String Public Property スコア As String End Class Public NotInheritable Class ResultShowPage Inherits Page ‘ 要素の厳密に型指定された読み取り専用のコレクションを表す、IReadOnlyCollection(Of IStorageFile)型の ‘ メンバー変数readFilesを宣言します。 Private readFiles As IReadOnlyCollection(Of IStorageFile)
ページがアクティブになった時の処理
ピクチャライブラリ—のMentalArithmeticXMLフォルダーにアクセスします。フォルダー内のファイルをGetFilesAsyncメソッドで取得し、コレクション変数readFilesに格納します。
新しいDataInfoクラスのリストであるmyDataListオブジェクトを作成します。
取得したファイル内のファイルを変数resultに格納しながら、以下の処理を繰り返します。GetFileAsyncメソッドでresult.Nameで指定したファイルを取得し、変数docで参照します。
Await doc.OpenAsync(FileAccessMode.Read)
と指定して、ファイルのランダムアクセスストリームを開きます。StreamReaderでファイルを読み込みReadToEndでファイルを読み取り変数myResultに格納します。
XElement.ParseメソッドでmyResultに格納されているXMLを文字列として読み込みます。
Descendantsメソッドで全ての子孫要素、情報要素内の値を、変数xmlResultに格納しながら以下の処理を行います。
DataInfoクラスの「年月日」プロパティに要素の値を、「桁数」プロパティに要素の値を、「速度」プロパティに要素の値を、「文字サイズ」プロパティに要素の値を、「背景」プロパティに要素の値を、「レベル」プロパティに要素の値を、「スコア」プロパティに要素の値を指定して、Addメソッドで、myDataListオブジェクトに追加します。GridView1のItemsSourceプロパティにDataListオブジェクトを指定すると、保存していた戦績の一覧が表示されます。
AddHandlerステートメントで、GridViewが読み込まれた時に、GridView1_Loadedイベントハンドラを実行します。
Protected Overrides Async Sub OnNavigatedTo(e As NavigationEventArgs) Dim myStorageFolder As StorageFolder = Windows.Storage.KnownFolders.PicturesLibrary Dim mySubFolder = Await myStorageFolder.CreateFolderAsync("MentalArithmeticXML", CreationCollisionOption.OpenIfExists) readFiles = Await mySubFolder.GetFilesAsync Dim myDataList As New List(Of DataInfo) Dim myResult As String = String.Empty For Each result In readFiles Dim doc As StorageFile = Await mySubFolder.GetFileAsync(result.Name) Using myStream As IRandomAccessStream = Await doc.OpenAsync(FileAccessMode.Read) Using reader As StreamReader = New StreamReader(myStream.AsStream, System.Text.Encoding.UTF8) myResult = reader.ReadToEnd End Using End Using Dim xmldoc As XElement = XElement.Parse(myResult) For Each xmlResult In From c In xmldoc.Descendants("情報") Select c With myDataList .Add(New DataInfo With {.年月日 = xmlResult.Element("年月日").Value, _ .桁数 = xmlResult.Element("桁数").Value, _ .速度 = xmlResult.Element("速度").Value, _ .文字サイズ = xmlResult.Element("文字サイズ").Value, _ .背景 = xmlResult.Element("背景").Value, _ .レベル = xmlResult.Element("レベル").Value, _ .スコア = xmlResult.Element("スコア").Value}) End With Next Next GridView1.ItemsSource = myDataList AddHandler GridView1.Loaded, AddressOf Me.GridView1_Loaded MyBase.OnNavigatedTo(e) End Sub
GridView1が読み込まれた時の処理
最も新しく追加したGridViewまでScrollIntoViewメソッドでスクロールして、そのデータを選択状態にします。この状態なら、キーボードの「←」や「→」キーで選択ができます。Windows ストアの審査では、このような場合は、キーボードで選択できないとリジェクトの原因になりますので、注意してください。
Private Sub GridView1_Loaded(sender As Object, e As Object) Dim _myIndex As Integer = 0 _myIndex = readFiles.Count - 1 If _myIndex < 0 Then Exit Sub Else GridView1.Focus(Windows.UI.Xaml.FocusState.Keyboard) GridView1.SelectedIndex = _myIndex GridView1.ScrollIntoView(GridView1.SelectedItem) End If End Sub End Class
これで2回にわたってお届けした動体視力暗算アプリの解説は終了です。それではまた次回の記事でお会いしましょう。
連載バックナンバー
Think ITメルマガ会員登録受付中
全文検索エンジンによるおすすめ記事
- 制限時間内に指定した画像を見つけ出す脳トレーニングアプリを作ろう
- キャラクターが音声で応援してくれる脳トレーニングアプリを作ってみよう
- Webカメラで撮影した写真をセピア調に演出するアプリを作る
- 撮影した写真の管理ができるマイフォトアプリを作る
- キャラクターが声で天気予報を教えてくれるアプリを作る
- 画像に各種フィルタを適用して保存するWindowsアプリを作る
- 時刻とともに、その日の出来事をキャラクターが音声で教えてくれるアプリを作る
- 場所と写真を記録するプログラムを作って思い出のシーンを保存しよう
- PCで撮影した写真を並べて最適な1枚を選べるプログラムをつくる
- ListBoxに表示された画像をポップアップメニューから削除する+1つのサンプル