キャンバスアプリ 脳トレ漢字の間違い探しアプリの作り方 その① ベータ版

はじめに

この記事は、Microsoft Power Apps Advent Calendar 2024 12月11日担当分の記事です。

先日、夜思い付いて脳トレでよくある漢字の間違い探しのアプリをつくってみました。
最初に1時間くらいで作って基本機能は出来ました。そこから、次の日くらいに思いついた拡張機能を追加していった感じです。
なんでもそうですが、最初っから色々詰め込むよりはまずはサクッと作り、そこから機能拡張していくような感じがいいよなーと思っております。特にPower Appsはその辺とてもやりやすいのでいいですよね!

ということでその①では最初のベータ版のバージョンまで、その②で拡張した作りの部分をご紹介していこうと思います。

サンプル動画

YouTubeに①ベータ版と②拡張版の動画をアップしました。


以下以前Xにポストしたときの動画です。前のポストが①ベータ版、次のが②拡張版という感じですね。

漢字間違いを探すアプリの機能について

TIPSこのゲームの概要:
・見た目が似ている漢字を表形式で並べてそのうち一つの間違いを探すゲーム

機能を洗い出し

 まずは基本的な機能部分を考えます。機能というかアプリの内容かな。

  • 問題として見た目が似ている漢字のセットを用意する
  • 表に並べてひとつだけ違う漢字、それ以外は同じ漢字を出す
  • ひとつだけ違う漢字を選択出来たら正解にして次の問題へ切り替える
  • 制限時間一杯または10問正解したら終了画面へ遷移する
  • 終了画面で正解数やかかった時間などを表示する
  • データソースはアプリ保持にする

→上記が基本的な感じでしょうか。とりあえず、制限時間制で作ってみます。
問題数もとりあえずは10問固定で順番に出題されるで作ります。
配布しやすいようにデータソースもアプリ内に保持する形でやります。まあ問題位なので。

拡張要件


作っている途中や完了後に色々拡張したい機能が出てきます。
この辺は一旦出来てから追加することにします。

  • ランダムに出題されるようにする
  • 表示する文字数を変更して難易度を選択できる
  • 10問、20問、30問とタイムアタックモードを選択できる
  • ユーザー好みのカラーを選択できる (なぜか入れちゃったけど後回しでよい)
  • ランキング一覧を追加する
  • CLEAR履歴や選択カラーをキャッシュで保持する

メインのロジック部分は先にイメージしておく

今回のアプリではギャラリーを縦横のマス目で表示して漢字をそれぞれ表示したいです。
問題ごとに一つだけ異なる漢字を入れたテーブルデータを用意するのもアリですが、問題の一覧を用意して正・誤のセットを持たせておき各マス目から参照させる。マス目には連番を振っておき、毎回ランダムに違う漢字となる番号を決めれば、その番号のマス目だけ違った漢字になる。
と言ったロジックでの実装を考えました。以下のようなイメージです。
これにあてはめて実装を進めていきます。

アプリを空から作成

まずはアプリを空から作成します。本来はスマホ用レイアウトで作ってよかったんですが、タブレットで作ってました。
なので、作成後にレイアウトを横→縦に変更しています。


設定>表示から向きを縦へ

今回モダンコントロールも一部使うのでモダンをオンにしておきます。
設定>更新>モダン コントロールとモダンテーマをオン

メインスクリーンを作る

最初のトップ画面は後回しで先にメイン画面を作ります。
ここにはアプリ名なんか書いたヘッダー、真ん中にギャラリー、その下に時間表示、下の枠に移動ボタンを想定します。

なんとなくコンテナーを入れてますが、無くても問題ありません。
上部にコンテナーを入れてモダンのヘッダーコントロールを追加。アプリ名を付けます。他はお好みで。

ヘッダーを追加

ギャラリーを追加

ここがメインですね。コンテナーを追加してその中にギャラリーを入れます。
一旦空のギャラリーにしておきます。

ギャラリーの折り返しを設定する(サンプルでは9)

ギャラリーで正方形が並ぶように表現したいので、折り返しを設定します。まずは9で固定してみます。
そしてとりあえずボタンを入れます。ボタンの大きさはテンプレートサイズ幅と同じに広げておきます。

