75才からのモバイルアプリ作成

MIT App Inventor 2 を使ったアプリ作成

MIT App Inventor 2でチャレンジしたらどうなる (Coding Challenge 1)

2024-11-22 08:07:58 | 日記

Coding Challengeとは、Google先生によると、プログラミング能力を競う競技や、スキルを向上させるための課題を解くこと、とのこと。

Coding Challengeを行う場や機会がウエッブサイトにて多数提供されている。

MIT App Inventor2 は、子供から大人までが手軽にスマホのアプリを作れるようにと開発されたツールなので、Coding Challengeのようなものには向かないと思うが。componentの使い方やアルゴリズムの練習にはいいかもしれない。

今回のCoding ChallengeはProject Eulerという有名な(?)サイトにある906個の問題の中で、もっともやさしい問題2つにチャレンジするもの。

実行画面のビデオ(Problem 1 and Problem 2):

問題は以下の通り。

Problem 1

If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23. Find the sum of all the multiples of 3 or 5 below 1000.

要するに、1000未満の自然数で、3または5の倍数の合計を計算せよ、という問題。

スクリーン・デザイン:

                                                    

コード・ブロック:

problemLabelに問題の内容を表示し、倍数のリストと合計を表示するlabelを初期化。

該当の倍数を格納する変数numPickedを初期化(0)。

該当の倍数をリスト形式で格納する変数pickedNumsListを初期化。

1000未満までの自然数なので、範囲は1から999。

各数字が3あるいは5の倍数かをチェックし、もしその条件に該当する場合は、その数を変数pickedNumsListに格納。

なお、3または5の倍数ではなく、3と5の公倍数の場合は、「or」の代わりに「and」を指定すればOKか。

変数numPickedに3または5の倍数だった数を加算して行く。

999までチェックが終わったら、該当の数を合計した数字が格納されているnumPickedをaddedUpAmountLabelに表示。また、picked NumsListの数字をlistOfNumsLabelに表示。

 

Probelm 2(2番目にやさしい問題)

Each new term in the Fibonacci sequence is generated by adding the previous two terms. By starting with 1 and 2, the first 10 terms will be:
                                                                    1,2,3,5,8,13,21,34,55,89...
By considering the terms in the Fibonacci sequence whose values do not exceed four million, find the sum of the even-valued terms.

要するに、4,000,000未満のフィボナッチ数列の偶数のみを合計せよ、という問題(?)

フィボナッチ数列の全ての数を合計した場合と偶数のみを合計してた場合に分けて表示するようにした。

スクリーン・デザイン:

                                                           

コード・ブロック:

変数firstNumに1をセット。(1番目の数字で、最初に1が与えられている)

変数secondNumに2をセット。(2番目の数字で、最初に2が与えられている)

変数thirdNumには0をセット。

数列を格納する変数numsListを初期化。

偶数の数列を格納する変数evenNumsListを初期化。(この数字の合計が今回の問題の解答)

2番目の数字が4,000,000未満であれば、

=>変数firstNum(1番目の数字=1)に同secondNum(2番目の数字=2)を加算し、結果を変数thirdNumに格納

=>次に1番目の数字としてsecondNumを設定

=>また、2番目の数字としてthirdNumを格納

 さらに、thirdNumの数字が4,000,000未満であれば、thirdNumの数字をnumsListに追加

 そして、このthirdNumの数字が偶数であれば、

  =>thirdNum の数字をevenNumsListに追加する。

わざわざ図解するほどでもないが、

                                 

関数addFirstTwoNums、関数addFirstEvenNum、関数sumUpNumbers、関数sumUpEvenNumbersを実行し、それぞれのLabelに結果を表示する。

関数addFirstTwoNums:

 =>所与の一番最初の数字(1)と2番目の数字(2)をnumsListの最初に(index =1)追加する関数

関数addFirstEvenNum:

 =>また、偶数である所与の2番目の数字(2)をevenNumsListの最初に(index =1)追加

関数sumUpNumbers:

 =>numsListに保存されている数字を合計し、変数summedNumに格納

 =>extensionを使って3桁毎にカンマを入れている

