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

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

MIT App Inventor 2で遊ぶ (インディアンポーカー 1)

2025-01-22 06:46:24 | 日記

インディアン・ポーカーとは?

このYouTubeを見るのが早いと思う。=> 「 Indian Poker Card Game Rules

スマホのアプリもあるらしいが、今回は、MIT App Inventor 2で簡単なアプリを作ってみたい。

以前「ポーカー・ゲーム 1」でも使用した Deck of Cards API を利用。

アプリ実行のビデオ:

スクリーン・デザイン:

縦に長い画面なので2つに分けて表示。

                                                

ブロック・コード:

1. Screen1の初期化時に「カードを配る」ボタンを無効に設定

まず、「カードを受取る」ボタンをタップして、52枚のカードのIDを取得する必要があるため。IDが取得できたら、「カードを配る」ボタンをタップして、取得したIDをキーにして具体的なカード(今回の場合4枚ずつ)データを取得することになる。

したがって、「カードを配る」ボタンは、「カードを受取る」ボタンの後でタップする必要あり。

2. 1組のカードのIDを取得

変数URLForGettingCardIDに1組のカードのID等基本データを取得する先のURLを格納。

変数URLForGettingCardsに具体的なカード情報を取得する先のURLを格納。このURLに上記カードのID及び一回に受取るカードの枚数(今回の場合4枚)をパラメーターとして追加してデータを取得することになる。

カードのIDを格納する変数cardDeckIDを設定。

カードの基本データを格納する変数initialDeckDataを設定。

カードの基本データとは以下の通り。

{
   "success":true,
   "deck_id":"lcvavm0z0uma",
   "remaining":52,
   "shuffled":true
}

「カードを受取る」ボタンをタップした時の動作を設定。=>所定のURLに対しGETリクエストを実行。(なお、変数URLForGettingCardIDをすでに設定済みなので、URLの代わりに同変数をセットしてもOK。)

カードの基本データ(上記)取得に問題がなければ、デコードの上、変数initialDeckDataに格納。=>同データよりdeck_ID(1組のカードのID)を抽出して、変数cardDeckIDに格納。=>変数cardDeckIDが空白でなければ(正常にカードID取得に成功)「カードを配る」ボタンを有効に。

カードの基本データ取得に問題あれば、再度「カードを受取る」ボタンのタップを促すポップアップを表示。

 

3. 取得した1組のカードより具体的にカードを引き出す

取得したカードのデータを格納する変数obtainedCards_Dataを設定。

取得したカードのデータ(サンプル)とは以下の通り。カードは4枚ずつ引き出すが、以下は最初の1枚目のカードの内容。52枚のカードより4枚引き出したので、残りの枚数が48枚となっている("remaining":48)。

{
   "success":true,
   "deck_id":"lcvavm0z0uma",
   "cards":[
      {
         "code":"5S",
         "image":"https://deckofcardsapi.com/static/img/5S.png",
         "images":{
            "svg":"https://deckofcardsapi.com/static/img/5S.svg",
            "png":"https://deckofcardsapi.com/static/img/5S.png"
         },
         "value":"5",
         "suit":"SPADES"
      },

...            ********** 省略 **********

   ],
   "remaining":48
}

変数myCardImage:取得したカードの内、「自分」用カード(4枚目のカード)の図柄のURLを格納。

カードのIDをパラメーターとして所定のURLにセットすると共に、一度に引き出すカードの枚数を4(count=4)にセットし、GETリクエストを実行。

「カードを受取る」ボタンは無効に設定。

取得したカードのデータをデコードした上で、関数initCardsAndImagesList および 関数makeCardsList を実行する。

関数makeCardsList実行の結果取得するcardsImagesURLList(カード図柄)のindex1〜3を、相手1、相手2、相手3のカードに表示する。

ただし、「自分」については、trumpCardBack1.png(カードの裏の図柄)をセットし、カードの図柄 (index4) のURLは、変数myCardImageURLにセットしておく。(相手1〜3のカードは表示されるが、「自分」に配られたカードが何かはまだわからない)

関数initCardsAndImagesList:カード及びカードの図柄イメージが保存されているURLリストなどが格納される変数を初期化する。

関数makeCardsList:取得した4枚のカードの図柄が保存されているURLを抽出し、そのリストを変数cardsImageURLListに格納。=>カードの情報の内、 "code"をキーにしているカードの手 "5S"(スペードの5)を変数cardsListに4枚分格納。ただし、カードの数字が 10 の場合は "0S"となるので、これを "10S" に変更して格納。なお、この変数cardsListは今回のブログでは使用しない。

関数convert0To10:関数の名前がちょっと紛らわしいが、取得したカードのデータのうち"code"の値を取り出す関数