ギャラリーに表示するマス(数値の連番)を定義して指定する

横を9列に指定しているので、縦も9列 →9×9 で81個のデータ、というかマス目を用意したいです。
連番を作るにはSequence関数を使います。

Sequence 関数 – Power Platform | Microsoft Learn

直接ギャラリーに指定してもいいですが、他でも使いそうなのでApp.Formulasに定義しておきます。

CodegalCol=Sequence(81,1);

ギャラリーのItemsに指定して連番を表示

上記をギャラリーのItemsに指定します。そして配置しているボタンのTextプロパティをThisItem.Valueにします。
1~81までの連番が表示されますのでイメージ付きやすくなりますね。
またボタンは種類をSecondaryにして白っぽくしています。

サンプルの問題を用意する

一旦画面を離れて先に問題のサンプルを用意しようと思います。
そもそもどのような形の問題があればいいのかというと、今回のゲームでは一つだけ違う漢字があり、他は同じ漢字のセットがあればいいですね。それに問題用のIDを付けてあげる形で用意します。

App.Formulasに問題を定義

まずは10問、それっぽいのを探したり考えたりして追加します。
項目はid、trueText、falseTextとしたレコードを10個配列で定義します。

CodekanjiCol=[{id:1,trueText:"右",falseText:"左"}
,{id:2,trueText:"上",falseText:"土"}
,{id:3,trueText:"頂",falseText:"頃"}
,{id:4,trueText:"開",falseText:"閉"}
,{id:5,trueText:"雲",falseText:"雪"}
,{id:6,trueText:"倹",falseText:"検"}
,{id:7,trueText:"雑",falseText:"難"}
,{id:8,trueText:"都",falseText:"郡"}
,{id:9,trueText:"准",falseText:"淮"}
,{id:10,trueText:"質",falseText:"資"}
];

ギャラリー内のボタンの参照値を問題一覧に変更して調整する

ギャラリー内のボタンからApp.Formulasに定義した問題一覧(KanjiCol)を参照します。
IDや間違った数値は後で変数にして動的にしますが、一旦、以下のように固定値で試してみます。

この際にボタンの文字の大きさを見やすく大きくしておきます。(サンプルでは40にして太さを標準に調整)

CodeWith(LookUp(kanjiCol,id=1),If(ThisItem.Value =5,falseText,trueText))

Withを使って2回参照しないようにしてます。ID(上記では1)をLookupして自分の連番が間違った値(上記では5)の場合にfalseTextを、それ以外はtrueTextを。としています。

以下のように5番目のマスだけ誤った漢字になっていれば成功です!

一旦変数を作成するダミーボタンを用意して調整

一旦適当にボタンを追加して、今の問題ID用の変数:Current と間違いの番号の変数:Wrong を定義します。
合わせて後で使うScore変数も0で定義しておきます。

Wrongの値は RandBetween関数で1からマス目の数の範囲にしたいので以下のように定義します。

CodeConcurrent(
    Set(Current,1),
    Set(Wrong,RandBetween(1,CountRows(galCol))),
    Set(Score,0)
);

先ほどのギャラリー内のボタンの定義を数値から変数に修正します。
そしてボタンをクリックするとIDが1の問題が出て、ランダムに一つが間違った漢字になると思います。

CodeWith(LookUp(kanjiCol,id=Current),If(ThisItem.Value =Wrong,falseText,trueText))

問題数の表示テキストを追加

Currentに問題数が入るようになったので上部に第〇問 のラベルを追加します。サンプルではボタンにしてます。

正解時の処理を作る

次に正解した場合の処理を作りましょう。正解のボタンをクリックした場合は、その漢字を表示、次の問題へ進むのボタンを出したいと思います。また、10問までとしているので、10問目の場合はエンド画面へ遷移したいです。
※タイマーを一時停止したりもするのですが後で足します。

ボタンのOnSelectを実装

正解(間違った漢字)をクリックした場合のみ処理したいのでそのIf文を書きます。
正解の場合はスコアを+1して、正解画面表示用の変数:IsAnswerViewをTrueにします。