関数sumUpEvenNumbers:

 =>evenNumsListに保存されている数字を合計し、変数summedEvenNumに格納(これが解答

 =>extensionを使って3桁毎にカンマを入れている

 

                                                       ***********************************************

以上が正解かどうかはわからないが。

ちょうどいいコーディング(アルゴリズム)の練習になり、頭の体操にもなる。でも、「Start」ボタンを押したら一瞬で終了で、それ以上の動きがないのはちょっと寂しい。やはり普通のアプリの方が動きがあって、作っていても楽しい。

もう少し、アプリらしく作った方がいい。

                                                       ***********************************************

次回は、別のCoding Challengeにも挑戦したい。

 


MIT App Inventor 2で遊ぶ (T-Rex Jump 1)

2024-11-18 08:29:15 | 日記

再度マリオ型ゲームに挑戦。

Google Chromeの有名なゲーム T-Rex Game がお手本。今回のブログでは、T-Rex (ティラノサウルス・レックス)をジャンプさせてみるだけで、背景はまだ動かない。と言うより、今のところ背景を右から左へ動かすとうまくいかないから、が正確な表現。

また、本来であればスクリーン・オリエンテーション(画面の向き)は、landscape(横向き)だが、とりあえず慣れているportrait(縦向き)に設定。試験的に横向きで試行錯誤してみたが、これまた、うまく作動しない。

               ********************************************************

作り方は、marioに非常によく似ていると言うよりは、marioの代わりにティラノサウルスが飛び跳ねるようなものを作ればよい。たったそれだけのことなのだが。

marioの復習を兼ねて作ってみることにした。mario型ゲームの技術面なら、YouTuber Tutorials Azaotlさんに教えを乞うのがいちばんの近道。というより、Tutorials Azaotlさんが教えてくれる通りに作ればうまくいく(はず)!!!

marioの時はAzaotlさんのブロック・コードを理解せずに、単に「模写」しただけだったが、今回はブロック・コードの理解を深めたい。特に、ジャンプする際のブロック・コードなど私にとってブラック・ボックスだった部分も細かくみていきたい。

YouTubeには、いくつかのプログラミング言語でこのゲームの作り方に関するチュートリアルがアップされている。ゲーム全体の感じを知る上で参考になったのは、以前も紹介したYouTube Channel "Code with Ania Kubów" の T-rex run in JavaScript! (Super simple!!!)

では、現実問題として、

ポイントは2つ。1つは、T-Rexをジャンプさせること。もうひとつは、背景を右から左に動かすこと。どちらも私が出る幕はない。Tutorials Azaotlさまさまです。でも、初めに書いた通り、今回はジャンプだけ。

今後検討を要する課題としては、画面を横向き設定にすること。背景を動かすスピードを徐々にあげること。障害物のサイズを徐々に大きくすることなど。まだまだ先の先の話だが。。。

アプリ実行のビデオ:

ジャンプするだけのつまらないビデオ。

スクリーン・デザイン:

メインスクリーン Screen1(左)=>

  Check (Button):ジャンプ時のT-RexのY座標値を確認するためのスクリーンへ遷移するボタン。

  RexSprite:ティラノサウルスのイメージを格納するコンテナー(sprite)

  animationClock:T-Rexが走っているように表示するアニメーション用Clock

  jumpingClock:T-RexがジャンプするためのClock(画面をタップしたらジャンプする)

checkYPosScreen(右)=>

  Back:メインスクリーンに戻るボタン

  PositionY of T-Rex:T-Rexがジャンプした際の45ミリ秒ごとのY座標値を表示するLabel

                     

ブロック:コード:

以下のブロック・コードは私が考えたブロック・コードではない。また、記述内容はTutorials Azaotlさんのコードを私なりに理解し学んだ内容。

Tutorials Azaotlさんのtutorial  App Inventor Tutorial: how to make Mario jump | variable jump height を「模写」しながらブロックを組み立てた。(ファイル名等は異なるが))

ポイントとなるブロック・コードのみ。