「勝負!」ボタン (showMineButton) をタップした時の動作=>ここで初めて自分のカードの図柄が表示される。

「おりる」ボタン (foldButton)をタップした時の動作=>このボタンをタップして時には、自分のカードは表示されず、現在使っているカードを引き続き使っていくか、新しいカードを受取るかの選択を促すポップアップが表示される。

「このカードで遊ぶ」が選択された時は、「カードを配る」ボタンをタップするよう促すポップアップが表示される。

「新しいカードで遊ぶ」が選択された時は、「カードを受取る」ボタンを有効にして、「カードを配る」ボタンは無効となる。

ポップアップの表示が多くUX (User eXperience) 的にはスッキリとした感じに欠ける気がする。また、52枚のカードをすべて配り終えた場合の対応がまだできていない。

なお、testLabel1〜testLabel3のcomponentsがあるが、これらは、データが正しく取得できているか確認するためのもので、アプリ実行時には非表示とした。

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

以前アップした類似ゲーム:

MIT App Inventorで遊ぶ (ポーカーゲーム 1)

 


MIT App Inventor 2でもできるかやってみた  (Collection of Small Apps 1)

2025-01-16 07:56:10 | 日記

YouTubeにあった 「9 HOURS of Python Projects - From Beginner to Advanced」 をMIT App Inventor 2でできるのかやってみた。

今回は、略語が何を表しているのかを答える簡単なアプリと、思いきや、ちょっと手こずった。

アプリ実行のビデオ:

スクリーン・デザイン:

左端:初期画面 中央:初期画面で「1」をタップした時に遷移する画面 右端:中央の画面を上方向にスクロールした画面

今回は、「1」をタプした時が対象。

           

ブロック・コード:

スクリーン・デザインで表示している初期画面の部分=>

今回は、5つの Vertical Arrangements (mainScreenVA + subScreen1VA1 〜 subScreen1VA4) で Screen1 が構成されている。mainScreenVAは上記初期画面となる。今回のブログの対象はsubScreen1VA1。

Screen1の初期化時に、関数makeVAVisibleにパラメーターとして「home」を渡し実行され、mainScreenVAのみが表示される。

関数makeVAVisible:受け取るパラメータの内容により、表示するVertical Arrangementを選択し表示する。

画面の最下部に配置されている homeButton (家のアイコン)及び各ボタンがタップされたときに、該当のVertical Arrangementをパラメーターとして関数makeVAVisible に渡し表示させる。今回は、item1Buttonをタップした時のみが対象。以下item2Button〜item4Buttonは次回以降に動作等を追加。

item1Button をタップした時の動作=>

変数abbrevDictの設定。使用するデータをdictionary形式であらかじめ格納。Firebase Realtime DBなどに格納し、アプリ上からデータの追加・訂正・削除などができるようにすれば便利かもしれないが、今回は必要なデータをアプリに同梱。

key => 略語

value => 3つのデータ(略語に対応するフルテキスト、詳細な説明があるウエッブサイトのURL、簡単な略語の説明)をリスト形式で設定。

上の画像では見にくいので、例として「HTTPS」を拡大表示すると以下の通り。

略語(abbrevList)、略語のフルテキスト(abbrevInFullTextList)、ウエッブサイトのURL(wikiSiteList)、簡単な説明(abbrevMeaningList)をそれぞれリスト形式で格納するための変数を設定。

また、略語データの件数 (abbrevListLength) と問題をランダムに選択する際使用する乱数 (randomNumber) を格納する変数を設定。

初期画面でボタン「1」をタップした時の動作を設定=>

略語クイズ画面の「スタート」ボタンの表示を「スタート」に設定(1回目以降の表示は「次の問題へ」となる)

関数makeVAVisibleにパラメーター「1VA1」を渡して実行。この結果、初期画面(mainScreenVA)が非表示となり、略語クイズ画面(subScreen1VA1) が表示される。

さらに、関数makeListsを実行し、上記変数にデータをセットする。また、「正誤の確認」ボタンは一時無効にする。

関数makeLists:Dictionary形式のデータのvaluesをlist形式で抽出し、項目ごとにそれぞれのデータをlist形式で変数に格納。

変数selectedAbbrevはランダムに選択された略語を格納

略語クイズの画面で「スタート」ボタン (start1Button) をタップした時の動作を設定=>

念の為、問題の略語を表示するLabel、回答を記入するTextboxおよび結果を表示するTextBoxを空白で初期化。

1からデータの個数までの数字よりランダムな数字を生成してrandomNumberに格納。

略語リストよりindexがrandomNumberに該当する略語をselectedAbbrevにセット。