Code//正解時
If(ThisItem.Value =Wrong,
    Concurrent(
        Set(Score,Score+1),Set(IsAnswerView,true)
    )
)
※ConCurrentは並列処理にして少しでもパフォーマンスを上げるためです

正解時のモーダル表示画面を作る

ここはある程度自由でいいんですが、サンプルでは以下のようにして作ってます。
正解!の文字とその漢字、次に進むボタンを付けてます。

コンテナーを作って一番上に配置します。
Visibleには先ほどの変数:IsAnswerViewを指定します。Fillは半透明にしています。

上のテキストは正解!で固定。真ん中の文字は正解(間違いの漢字)を出してます。

ボタンのテキストは10問目の場合は結果へ!としてそれ以外は次の問題へとしてます。
OnSelectにはとりあえずCurrentを+1、Wrongを再度ランダム値で設定、正解モーダルを非表示にしています。

CodeConcurrent(
    Set(Current,Current+1),
    Set(Wrong,RandBetween(1,CountRows(galCol))),
    Set(IsAnswerView,false)
)

TIPSこの状態で動かすと正解の度に上記が表示、次の問題へ切り替わると思います。
※ダミー用の初期化ボタンをクリックすると最初のIDに戻ります。

タイマー処理を追加する

次にタイマーを追加します。ギャラリーの下を開けているのでそのあたりに追加します。
大きさや位置は調整してください。
自動開始をオンにします。また、表示モードはビューにしておきます。Durationは今回60秒の制限にしているのでそのまま60000です。

Startに変数を指定、各ボタンに変数の調整処理を追加

ボタンを追加したら、Startプロパティに変数:TimerStart を指定します。この時点でエラーとなるので、各ボタンに変数の更新処理を追加します。

タイマーのStartに「TimerStart」を指定

デモ用ボタンにタイマーのリセットとTimerStartをTrueにする処理を追加。(併せて正解モーダルを非表示にする処理も追加)
※この処理は後でスタート画面に持っていきます。一旦この時点では最初だけタイマースタートしないと思いますがスルーしておいてください

ギャラリー内のボタンのOnSelectにもTimerStartをfalseにする処理を追加 (一旦止める)

正解モーダルのボタンのOnSelectにTimerStartをTrueにする処理を追加(タイマーを再開)

スタート画面を追加する

ここまで来ておおよその動きは出来てきました。いまのところだと、60秒立っても何も起きませんし、10問正解しても次のIDがないので空欄になる状態です。
後はスタート画面を作って、10問終わった場合とタイマーが終了したときに終了画面へ遷移する実装をする感じですね。

ということでスタート画面を作ります。メイン画面のヘッダー部分などコピーして同じように作ればいいですね。この段階で、ScreenStart、ScreenMainと名前付けもしておきましょう。

一番下のスペースにはコンテナーを入れてFillを「App.Theme.Colors.Lighter80」として色合いをあわせたフッダーを追加しています。

この画面に先ほど作成していたデモ用のボタンを持ってきて配置しましょう。
テキストを「開始」としてあげてサイズや位置、角丸などお好みで調整します。

OnSelectの処理にメインスクリーンへ遷移する処理を追加します。

動かしてみてギャラリー画面が表示され、最初の問題が表示、タイマーがスタートしてくれればOKです。

メイン画面にスタート画面へフッダー、戻るボタンを追加

メイン画面にスタート画面と同じくコンテナーを追加してフッダーを追加し、
その中へスタート画面へ(サンプルではホームにしちゃってるがどっちでもいいっすね)戻るボタンを追加します。

これでスタート画面とメイン画面の行き来は出来ました。

終了画面と終了処理を追加する

さて、やっと最後ですね!最後は終了画面を作って結果を表示します。
また、メイン画面から終了処理へ自動遷移する処理(10問完了またはタイマー終了)を追加していきます。

終了画面を追加

これもスタート画面をコピーするなどで同じレイアウトとして中身を調整していけばスムーズです。

とりあえずスタート画面を複製して真ん中のボタンを削除した状態

正直この辺はお好みで調整してもらえればなんですが(後々拡張した際に変えたりもしますし)
正解した問題数とかかった秒数を表示するようにします。
真ん中のエリアにコンテナーを入れてドロップシャドウしたりなどしてます。