1. T-Rexを走らせる:

 animationClockは、アプリ実行と同時に有効になるように設定。timerIntervalは45ミリ秒。

 有効になると関数AnimateRexを実行。

 

 表示するT-Rexのイメージのコマ番号を格納する変数animationFramesを設定。

 

 変数animationFramesを 1 にセット。

 animationFramesが 3 未満の場合は、Dino + animationFrames + .png を表示。

 animationClockのTime Intervalである 45ミリ秒間隔で、animationFramesに 1 と 2 が交互に挿入される。

 その結果、Dino1.pngとDino2.pngが交互に表示されることになる。

 animationFramesが 3 以上になると、animationFramesを初期値の 0 にセットし直す。

 こうして、パラパラ漫画のようにT-Rexが走っているように表示される。(説明するまでもないが)

 

                          

               Dino1.png          Dino2.png

 

2. T-Rexをジャンプさせる:

 Canvasを押し込んだ場合は、TouchDownのイベントハンドラーにより関数PrepareForRexJumpを実行

 (軽くタップし、すぐに指先を上げた場合は、後述のTouchUpのイベント・ハンドラーが対応する)

 ジャンプしているかどうかを判定する変数Jumpingを作成し、falseで初期化

 変数RexSpeedYを作成し、T-Rexのジャンプする速度(縦方向)を 0 で初期化

 事前準備のための関数 (PrepareForRexJump) を設定

 変数Jumpingがfalseの場合(まだジャンプしていない時)は、以下を実行

  T-Rexが飛び上がる初速を設定=>-60pixels (Canvasの左上端が座標の 0, 0 。下に移動は+、上に移動はー。)

                                                                (Set global RexSpeedY to -60)

  animationClockを停止=>ジャンプした場合は、走る動作を休止 (Set animationClock.TimerEnabled to false)

  T-Rexのイメージを上記のうちの一つ(Dino1.png)に固定する。(Set RexSprite.Picture to Dino1.png)

  jumpingClockの起動。(Set jumpingClock.TimerEnabled to true)

 junmpingClockの設定:

 jumpingClockが有効になった場合(変数Jumpingがtrueとなった時)は、関数RexJumpingを実行する

 関数RexJumping:

 ジャンプする場合、上に上がるにつれて速度が減速し、最高到達点で速度が 0 になる。その後は加速しながら下に下がっていく。

 jumpingClockのTimeIntervalをあらかじめ45ミリ秒に設定。

 また、減速、加速の程度を変数gravityとして5(pixels)に設定。

 T-Rexの最初の位置を変数groundに格納。(Canvasの高さ X 0.65 。 今回の場合は、Canvasの上端から496.6 pixelsの位置)

 45ミリ秒ごとに以下を実行させる

 (1)T-Rexの飛び上がる速度 RexSpeedY = RexSpeedY - gravity に設定。gravityは 5 (pixels)に固定。

    (上に行くほど速度が減速していく 最初は -60 + 5 = -55、 45ミリ秒後は、-55 + 5 = -50 。。。という具合に)

    (速度が0 に到達すると、今度は、+5、次に +5 + 5 = +10という具合に加速しながら下向きに移動していく)

 (2)今回の場合、最高到達点はCanvas上端から166.6 (pixels)の点で、そこから下向けに+5ずつ加速しつつ下方向に移動。

    T-Rexの位置が496.6を超えた時点で、T-Rexの位置を変数groundの位置(496.6 (pixels))に設定し、ジャンプは終了。

 (3)T-RexのY座標値を見れば以下の通りで、上記(1)(2)の通りとなっている。

   上にジャンプする時は、出発時点のY座標 (496.6) => 441.6 差は、-55、441.6 => 391.6 差は-50 。。。

   下に降りてくる時は、166.6 => 171.6 差は -5、171.6 => 181.6 差は -10 。。。

 (4)以下記録のキャプチャーとアプリ実行中のビデオは異なる日に作成。数値が若干異なっているが、理由は不明。

                                              

ジャンプの高さを低くしたい場合は、長押しするのではなく、素早く指を離す(タッチ・アップのイベントハンドラー作動) 

この場合、以下の「When Canvas1.TouchUp」のイベントハンドラーが対応するが、Rex-Tの速度が-30未満であれば、その速度を-30に設定する。このようにして、少し上に上がって、すぐに下に下がるスモール・ジャンプとなる。

(タップのタイミングにより、どこまで到達するかが変わっていくことになるのか)

この時の時系列的な速度は以下の通りとなる。スタートは、上記と同じ496.6。

最初に設定された速度-60は、-30より小さいので、-60上に上がる前に-30に変更となりその後は以下の通りとなる。