問題の略語を表示するabbreviationInQuestionLabelにselectedAbbrevに格納されている略語を表示。

「正誤の確認」ボタンを有効に。

関数clearVarsVA1:変数およびLabel/TextBoxを初期化する関数

「正誤の確認」ボタン (checkButton1)の動作を設定=>

回答を入力するanswerTextbox1に何らかの入力があった場合 >> もし、入力された回答が、略語のフルテキスト・リストの該当するフルテキストを同じであれば(問題の略語を抽出したときに使用したrandomNumberをindexとして使用)、 >> 結果を表示するresultTextBox1に「正解です」+略語の意味を表示。(なお、Labelの代わりにTextBoxを使用することにより複数行の表示が可能となる)>> 「スタート」ボタンの表示を「次の問題へ」に変更する >> 正解ではない場合は、「再度入力」か「次の問題へ」のいずれかの選択を促すポップアップを表示

上記ポップアップにていずれか(「再度入力」あるいは「次の問題へ」)を選択した場合の動作=>

キーボードの表示・非表示などがコントロールできるextension 「pl.extension.Keyboard.aix」を利用した。

「再度入力」を選択した場合は、キーボードを表示して、カーソルを回答欄にセット。

「次の問題へ」を選択した場合は、「スタート」ボタンの表示を「次の問題へ」に変更し、回答欄と問題欄は空白にセット。

お手本のYouTubeビデオ「9 HOURS of Python Projects - From Beginner to Advanced」の#1 - Quiz Game (Easy) をMIT App Inventor2 でやってみようとしたのだが。。。お手本ビデオだとterminalに入力、出力を行い非常に簡単に仕上げている。

同じようにはいかないが、もう少し簡単に作ってみたい。(多分、素人コーディングなので、必要以上にややこしくなっているのではと思う。)

改善すべき点としては、同じ略語が続けて出ないようにしたい。

 

 


MIT App Inventor 2で遊ぶ (Weather App New 5)

2025-01-10 20:20:13 | 日記

最高・最低気温、日の出・日の入時間、湿度を表示。ブロック・コード的には、復習。特別目新しい事項はないが、関数実行の順序などで勘違いし解決するのに随分時間を使った。(例えば、変数Aに値を設定する関数A-funcが実行される前に変数Aを使うなど、初心者がよくやる行き当たりばったりのコーディングからくる間違い。)

日の出・日の入時間については、以前と同様、time zoneによる補正を行った。日付 (date) についても、一応補正を行った。実質的には何も変わらないが。

アプリ実行のビデオ:

スクリーン・デザイン:

変更点は、右上端に配置していた日の出・日の入時間の表示ボタンを削除したこと。

                                     

ブロック・コード:

最高・最低気温、日の出・日の入時間、湿度を表示する部分のみを要約の形で。

1. デコードする前のDBより取得したJSONデータは以下の通り(最初の関係する部分のみ)。単位は、時間・日付はUnix Time、温度は°C、湿度は、%。

                               

=>該当都市のtime zone(GMTとの時差)を取得し、変数targetCityTimeZoneに格納

=>日の出、日の入時間を取得し、7日間のデータを変数sunriseTimeListおよび変数sunsetTimeList(省略)に格納。

関数getSunriseDate(赤黄点線内):取得した日の出時間 (Unix Time)をHH:mmフォーマットに変換する前に、(日の出時間 (Unix Time) + time zone) - 32400 を計算して補正の上、1000倍(MIT App Inventor2が扱うミリ秒へ換算)してからフォーマットしている。

なお、今回、同様の補正を日付に対しても行った。

=>最低・最高気温を取得

キー、値を順番に辿って7日間のデータを取得し、変数maxTempListおよび変数minTempListに格納

=>湿度を取得

キー、値を順番に辿って7日間のデータを取得し、変数humidityListに格納

2. 日本語と英語の切り替え機能を備えているので、見出しなどを日英両言語でリスト形式であらかじめ設定した。

変数sunriseLabelおよび変数sunsetLabel(後者は省略)

変数maxTempLabelおよび変数minTempLabel(後者は省略)

変数humidityLabel

3. 上記1.のデータと2.の見出しを、選択された言語に応じListViewに表示。

ListView1に表示するデータは、「call ListView1.CreateElement」ブロックを利用するのが便利。データの挿入口は3つあるが、その内 detailText「サブテキスト」に取得したデータを挿入。

スクリーンでそれぞれのデータを見ると以下の通り。今回追加したのは、サブテキストの部分。

実際のブロック(最高気温の部分のみ、他のデータはこの下に続く)を見ると、以下のように選択された言語に応じ、ラベルをピックアップしデータと結合して表示する。

                                            *********************以下続くが省略*********************                           