問題数には以下を指定。Score に回答数を入れているのでそれを表示

かかった時間には以下を表示。タイマーの値を1000で割って丸めて秒にしています。
Round( Timer.Value/1000,1) & ” 秒”

メイン画面からの遷移(終了処理)を追加

メイン画面に戻って、タイマーのOnTimerEndプロパティに終了画面へ遷移する処理を追加します。
Navigate(ScreenEnd)ですね。

次に10問終了した場合に遷移する処理を追加します。
正解モーダル画面の「次の問題へ」ボタンのOnSelectにIf文で囲って10問目の場合は終了画面へ遷移するようにします。※ボタン名も10問目の場合は結果へ!と変えています。

CodeIf(Current=10,
    Navigate(ScreenEnd)
    ,
    Concurrent(
        Set(Current,Current+1),
        Set(Wrong,RandBetween(1,CountRows(galCol))),
        Set(IsAnswerView,false),
        Set(TimerStart,true)
    )
);

動作を確認

実際には作りながらちょこちょこ動作確認しつつとなりますが、ここまででVer1は基本完成です。
プレビューでの動作確認、アプリを公開しての動作確認をやってみましょう。

フォントを明朝体にする

最後にフォントを調整してみましょう。Power Appsはフォント名をテキストで指定することで日本語のフォントも使えます。ただブラウザによっては対応、非対応がありますのでブラウザ、スマホ双方で対応しているようなフォントがいいですね。自分の場合、タイトルや問題部分を明朝体(HGP明朝B)で指定してみました。
PCとiPhoneではちょっと雰囲気が違ったのでちゃんと当たってない気もしましたがひとまずいいやとw

NOTE※本当はゴシックと明朝体で切り替え可能な機能も付けたりしたんですが、スマホの場合にゴシックがいまいちだったりしたので切替え機能は取りやめました。

おわりに

ということで今回はまず最初のベータ版ということで10問固定で時間制限制の基本的な機能を持つ漢字間違い探しアプリを作りました。
記事にしたら結構な工数に見えますが、ここまで作るのに実際には1時間とちょっとくらいで出来てます。ブログに起こした時間はその3倍かかりましたw

Power Appsだと思い付いたらすぐに実装、確認、調整が出来るのでとってもスピーディーにアプリが作れます。基本的なロジックが描けているのであればすぐだと思います。
ただ、作っている途中に色々動的な調整や追加機能なども思いつくのですが、一旦基本ベースを作ってからそのあたり追加していった方が最初のうちは特にいいのかなーと思います。まあ特に業務アプリの場合は勝手に機能追加したりはいかんですよね(笑)

このベータ版に以下の機能を追加していくのですが、ベースは出来ているので適宜調整していけばいいのでスムーズに進みます。実際以下を追加するのには1時間半位だったと思います。(想定出来てたり経験がある機能の実装だからとも言えますが)
そもそもマス目が細かくてやってみたら見えねーとなり、難易度(マス目を少なくする)をやらなきゃなが最初でしたw

  • ランダムに出題されるようにする
  • 表示する文字数を変更して難易度を選択できる
  • 10問、20問、30問とタイムアタックモードを選択できる
  • ユーザー好みのカラーを選択できる (なぜか最初のアプリでは入れちゃったけど本来後回しでよい)
  • ランキング一覧を追加する
  • CLEAR履歴や選択カラーをキャッシュで保持する

ということで、その②では上記の機能追加部分を書いていこうと思うのですが、、その①書くので結構疲れてしまったので、ちょっと間が空いてしまいそうです。。そのうちに書きますのでしばしお待ちを。

その②を書きました!(残りはその③で)それでは!

関連記事

この記事は役に立ちましたか?

もし参考になりましたら、下記のボタンで教えてください。

ヨウセイ

ヨウセイ

一般職からSharePoint、C#、.NET系技術者へ、そこからPower App、Power Automate技術者へと転身。 ワンランク上のおっさんはPower Appsでシステム開発が出来る〜! qiitaや自社HPでも技術ブログを書いていました。

関連記事

コメント

この記事へのコメントはありません。

CONTENTS