496.6 => 441.6 差は -55 だが、指を離したら-30に変更され、gravityが加算され -25となる。

441.6 => 416.6 差は -25、416.6 => 396.6 差は -20、396.6 => 381.6 差は -15、381.6 => 371.6 差は -10、 

371.6 => 366.6 差は -5、366.6 => 366.6 差は 0、366.6 => 371.6 差は +5、371.6 => 381.6 差は +10、

381.6 => 396.6 差は +15、396.6 => 416.6 差は +20、416.6 => 441.6 差は +25、441.6 => 471.6 差は+30、

471.6 => 506.6 差は +35 となり、若干下がり過ぎてしまうが??大勢に影響なし??

               

 

                                                       *********************************************************

あまりにも、Tutorials Azaotlさんのブロック・コードそのままなので、少し違う方法も考えてみたい。

また、次回には、背景が右から左に動き、その中で T-Rexをジャンプさせることができたら、と思う。

                                                       *********************************************************

All block codes in this blog originally crafted by Tutorials Azaotl and adapted to the  above app with slight modifications.

 


MIT App Inventor 2で遊ぶ (新ことわざ遊び 3 -U&D of CRUD-)

2024-11-13 07:19:23 | 日記

今回は、CRUDの U : Update(更新)、D : Delete(削除) を実装。

アプリ実行のビデオ:

ミラリングアプリがなぜか知らないが、一回だけうまく作動してくれた。でも、音声の録画設定を忘れたため効果音は録音されていない。

また、編集画面に遷移したときに、「更新または削除したいことわざをタップして選んでください」という感じのAlertをポップアップした方がuser-friendlyと思う。これがないと、ユーザーは、まず、何をする必要があるかわからない。

スクリーン・デザイン:

左がメイン画面。右が編集画面。

                                .         

ブロック・コード:

<編集画面のブロック・コード>

初期化

editScreenの初期化:変数のリセット、各データ固有のIDのリストを取得する関数getTagListの実行、削除ボタンをタップしたときに再生する警告音の設定。

必要データの取得とことわざ一覧のListViewへの表示

以下、前回のブログと同様で、tag list(データのIDリスト)および全データの取得、各項目ごとのリスト作成、ListView用の統合リスト作成のための関数を実行し、ListViewへ表示と続く。

関数、イベントハンドラーは前回ブログで既出なので縮小形式で表示のみ。

選択されたことわざの表示

ListViewでタップしたことわざの内容をTextBoxに表示。(最初の句、次の句、フル・テキスト、かなで表示のフル・テキスト、意味)

タプしたことわざのIDを変数targetIDに格納。

データの更新

更新することわざのデータを格納する変数updatedPostをDictionary形式で設定。

Firebase REST APIのルールに従い、所定のURLに更新することわざのIDを追加する。

(所定のURL + NewProverb/ + targetID + .json)

PUTリクエストをする。(同じIDがあれば、上書きし更新することになる)

TextBox、変数の初期化を行う関数を実行し、再度関数getTagListを実行し、更新後のデータを取得し、改めてListViewにデータを表示。

TestBox、変数の初期化をする関数の内容

ことわざの削除(実際にはあまり削除をすることはないと思うが)

ListViewで削除したいことわざをタップし、TextBoxに当該ことわざが表示されてから、この削除ボタンをタップすることになる。

警告の効果音を再生。

削除対象のことわざを表示し、「以下のデータを削除しようとしています」と注意を促すウインドウが表示され、「削除を実行」、「削除を取消す」「Cancel」の選択肢を提示する。

「削除を実行」を選択した場合は、所定のURLに削除対象のことわざのIDをセットしてDELETEのリクエストを行う。

変数などの初期化後、関数getTagListを実行し、削除後のデータを取得し、改めてListViewに表示。

次回は、番外編となる予定。

                                                     ********************************************************

前回までのブログ:

MIT App Inventor 2で遊ぶ (新ことわざ遊び 2 -R of CRUD-)

MIT App Inventor 2で遊ぶ (新ことわざ遊び 1 -C of CRUD-)


MIT App Inventor 2で遊ぶ (新ことわざ遊び 2 -R of CRUD-)

2024-11-08 08:20:51 | 日記

