08: 算数クイズ 1
この章の概略
-
LiveCodeの足し算、引き算、掛け算、割り算の小学校の算数との表記の違い。
-
「足し算クイズ」のインターフェイス、問題作り、解答合わせのスクリプト。
-
簡単なダイアログ・ボックス。
30年程前までは、コンピュータの事を電子計算機と言っていたくらいですから、小学生程度のやさしい算数クイズを作ってみましょう。ただの計算機では面白みがないので、プログラミングで問題を作って、ユーザーの答えに対話(ダイアログ)で回答します。まだ前章までのスタック「helloWorld」を開いていたら、「Fileメニュー > Close and Remove From Memory」を選びます。スタックのウインドウを閉じただけでは、LiveCodeの中に、スタックのメモリーが残ったままになってしまいますから、メモリーも同時に削除します。
足し算、引き算の表記
足し算はプラス記号(+)引き算はマイナス記号(-)を使うのは、普通の算数と同じです。簡単な計算をやってみましょう。1行づつメッセージ・ボックスで試してください。
2 + 3
100 + 200
65 - 30
300 - (380 -100)
普通の算数と同じように答えの数字が返されます。カッコがあるとその中が始めに計算されるのも同じです。では次に答えもある式を書いてみます。
2 + 3 = 5
100 + 200 = 330
65 - 30 = 35
300 - (380 -100) = -180
イコール記号の使い方も、普通の算数の表記と同じです。上から「true」「false」「true」「false」と返されます。書いてある行が、式として成り立っているかを「真偽」で答えますと言っても良いし、答えが正しいか間違っているか、と言う言い方でももちろん良いです。イコール記号(=)は、普通の英語の文の「is」にも書き換える事ができます。「is not」と言う表現もできますが、話がややこしくなるので、ここでサンプルを書くのはやめておきます。
2 + 3 is 5
100 + 200 is 330
65 - 30 is 35
300 - (380 -100) is -180
読みやすいように始めの計算部分をカッコで囲っても同じ回答が得られます。
(2 + 3) is 5
(100 + 200) = 330
(65 - 30) = 35
(300 - (380 -100)) is -180
少数も同じに計算できますが、少数点第7位の結果は四捨五入されます。別な言葉で言えば、少数点第7位までの計算をします(ただし答えは第6位までです)。
3.14159265 + 20
少数点第7位が四捨五入されて 23.141593 が返されます。
「足し算クイズ」のインターフェイス作成
新しいメイン・スタックをメニューから作ります(Fileメニュー > New Mainstack)。スタックの名前は「sansuu」にしましょうか。ツール・パレットのテキスト・フィールドから「Text Entry Field」をひとつ、カード上にドラッグ&ドロップします。文章をタイプする普通のテキスト・フィールドです。マウスをツール・パレットに持って行くと、「Text Entry Field」と書かれた、黄色のツール・チップが出てきます。フィールドのデフォルトのフォント・サイズは11ポイントですから、大きなフォントが入るように、フィールドの天地を少し伸ばします。フィールドのプロパティ・インスペクタを開けて、ベーシック・プロパティ(Basic Properties)で名前は「number1」とします。「Don't Wrap(改行しない)」をチェック(true)して、18ポイントのテキストを入れる予定ですから、天地がちょうど良いアキになるよう「Text height(行間)」を「20」ポイントにしてください。プロパティ・インスペクタの「Text Formatting」の「Size」はデフォルトのフォント・サイズ(11ポイント)で空白になっていますから「18」ポイントにします。「Font」がデフォルトで空白になっているのは、OSのシステム・フォントです。デフォルトのフォント名は、Mac OSでは「Lucinda Grande」、Windowsでは「Segoe UI」です。
同じプロパティのテキスト・フィールドをあと2つ、オプションキーを押しながらドラッグしてコピーを作ります。名前は「number2」と「tAnswer1」にします。ツール・パレットからテキスト・フィールドの「Label」をドラッグ&ドロップして、フィールド「number1」と同じフォント・サイズ、テキスト・ハイトにして、「Text Formatting」の「Align」はセンターにします。このフィールドは直接ブラウズ・ツールでタイプできないので、プロパティ・インスペクタの「Contents」を開いて「プラス記号」をタイプします(下図)。「プラス記号」のフィールドをもうひとつ、Mac OSなら オプション・キー + ドラッグ&ドロップ(Windowsはオルト・キー + ドラッグ&ドロップ)でコピーを作って、今度は「イコール記号」にします。
5つのテキスト・フィールドを下図のように適当な間隔で配置したら(スタックの横巾も適当に広げてください)、全部をポインター・ツールでセレクトして、インスペクターの「Align Objects」で高さを揃えて、きちんと横に並んでいるようにアラインします(下図)。
フィールド「number1」と「number2」をセレクトして、「Basic Properties」の「Lock text」を「true(チェックする)」、「Focusable」を「false(チェックを外す)」にセットします(下図)。この設定で「number」の2つのフィールドにはユーザーはタイプできなくなって、「tAnswer1」にだけタイプできるようになります。
ランダム「random」に数字を選ぶ
日本語でもランダムと言う言葉は使うので、だいたい予測はつくと思います。「the random of 上限の数字」で数字が「10」でしたら、「1から10までの数」から無作為に数字が返されます。例によってメッセージ・ボックスでやってみましょう。
put the random of 10
1から10までの数字を無作為に選んで返しなさい。
上限がそう大きくないので、何度か同じ数字が返される事もあります。今はできるだけ日常英語のような表現を使っていますが、だいぶLiveCodeに慣れて来ると、この後の章で出て来るファンクションのような表記にしたくなる人達もいるので、上限の数字をカッコに入れるだけでも同じ意味にできるようになっています。
put random(10)
1から10までの数字を無作為に選んで返しなさい。
(これも上で書いた「random」の表現とまったく同じ意味です)
ランダムに数字を発生させて、それをテキスト・フィールドに入れて問題とします。その為のボタンを作ります。ツール・パレットのボタンから四角い「Rectangle Button」をカード上に置いて、名前(name)は「question1」、レイベル(label)は日本語で「問題を作る」にします(下図)。ボタンの「Name」は、スクリプト中で使うので日本語にできませんが、これから使うこのボタンの「Label」は表示だけですから、インスペクタで日本語のレイベルに設定しても問題ありません。
ボタン名「question1」のスクリプト・エディターを開きます。ボタン名「question1」をエディット・ツールでセレクトしたら、アイコン・メニューの「Code」をクリックするか、コンテキスト・メニューから「Edit Script」。またはそれ以外の方法でも良いです。ボタンのエディターには「マウスアップ・ハンドラー」が既に用意されています。
on mouseUp
put the random of 100 into field "number1"
put the random of 100 into field "number2"
put empty into field "tAnswer1"
end mouseUp
スクリプト・エディターは書いてある内容が読みやすいように、
ハンドラーの中の行の頭に空白(インデント)を取るようになっていますが、
もしインデントがうまく表示されていないようでしたら、
行のどこかにカーソルを入れて「タブ・キー」を叩きます。
始めの2行は上に説明があるように、1から100までの数字をランダムに作り出して、ふたつのテキスト・フィールドに入れます。3行目にある「empty」は「空っぽ」と言う意味の英語ですから、テキスト・フィールド「field "tAnswer1"」にあるすべてを消して、空っぽをフィールドに入れます(つまり消し去ります)。上では「empty」と書いていますが、ダブル・クオートだけの中身の何もないストリング「""」でも同じです。
put "" into field "tAnswer1"
答えが正しいかどうか調べるボタンを作る前に、正しい解答を得る方法をマルチライン・メッセージ・ボックスで見てみます。
put field "number1" into tNumber1
put field "number2" into tNumber2
put field "tAnswer1" into tAnswer1
put tNumber1 & return & tNumber2 & return & tAnswer1
上記をマルチライン・メッセージに書いたら、エンター・キーを叩きます(またはコントロール・キー + リターン・キー)。フィールドにある各数字を、前章で説明したバリアブル(tNumber1, tNumber2, tAnswer1)に入れて、その3つのバリアブル(variable)をメッセージ・ボックスに3行で書き出しています。
バリアブルは、毎回違う数字や文字列などの値を、一時的に収納する器(文字列)です。
数字で始まる文字列にはできません。「&」が入っている文字列は使えません。
スペースを挟んだ1語以上の文字列は使えません。日本語の文字は使えません。
put tNumber1 + tNumber2 = tAnswer1
始めに普通の算数式で説明したように、上のこのスクリプトが「true 真」ならば、答えは正しく、「false 偽」ならば間違っています。マルチライン・メッセージに書き込んだ最後の行を、これに入れ替えてみます。
put field "number1" into tNumber1
put field "number2" into tNumber2
put field "tAnswer1" into tAnswer1
put tNumber1 + tNumber2 = tAnswer1
これで「true」が返されれば答えは正しく、「false」が返されたら間違った答えと言う事になります。この正しいか違っているかを、これも前章で学んだ条件の「if ... then」で判断すれば良い訳です。その部分を書いてみましょう。
if tNumber1 + tNumber2 = tAnswer1 is true then
put "Very Good."
else
put "Sorry."
end if
メッセージ・ボックスからはこれくらいにして、ボタンを作ってその中にスクリプトを書いて行きます。ボタン「question1」と同じ「Rectangel Button」を作ります。名前(Name)は「tAnswer1」、レイベル(Label)は「答えは?」にします(下図)。
上のメッセージ・ボックスで試した「if条件文」では、丁寧な言い方をして「tNumber1 + tNumber2 = tAnswer1 is true」と書いていますが、「true」と言う前提の文では「is true」を省いて書く事もできます。それでは「answer」を使ってユーザーと対話できるようにします。「answer」はダイアログ・ボックスでユーザーと対話形式のやり取りができるコマンドです。ここでは「OK」だけの回答にしますが、幾つかの選択を用意することもできます。日本語のダイアログも書けますが、もう少し学習のステップを踏んでからの方が良いので、今は英語にします。それから間違っていた場合にビープ音を鳴らすように、「beep」も入れる事にしましょう。以下を今作ったボタン「tAnswer1」の中に書き込みます。
on mouseUp
put field "number1" into tNumber1
put field "number2" into tNumber2
put field "tAnswer1" into tAnswer1
if tNumber1 + tNumber2 = tAnswer1 then
answer "Very Good!"
else
beep
answer "Sorry."
end if
end mouseUp
数字かどうかを判断、リターン・キーを無効にする
これで「足し算クイズ」としての機能は完成ですが、アプリケーションとしてはユーザーがちょっとした間違いなどをするといけないので、その対策が必要です。ひとつは解答欄に数字以外の文字を打ち込むかもしれません。もうひとつは解答欄でリターン・キーを叩くと複数行の答えになってしまいます。
解答欄にある文字列が数字かどうかと言う判断は「isNumber」を使います。これは正しい意味で英語ではありませんが、ニュアンスとして「これって数字?」と言う感じでしょうか。「isNumber」は、LiveCodeに類似する他の日常英語のようなプログラミング言語、SuperTalkでも使われています。では実際に使ってみましょう。下の2行はどちらも同じ意味です。
put the isNumber of field "tAnswer1"
put isNumber(field "tAnswer1")
『フィールド「tAnswer1」って数字なの?』の真偽を返しなさい。
(2行目は、randomのようにカッコを使う方法で書いています)
まず始めに、答えのフィールドが数字でなければ、そこでもうプログラミングを進める意味がないので、その時点で「mouseUpハンドラー」から抜けるように、ボタン「tAnswer1」のスクリプトを書き換えます。「isNumber」と「answer」と、もうひとつ新しいことば「exit mouseUp」を使います。「exit mouseUp」は実行をその時点で中止して、「mouseUpハンドラー」から抜ける意味です。
on mouseUp
put field "tAnswer1" into tAnswer1
if isNumber(tAnswer1) is false then
beep
answer "Your answer is not a number."
select the text of field "tAnswer1"
exit mouseUp
end if
put field "number1" into tNumber1
put field "number2" into tNumber2
if tNumber1 + tNumber2 = tAnswer1 then
answer "Very Good! You are a Genius."
else
beep
answer "Sorry, Wrong Answer."
end if
end mouseUp
一番始めにフィールド「tAnswer1」の答えをバリアブル「tAnswer1」に入れます。もしそれが数字でなかったら(「if」に書かれた条件が「false 偽」だったら)ビープ音を鳴らし、アンサー・ダイアログでその内容を表示して、すぐに正しい答えに書き換えられるよう、解答欄の文字列をハイライトにセレクトして(select the text of field "tAnswer1")、「mouseUpハンドラー」から抜けます。バリアブル「tAnswer1」が数字で、if文が「false」でなかったら、「if」の中に書かれた文は実行されないで、その後の行が実行されます。
もうひとつの問題点、もしフィールド「tAnswer1」の中でリターン・キーが叩かれたら、フィールドの1行目の文字列をそのままそっくり同じフィールドに入れる仕様にするか、すぐに答えのボタンがクリックされたようにする方法が考えられます。そっくり同じ文字列をフィールドに表示して、何も変わらないように見えるのは、下のスクリプト「returnInField」のハンドラーごと、フィールド「tAnswer1」に書き込みます。ここに書いてある「me」はオブジェクト自身の事、つまりフィールド「tAnswer1」と同じです。「returnInField」は、テキスト・フィールドのスクリプト・エディターに書かれるメッセージ・ハンドラーで、そのフィールド内でリターンが行われると「returnInField」のスクリプトが実行されます。「mouseUp」ハンドラーと同じように「on」で始まって「end」の行で終わります。
on returnInField
put line 1 of me into me
end returnInField
put line 1 of field "tAnswer1" into feild "tAnswer1"
(「me」を書き換えた同じ表現)
もうひとつの方法、答えのボタンがクリックされたようにするには、やはりフィールド「tAnswer1」の中に「returnInField」のハンドラーを書いて、 button "tAnswer1" にマウスアップ(mouseUp)を送れば、ボタンをクリックしたのと同じ結果が得られます。
on returnInField
send mouseUp to button "tAnswer1"
end returnInField
マウスアップをボタン名「tAnswer1」に送りなさい。
他にも対処の方法があるかもしれませんが、ここではリターンが押された後、ボタン「答えは?」にマウスアップが送られる方を使う事にします。フィールド「tAnswer1」の中に、上のスクリプトをペーストして「Apply」します。
掛け算、割り算の表記
掛け算の表記は、普通に小学校で習う算数とはちょっと違っています。例えば「2 x 4 = 8」とタイプすると、掛ける記号がアルファベットの「x」と紛らわしいと言う事がありますから「* アスタリスク(星印)」を掛ける記号に使って、下のように表記します。
put 2 * 4
put 3 * 6 = 24
put 10 * (2 + 4)
上から「8」、「false」、「60」が返されます。
割り算の表記も、やはり小学校の算数とは違っていて、LiveCodeでは、割り算の記号に「div」か「/」(スラッシュ)を使います。「div」は「divide(割り算する)」から来ている省略形かと思います。LiveCodeには別に「divide」と言う言葉(コマンド)もあって、少し使い方の違いがありますから、短縮形だと混同しないでください。「div」は割り算記号と考えます。「/」は分数にする記号と考えるのが良いかと思います。LiveCodeの言葉では、足し算、引き算、掛け算、割り算で使う、こう言う記号を「operator オペレイター」と言います。
同じ割り算記号でも「div」と「/」の、二つの結果には違いがあります。「div」は、結果がプラスの場合でもマイナスの場合でも、小数点以下を切り捨てます。またはいつも整数(integer インテジャー)を返すとも言えます。「/」は小数点第7位を四捨五入して、小数点第6位までの解答をします。文章で書くと面倒そうですが、下のスクリプトを見れば、違いがすぐ分かります。
put 29 div 3
put 29 / 3
上は「9」。下は「9.666667」が返されます。
デフォルトの小数点の単位(ナンバー・フォーマット numberFormat)は第6位ですが、いつもいつも小数点第6位までの必要もない事が多いでの、「numberFormat」で小数点第何位まで必要か、あらかじめ決めておけます。「numberFormat」のこの設定はハンドラーを抜けると、デフォルトに戻ります。
set the numberFormat to "0.##"
put 29 / 3
これで小数点第3位が四捨五入されて「9.67」が返されます。
もっと小数点以下が必要だったら、シャープ記号の数を増やします。"0.####"
もうひとつ割り算の余りを返す「mod」を書いておきましょう。「div」を使っているといつも整数が返ってくるので、時々余りが幾つか必要なことがあります。
put 29 mod 3
「2」が返されます。(余りは2)
大雑把にLiveCodeの加減乗除について書いてきました。次の章ではもう少し「算数クイズ」を発展させます。もしこの章のスタック「sansuu」を保存してなかったら、Fileメニューから「Save」してください。
Tips
- スクリプト・エディターのインデント(行の頭にある空白)がうまく表示されていないようでしたら、ハンドラーの行のどこかにカーソルを入れて「タブ・キー」を叩きます。
- 計算式は読みやすいように、カッコで囲うことができます。
この章で新しく出て来た言葉
+ オペレイター(operator) 2つの数字を足す
put 2 + 3
put 100 + 200
- オペレイター(operator) ひとつの数から他の数を引く。負の数にする
60 - 30
300 - (380 - 100)
is オペレイター(operator)
2つの値を比べて等しいければ「true 真」、そうでなければ「false 偽」とする 同義語:=
(2 + 3) is 5
65 - 30 is 35
65 - 30 = 35
random ファンクション(function) 無作為に選んだ整数を返す
put the random of 10
put random(100)
empty コンスタント(constant) 何も値がない。"" は文字列に何も入っていない状態
put empty into field "tAnswer1"
put "" into tNumber
answer コマンド(command) ダイアログ・ボックスに、メッセージと判別を選べるボタンを出す
answer "Very Good!"
beep コマンド(command) システム・ビープを鳴らす
beep
isNumber ファンクション(function) 値が数字の場合はtrue、そうでなかったらfalseを返す
the isNumber of field "tAnswer1"
put isNumber(field "tAnswer1")
exit コントロール・ストラクチャー(control structure) ハンドラーの途中でストップする
exit mouseUp
select コマンド(command) テキストをセレクトする
select the text of field "tAnswer1"
returnInField メッセージ(message)
フィールド内でリターン・キーが叩かれた時、そのフィールドにメッセージを送る
send コマンド(command) メッセージをオブジェクトに送る
on returnInField
send mouseUp to button "tAnswer1"
end returnInField
me キーワード(keyword) 実行しているハンドラーのあるオブジェクト名に同じ
put line 1 of me into me
* オペレイター(operator) 2つの数を掛ける
put 2 * 4
put 3 * 6 = 24
div オペレイター(operator) ある数を他の数で割る。小数点は切り捨て、結果は整数
put 29 div 3
/ オペレイター(operator) ある数を他の数で割る。デフォルトで小数点第6位までの値を返す
put 29 / 3
numberFormat プロパティー(property) 小数点以下の位を特定する
set the numberFormat to "0.##"
mod オペレイター(operator) ある数を割ったあまり。この例では2
put 29 mod 3