\nは改行マークだが、MIT App Inventor2 の場合、この改行マークではなくHTMLの br を使用しないと改行しない場合がある。この場合分けの基準は不明、と言うか私が知らないだけと思う。

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

前回までのブログ:

MIT App Inventor 2で遊ぶ (Weather App New 4)

MIT App Inventor 2で遊ぶ (Weather App New 3)

MIT App Inventor 2で遊ぶ (Weather App New 2)

MIT App Inventor 2で遊ぶ (Weather App New 1)


MIT App Inventor 2でもできるかやってみた  (Convert a number to words 1)

2025-01-07 18:07:10 | 日記

YouTubeやX上では、いろいろなプログラミング言語のチュートリアル(1分未満から数十時間まで)がある。

そんな中で、Xに、Python Codingというアカウントがあり、「入力した数字を文字に変換する」というコードの紹介があった。Python自体全くわかっていないが、グーグル先生もいるので見よう見まねでMIT App Inventor2 で可能かやってみた。

入力する数字が1000未満まで対応できるようになったが、これ以上は根気が続かずギブアップ。

また、今回は、Xの記事内容に沿ってMIT App Inventor2で再現しようとしたが、記事の内容にとらわれることなくブロック・コードを考えたらどうなるのか、機会があれば考えてみたい。

アプリ実行のビデオ:

スクリーン・デザイン:

                                                             

ブロック・コード:

変数units:数字が20未満の場合の対応する文字をリストにまとめたもの

変数tens:20より10ずつ増加していく数字の対応する文字をリストにまとめたもの

スクリーンの初期化の際にリストの内容を変数に格納。(Python Codingの記事の通りに設定)

なお、変数tensのindex 1および2は、変数unitsで対応済みのzeroとtenに相当するものなので空白文字。

変換ボタン「Convert」をタップした時の動作を設定。

=>入力した数字に対応する文字を表示するLabelを配置しているHorizontalArrangement5の背景色をピンクに設定。

=>数字を文字に変換する関数convertToWords(パラメーターとして入力された数字を受取る)を実行。

消去ボタン「Clear」の動作を設定=>clear関数の実行=>キーボードを非表示とする

関数clearの機能を設定

=>入力用TextBoxおより数字に対応する文字を表示するLabelに空白を設定して初期化=>HorizontalArrangenment5の背景色を白色に設定して初期化=>変数onesPlace(1のくらいの数字を格納)及び変数tensPlace(10の位の数字を格納)に0を設定して初期化

変数onesPlace(1のくらいの数字を格納)及び変数tensPlace(10の位の数字を格納)を設定(0で初期化)

関数convertToWords:

パラメーターとして受け取る入力数字(num)が20未満の場合=>変数unitsのリスト中から、indexが入力数字+1の文字を取り出しLabelに表示する。unitsのリストは「zero」から始まるので1を加算する。例えば、入力された数字が「1」の場合、「one」はindexで言えば「2」となる。

   14を入力=>20未満の数字=>unitsリストのindexが15(14+1)の文字 (fourteen) を表示

数字(num)が100未満の場合(20から99まで)=>入力された数字を10で除算した余りが0の場合は、1位の数字が0なので、変数tensのリストより10で除算した商の値+1をindexとして当該の文字を表示。=>余りが0でない場合は、さらに1位の数字に対する文字を取得する必要がある。変数unitsのリストから入力された数字を10で除算した余り+1をindexとして文字を取得し、それぞれjoinブロックで結合して表示する。

   40を入力=>20以上で100未満=>40/10 = 4 =>tensリストのindexが5 (4+1) の文字(forty) を表示。

   68を入力=>20以上で100未満=>67/10 = 6 余り 8=>tensリストのindexが7 (6+1) の文字(sixty)と

                   unitsリストのindexが9 (8+1) の文字(eight)を” ”を挿入して結合の上、

                   文字 (sixty eight) を表示。

数字(num)が1000未満の場合(100から999まで)=>上記と同じ考えで数字に対応する文字をリストより取得して、joinブロックで結合して表示する。

説明がまどろっこしいため意味不明かもしれないが。。。

最後に、1000以上の数字を入力した場合は、入力数字は1000未満とするよう促すポップアップを表示する。

Pythonでは、//という演算子を使えば、除算の商を取得することができるらしいが、MIT App Inventor2にはそのような演算子は見当たらないので floor ブロックを代用した。また、Pythonのように関数を自分の関数内でコールする方法がわからなかった(できない?)ので、回りくどいブロック・コードとなった。

このブロック・コードが正しいかどうかはわからないが、一応当方が意図したようにアプリは動いてくれた。