今回は、CRUDのR(Read)を中心にステップごとに確認しながら、次の句の表示などを実装。次の句を表示させるのは「再読込」ボタンを使っている。

ことわざデータの更新(U)、削除(D)の実装は次回以降に予定(は未定)。

アプリ実行のビデオ:

テスト、確認のためのデータなどがあり、画面がごちゃごちゃしているが最終的には、これら不要なものは削除予定。

また、ミラリング・ソフト (X-Mirage) が不調のため、とりあえずスマホの画面キャプチャーのみ。次回実装予定の更新、削除の時にはソフトがうまく作動し、連動しているところを見ることができればと思うが。

スピーカーをONにすれば効果音も聞ける。

スクリーン・デザイン:

左より、

1. メイン画面:「タグリスト」および「取得JSONデータ」はFirebase Realtime Databaseより読み込むデータを確認するためのもの。また、ことわざデータの出典を明記し、同サイトへのリンク(>)を追加。(MIT App InventorのDesigner画面では全てを表示できなかったので、実際のアプリのスクリーンショットを使用)

2. 追加画面:「最初の句」「次の句」入力欄の次に「かなのフルテキスト」を追加。他は変更等なし

3. ことわざの出典「ことわざ・慣用句の百科事典」のサイトを表示する画面。

                    .           .         

ブロック・コード:

Screen1(メイン画面)の初期化時に、関数reset(変数のリセット)、関数getTagList(データIDのリスト取得)を実行。

また、正解と不正解の際に使う効果音を設定。

「再読込」ボタンをタップした時の動作設定。スクリーンの初期化と同じく関数reset、関数getTagListを実行。加えて、解答(フルテキスト)と正誤チェックの結果を表示するLabelを空白に。

関数getTagList

前回取り上げた各データのID取得と同じ内容。

前回すでに取り上げ済みだが、今回はtestLabel1(タグリスト)にIDを念のため表示。

そして、ことわざデータ取得のためのGETリクエストを行う関数makeGETequestを実行。

関数makeGETequest

データ全てを取得するので、「?shallow=true」は省く。

Firebase Realtime Databaseよりデータを取得後、デコードの上変数JSONDataに格納。

関数makeFirstPartList(最初の句のリスト作成)、関数makeSecondPartList(次の句のリスト作成)、関数makeFullTestList(最初の句と次の句を結合したフルテキストのリスト作成)、関数getRandomlychosenFirstPart(無作為に選んだ最初の句を選択)を実行し、makeSecondPartListが作成したsecondoPartListをSecondPartListPicker(次の句を選択するリスト)に設定する。

関数makeFirstPartList

空の変数firstPartListを設定。

tagaListのIDをキーにして、firstPart(最初の句)のデータをリスト形式でfirstPartListに格納。

関数getRandomlychosenFirstPart

空の変数chosenFirstPartを設定。

firstPartListをextensionを利用してシャッフルし、最初の句をchosenFirstPartに格納。

関数makeSecondPartList

関数makeFirstPartListと同様にsecondPartListに次の句のリストを格納。

関数makeFullTestList

同上。

最初の句とリストより選択した次の句を、全角の空白を間に入れて結合し変数answerFullTextを設定。(データベースに保存してあるフルテキストは、最初の句と次の句の間に全角の空白を挿入してある。)

fullTextListの中にanswerFullTextが含まれていたら、showResultLabelに「正解」を、そうでなければ「もう一度次の句を選んでください」のメッセージを表示するとともに、効果音を再生する。

ことわざデータの出典表示の右端にある「>」ボタンをタップすると、ことわざデータ出典元のサイトを表示するスクリーンへ遷移する。

 

                                            ******************************************************************

前回までのブログ:

MIT App Inventor 2で遊ぶ (新ことわざ遊び 1 -C of CRUD-)

 


MIT App Inventor 2で遊ぶ (新ことわざ遊び 1 -C of CRUD-)

2024-11-04 07:58:25 | 日記

初めて作ったアプリが、ことわざ遊びだったが、もう一度作成。

初回はことわざデータをFirebase Databaseに登録する部分。主に、データベースを扱う基本CRUDのC (Create) を扱う。Firebase REST API を使用。

以前にこのブログで書いた内容と重複する箇所も多いが、Firebaseのデータベース (Realtime Database) の復習も兼ねて。

アプリ実行のビデオ:

スクリーン・デザイン:

左側:メインスクリーン(今回は対象ではない)

右側:ことわざデータ追加画面(今回のブログの対象)

             

ブロック・コード(ことわざデータ追加画面):

メインスクリーンで「追加」ボタンをタップしたら、追加画面 (AddScreen) へ遷移する。

追加画面の初期化componentで「入力チェック」ボタン (checkInputbutton) を無効化。

新規データ(Dictionary形式)を格納する変数postDataを設定。

1.  「保存」ボタン (saveButton) をタップした時のイベントハンドラーの内容

if 条件の内容は、長いため省略(collapse)してあるが、内容は、firstPartTextBox, SecondTextBox, meaningTextBox のいずれもが空白ではない(何らかのテキストが入力されている)場合は then 以下を実行することとしている。

set Web1.Url to =>

HTTP POST リクエストを行う対象のURLを定義。URLの内容は、「Firebase Realtime Database をセットアップした時にFirebase より指定された所定のURL + "NewProverb" + ".json"」

もし、所定のURLのサブディレクトリーに "NewProverb" が存在しない時は、Firebase側で自動的にその名前のサブディレクトリーを作成してくれる。

set global postData to =>

firstPartTextBox, SecondTextBox, meaningTextBox 及び fullText (firstPartTextBox + 全角空白 + SecondTextBox) の4つのデータをDictionary形式で変数postDataに格納。

call Web1.PostText => 変数postDataを所定のURLに対しPOST Requestする。

call AddScreen.HideKeyboard => キーボードを隠す。

checkInputButton.Enabled to true =>「入力チェック」ボタンを有効にする。

もし、if 条件が満たされない場合は、「call Notifier1.showMessageDialog」componentを実行し、入力漏れがあることを表示。

 

2. 「入力欄をクリアー」ボタンをタップした時の動作の設定。全てのTextBoxの入力欄をブランクにする。

3. 「入力チェック」ボタンをタップした時の動作の設定。

リスト型の変数tagListを設定し(念のため初期化しておく)、関数getTagListを実行する

関数tagListの実行内容

所定のURLのサブディレクトリー (NewProverb)にデータを保存した場合、以下サンプルデータのように各データごとにunique IDが与えられる。削除、更新等の際に各データを識別する場合に使用。

           

このIDのリストを取得するためには、所定のURLの末尾に ”?shallow=true" を付加すれば自動的にリストを取得できる。shallowについては、Firebase REST APIのページにも簡単な説明があるが、METRIC RAT AI2 の Firebase Demo: No Security with Web Component の GET(TAGS)の項目がわかりやすい。(以前の説明と同じ)

そして、このURLに対しGETリクエストを行う。

取得したサンプルデータは以下の通りで、これをデコードし、「get keys」componentでキーの値(ID)のみを取り出しtagListに格納。

{

  "-OAbncQpTSsdpqufxGj7": true,

  "-OAbpeo1tGyoMYLjfsIf": true

}

内容をListView (checkAddedDataListview) に表示。(とりあえず、追加したデータの分だけではなく、全てのIDを表示させている)

4. 右上端の backButton をタップした時の動作

メインスクリーンであるScreen1へ戻る。その時、startValueとして"fromAddScreen"を返す。

startValueとして"fromAddScreen"を受け取ったメインスクリーンでは、再度「追加」ボタンをタップした場合、管理者パスワードの再入力は不要となる。

なお、メインスクリーンの管理者パスワードの再入力が不要となる部分のブロック・コードは以下の通り。

「追加」ボタンをタップした時、遷移元より返される値(get start value)として"fromAddScreen" が返されていなければパスワード入力が促される。 "fromAddScreen" であればパスワードなしでAddScreenへ遷移できる。

初めて「追加」ボタンをタップした時は、当然、遷移元はないので get start value は null となり、パスワードの入力が必要となる。

                           *************************************************************************

今回も、Firebase側で、新規設定のサブディレクトリー(NewProverb)に対するアクセス権限設定を忘れたため、何度試みてもデータの保存ができず(アクセスできず)、四苦八苦した場面があった。(歳のせいか、すぐ忘れてしまう。。。もうすぐ76歳か〜!)

                           *************************************************************************