プチコン3号講座 SMILE BASIC

NINTENDO 3DSのプチコン3号の使い方、プログラミング方法を紹介します。

2014年11月

数当てゲームを作ってみる

さて、これまでにいくつかの命令を覚えてきました。
画面に表示しなさい PRINT
何かを入力させなさい INPUT
繰り返し処理しなさい FOR
途中で繰り返しを抜けなさい BREAK
もしも~なら~しなさい IF
適当な数字を選びなさい RND
※わからない場合や、忘れている人は前のを読んでください。

これを組み合わせると、数当てゲームを作ることができます。

数当てゲームのルールをまず決めます。
それを仕様を考えるといいます。

数当てゲームといえど、ルールによって面白さが変わってきます。
どうすれば面白くなるか考えながらルールを考えていきます。

たとえば、1から99まで数を5回までに当てるということにします。
1回であたれば、「あなたてんさい!」と表示しましょう
2回であたれば、「すごい!」と表示しましょう。
3回であたったら「よくできました」と表示しましょう。
4回であたったら「まぁまぁかな」と表示しましょう。
5回であたったら「ふつうです」と表示しましょう。

正解しなかったら、「ざんねんでした答えは○○です」を表示しましょう。

そして外れるごとに、答えより大きかったか小さかったか教えて上げます。


では、命令形式で書いてみましょう。
変数NUMに5を入れなさい
変数SEIKAIFLGに0を入れなさい
変数ANSに0から98の乱数+1を入れなさい

"サンディ:わたしがあたまにおもいうかべた1から99のかずをあててね"を表示しなさい
変数Iに1から5まで1ずつ増やしながら次の処理を繰り返しなさい
  "かずをにゅうりょくしてください"を表示して入力させKAZUにいれなさい
  もし、KAZUとANSが同じ場合
    SEIKAIFLGに1を入れなさい
    もし、Iが1の場合
      "あなたてんさい!"を表示しなさい
    もし、Iが2の場合
      "すごい!"を表示しなさい
    もし、Iが3の場合
      "よくできました"を表示しなさい
    もし、Iが4の場合
      "まぁまぁかな"を表示しなさい
    もし、Iが5の場合
      "ふつうです"を表示しなさい
    判定終わり
    繰り返しから抜けなさい
  判定終わり

  もし、KAZUよりANSのほうが大きい場合
    "もっとおおきいですよ"を表示しなさい
  その他の場合
    "もっとちいさいですよ"を表示しなさい
  判定終わり
繰り返し終わり

もしSEIKAIFLGが0の場合
  "ざんねんでした、こたえはANSでした"を表示しなさい
判定終わり

では、プログラムを作って見ましょう
2014113001
2014113002

ANS=RND(99)+1
NUM=5
' せいかいのばあい1をいれる
SEIKAIFLG=0
PRINT "サンディ:わたしがあたまにおもいうかべた1から99のかずをあててね"

FOR I = 1 TO NUM
  INPUT "かずをにゅうりょくしてください";KAZU
  IF KAZU == ANS THEN
    SEIKAIFLG = 1
    IF I == 1 THEN
      PRINT "あなたてんさい!"
    ENDIF
    IF I == 2 THEN
      PRINT "すごい!"
    ENDIF
    IF I == 3 THEN
      PRINT "よくできました"
    ENDIF
    IF I == 4 THEN
      PRINT "まぁまぁかな"
    ENDIF
    IF I == 5 THEN
      PRINT "ふつうです"
    ENDIF
    BREAK
  ENDIF

  IF KAZU < ANS THEN
    PRINT "もっとおおきいですよ"
  ELSE
    PRINT "もっとちいさいですよ"
  ENDIF
NEXT I

IF SEIKAIFLG == 0 THEN
  PRINT "ざんねんでした。こたえは";ANS;"です。"
ENDIF

さて、実行してみましょう。

2014113003

正解したパターンも載せますね。

2014113004

ちなみに、今回IF文で1から5の判断をして文章を変えていますが、配列を使うともっとすっきりとした命令の仕方ができます。

次回、配列について学習しましょう。

繰り返しから抜けたり、戻ったりするには?BREAK CONTINUE

繰り返し処理をしていると、もう繰り返ししなくて次に進みたいとか、この値のときは処理させたくないということが出てきます。

たとえば、10日間単語を覚える勉強をするのですが、10個以上覚えた日は次の日勉強を休める。
そして、50個覚えたらもう勉強を終わりにしたい。

そういったことがあります。

では、これをプログラムにして見ましょう。
1日に単語を覚える数は乱数で1から20個とします。
10日間なので10回プログラムを繰り返します。
そして、10個以上覚えたときは次の日休みます。
50個を超えていたら、繰り返しから抜けます。

命令形式で書くと
変数KIKANに10を入れなさい
変数KIOKUに0を入れなさい
変数GOUKEIに0を入れなさい
変数Iに1から10までを1ずつ足して次の処理を繰り返しなさい
  もしKIOKUが10以上の場合、
    "Iにちめ:きょうは、やすみです"を表示しなさい
    KIOKOUに0を入れなさい
    繰り返しの頭に行きなさい
  判定終わり

  KIOKUに0から19までの乱数 + 1を入れなさい
  "Iにちめ:KIOKUのたんごをおぼえました"を表示しなさい

  GOUKEIにKIOKUを足しなさい
  もし、GOUKEIが50以上の場合、
    繰り返しを抜けなさい
  
判定終わり
繰り返し終わり

"GOUKEIこのたんごをおぼえて、おわりました"を表示しなさい。

さて、ここで緑色の文字で書かれた部分がまだ覚えていない命令です。

繰り返しの頭に行きなさいとは、この後の処理をせずに繰り返しの最初に戻る命令です。
繰り返しの最初に戻るといっても、数を戻すわけではありませんよ。処理の頭に戻って、1を加えてまた処理をします。

その命令はCONTINUEです。

繰り返しを抜けなさいは、FORの最大値にならなくても、繰り返し終わりを抜けて、処理します。
その命令はBREAKです。

では、プログラムを書いてみましょう。

2014112803


KIKAN=10
MAXTANGO=10
KIOKU=0
GOUKEI=0
MAXKIOKU=50
FOR I=1 TO KIKAN
  IF KIOKU >= MAXTANGO THEN
    PRINT I;"にちめ:きょうは、やすみます"
    KIOKU=0
    CONTINUE
  ENDIF

  KIOKU = RND(20) + 1
  PRINT I;"にちめ:";KIOKU;"このたんごを、おぼえました"
  GOUKEI = GOUKEI + KIOKU

  IF GOUKEI >= MAXKIOKU THEN
    BREAK
  ENDIF
NEXT I

PRINT GOUKEI;"このたんごをおぼえておわりました"

実行するとこうなります。
(乱数を使っているので表示は同じにはなりません)

2014112804


ちなみに、今回のテクニックとして、プログラムの最初に使う変数を初期化しています。
これは、最初の変数の初期値を変えることで条件を変えることができるからです。

たとえば20日にしたいならKIKAN=20
にすればよいし、
100個覚えるまでにしたいならMAXKIOKU=100
にします。

プログラムの途中で値を直接設定していたら、直すのに時間がかかってしまいます。
変数は最初に設定しておくと値の変更が楽なので皆さんもやってみましょう。

ここから余談

昔のBASICではプログラムを実行するときに変数が初期化されないため思いもよらないバグが発生することがあった。
たとえば
0001 PRINT A
というプログラムがあって、
RUNとすると
0
OKとなるのですが、
A=4
RUN
とすると、
4
OK
とプログラムに影響がありました。

SMILE BASICでは、RUN実行時に変数が初期化されるらしく、毎回0になります。

これはこれで、うれしいですが、初期値を外で設定してRUNしている人には思わぬ結果になるので注意が必要です。

適当な数字を選ぶには?RND RANDOMIZE

人生は選択の繰り返し、という話をしましたが、何かに決めるということは重要です。

しかし、たまには適当に選んだり、さいころを振ったりして何かを決めたりしますよね。

さいころの目は何が出るかわからない適当な数字です。

そんな自分が決めたわけではない適当な数字のことをランダムな数といったり乱数といったりします。

それをプログラムで使うことができます。

それはRNDです。

変数=RND([シードID,]最大値)

これを命令形でいってみると、
変数に0から最大値-1までの適当な値を1つ入れなさい。

となります。

ですから
R=RND(10)
としたら、0から9までのどれかの数字がRに入ります。

さて、ヘルプにもあるシードIDとはなんでしょうか?

ここからは、初心者の方には難しい話なので、■□の間の部分は読み飛ばしてもかまいません。

□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■
古いBASICの話をしなければなりません。

乱数は適当に数字を選んでるかのように思われますが、実はすでに決められた数字の羅列から場所を選び返しています。
どういうことでしょうか?

たとえば0から9だけにかぎっていうと
05327294638246723450982・・・
上のように数字の順番は決まっています。

シードというのは、こういった数字の並び順が決まったパターンのことを言います。

シード1:05327294638246723450982・・・
シード2:43598504723570286234598・・・
シード3:12908342543752348064323・・・
といったようにシードごとに数字の順番が決まっています。
(上のは例で実際の順番は異なります。)

シードIDを指定すると、どのシードを利用するかが変わります。

たとえば、
R=RND(1, 10)
とすれば、
シード1の1番目の数値0を返します。

R=RND(2, 10)
だと、シード2の1番目の数値4を返します。

昔のBASICでは、プログラムを実行すると、シードの1番目から順番に1つずつ返していくので同じ順番で値が返ります。

それを避けるのがRANDOMIZEという命令です。

RANDOMIZEは、この最初の位置をずらします。
RANDOMIZE シードID [,シード値]

シード値については、詳しい説明がないため私の予測ですが、最初の位置の指定だと思われます。
これを省略すると、時間によって開始位置が決まります。
シードIDは説明したとおり、どのパターンを使うかというところです。

ですので、昔のBASICでは
RANDOMIZE
R=RND(10)
PRINT R
とすることで、毎回異なる値が取れるようになりました。

SMILE BASICでは、試してみたところ、RANDOMIZEを使用しなくても、毎回違う値が取れるので命令としては存在するようですが書く必要はなさそうです。

追記:
ためしに
FOR I=1 TO 3
  RANDOMIZE 1, 6
  PRINT RND(1,10)
  PRINT RND(1,10)
  PRINT RND(1,10)
NEXT I
とすると
0
5
9
0
5
9
0
5
9
と同じ順番になります。

□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■

では、今まで覚えたことをフル活用して、3回さいころを振って出た目の合計を画面に表示するプログラムを作ってみましょう。

実践して試したい方は、自分で作ってみてから読んでください。

では、考え方から。
3回さいころを振るということは、繰り返しの命令を使うということがわかります。
合計しなければいけないということは、合計用の変数を用意します。

では、書いてみましょう。
以下の処理を3回くりかえしなさい。
 0から5の乱数を取得して1を足したものを変数Rに入れなさい。
 合計変数GOUKEIに変数Rの値を足しなさい。
 画面に変数Rの値を表示しなさい。
繰り返しの終了
画面にGOUKEIの値を表示しなさい。

となります。

PROGRAMにすると
2014112801

NUM=3
FOR intLoop=1 TO NUM
  R=RND(6)+1
  GOUKEI=GOUKEI+R
  PRINT R;"がでました"
NEXT intLoop

PRINT "ごうけいは";GOUKEI;"です"

実行すると、こうなります。

2014112802

さて、上のプログラムの合計を表示するだけなら

PRINT "ごうけいは";RND(6)+1+RND(6)+1+RND(6)+1;"です"
と1行だけでもできます。

でもこれだと、回数を増やすごと、文も長くなってしまいます。
FOR文を使うと、合計回数を書き換えるだけで、10回、100回と簡単に切り替えができます。

プログラムを作るときには、拡張性も考えて作るとよいでしょう。

同じことを繰り返すには?For文の使い方

毎日は、同じことの繰り返しと誰かが言っていますが、同じことだけだと退屈しますね。

とはいえ、プログラムの勉強も命令を何度も繰り返し使って覚えていくもの。

そんな、同じことを繰り返すような命令はあるのか?

それがFORです。

FOR ループ変数=初期値 TO 終了値 [STEP 増分]
  処理
NEXT

FORは「フォー」と呼びます。
HGという人が頭に浮かびましたが何の関係もありません。

TOは「トゥー」
STEPは「ステップ」
NEXTは「ネクスト」です。

ループ変数とは、同じことを繰り返すのに使う変数のこと。
よく iなんてのが使われます。

初期値は、始まりの値。
このとき、ループ変数に初期値が入ります。

終了値は終わりの値
STEP とは、1ずつ増やすのではなく、2つとかマイナスとか増減させたい数値を指定します。
その数が、増分になります。

処理を続行していき、NEXTまできたらFORのところまで戻ります。
ループ変数に増分(指定がない場合+1)を加え、終了値になるか超えるかしたらNEXTの後ろの処理に移動します。

では、例を書いてみましょう。

EDITモードで入力してみてください。

FOR intLoop = 0 TO 3 STEP 1
  PRINT intLoop;"にちめがすぎました"
NEXT intLoop

PRINT "そしてせかいがおわりました"

2014112701

intLoopというのはループに使う変数
BASICの世界ではI(英大文字のアイ)を使うのが一般的ですが、ここでは数値型でかつループに使う変数という意味になるintLoopという名前を使ってみました。
ちなみに変数名は、今までなんの断りもしなかったのですが、自由に好きな名前をつけることができます。
(ただし、命令と同じ名前やシステム変数と同じ名前は使用できません)

さて、続けて説明すると0から3になるまでNEXTまでいったら1ずつ足して繰り返しなさい
という意味になります。

ここで気になるのは3になるまで、というところです。
これは、3は含まれるのか含まれないのか気になりますね。

答えをいうと、含まれます。

最後にNEXT ですが、ここで、NEXTの後ろにintLoopというのを書いています。
実は、ここのintLoopは必要ありません。
しかし、FOR文の中にまたFOR文を書く場合など、どこまで繰り返すのかがNEXTだけだとわからなくなる場合があります。


FOR intLoopX= 0 TO 3 STEP1
  FOR intLoopY = 0 TO 3 STEP 1
    FOR intLoopZ = 0 TO 3 STEP 1
      PRINT "Z=";intLoopZ
    NEXT
    PRINT "Y=";intLoopY
  NEXT
  PRINT "X=";intLoopX
NEXT

そこで、NEXTの後ろにループ変数を書いておくと、範囲がわかりやすいので私は書くようにしています。

FOR intLoopX= 0 TO 3 STEP1
  FOR intLoopY = 0 TO 3 STEP 1
    FOR intLoopZ = 0 TO 3 STEP 1
      PRINT "Z=";intLoopZ
    NEXT intLoopZ
    PRINT "Y=";intLoopY
  NEXT intLoopY
  PRINT "X=";intLoopX
NEXT intLoopX

では、先ほど作ったプログラムを実行してみましょう。

2014112702

ちょっと日本語的におかしなメッセージのところもありますが、一応繰り返しできました。


では、後の注意点も書いていきましょう。

FOR intLoop = 4 TO 3 STEP 1
  PRINT intLoop;"にちめがすぎました"
NEXT intLoop

PRINT "そしてせかいがおわりました"

2014112703


さて、初期値が終了値より大きくなってしまいました。
これはどういう動きをするでしょう?

答えは
FORの中は処理されず、NEXTの後ろの処理が実行されます。

つまり、「そしてせかいがおわりました」だけ表示されます。

2014112704


続いて
FOR intLoop = 2 TO 3 STEP 2
  PRINT intLoop;"にちめがすぎました"
NEXT intLoop

PRINT "そしてせかいがおわりました"

2014112705

初期値が2で、終了値が3はいいのですが、増分が2になっています。
2で1回実行され、次に2足されるわけですから4になりますね。
そのとき、このFORの中は処理されるでしょうか?

結果は2だけ表示されます。
つまり、終了値を超えたらFORの中は処理されません。

2014112706


最後に
FOR intLoop = 3 TO 1 STEP -1
  PRINT intLoop;"にちめにもどりました"
NEXT intLoop

PRINT "そしてせかいがはじまりました"

2014112707


今回は初期値より終了値が大きいのですが、増分が-1になっています。

これはどういう動きをするでしょうか?

3からはじまって、1になるまで、1ずつ数を減らしていきます。

2014112708

カウントダウンなんかに使えますね。

では、後はあなたがプログラムを改良していろいろ試してみてください。

あなたの世界が始まります。

どちらか選ぶには?IF文

人生とは選ぶことと誰かが言っていました。

大学を選ぶとか、誰と付き合うか選ぶ。
そんな人生の大きな選択から、今日の夕ご飯に何を食べるか?
面白そうなドラマが重なってどちらを見ようなど、軽いものまでいろいろ選びます。

そんな、選択をプログラムでも行うことができます。
それがIFです。

IF 条件式 THEN 処理1 ELSE 処理2 ENDIF

といった具合に使います。

IFだけやないやないかーっとお怒りの方もいることでしょう。
しかし、これら、IFでは必要なものなので、一緒に覚えましょう。

IF これは、もしもという意味です。
条件式、というのは、たとえば
お金を5000円以上持っているか?
とか、年齢20歳以下じゃないといけません。
など、条件がありますよね。
その式ということです。

お金を5000円以上持っているか?
「お金 >= 5000」
これが条件式です。

年齢20歳以下
「年齢<=20」

なんとなくわかったでしょうか?

つづいて、THEN
これは「~だったら」といったニュアンスです。
条件式のとおりだったらこの次にかかれたことを実行します。

前の例だと、
お金を1万円持っていたとしたら、「お金>=5000」に合致するので
THENの後ろを実行します。

では、違っていたら?
それは ELSEです。
これは、「違っていたら」といったニュアンスです。


では、これを使って1つ書いてみますね。

IF お金>=10000 THEN PRINT "おかねもちですね" ELSE "びんぼうですね" ENDIF

これを日本語にすると
お金を10000円以上持っていたら「おかねもちですね」といって、
それより少ない場合は「びんぼうですね」という。

となります。 

ENDIFは、IFの終わり、ここまでという感じです。

なんとなく理解できたでしょうか?

でも、これをプログラムとどう結び付けるの?
という疑問がわきます。

では、NINTENDO 3DSに質問されたい。(使う人に何か入力させるには?)
で使用したINPUTと組み合わせてみましょう。

やることは、NINTENDO 3DSにあなたの名前を聞かせて、
名前がサンジだったら、「ヨンジのおとうとですね」
と返します。違う場合は前回どおり「てんし:○○さん、こんにちは!」と表示します。

これを、プログラムの命令っぽく書くと
1.「あなたのなまえは」と聞いて、NAME$という変数に入力した名前を入れなさい
2.もしも、NAME$がサンジだったら「ヨンジのおとうとですね」と表示しなさい
3・違う場合「てんし:」+NAME$+「さん、こんにちは!」と表示しなさい

さて、ここまで書けば、いままでの知識を生かしてプログラムを作れるでしょうか?
ちなみに「NAME$がサンジだったら」というところは条件式でかくと
「NAME$ == "サンジ"」
になります。

2014112601

EDITモードへの変更の仕方はダイレクトモードとエデイトモード
を読みましょう。

なおプログラムはIFの次の行に処理1を書いています。
しかも少し、頭がずれていますよね。
これはインデントといって、4文字分ずらしています。

この処理1がどこまで続くのかがインデントをすることでわかりやすくなります。

またELSEの後ろもインデントしています。
こちらも処理2がどこまで続くかがわかるようになっています。
(処理が続く場合インデントされた行が続きます。)

ひとつ例を書いてみましょう。
インデントなし
IF NAME$="AIUEO" THEN
A=5
B=6
PRINT "A=";A
ELSE
PRINT "B=";B
ENDIF

インデントあり
IF NAME$="AIUEO" THEN
  A=5
  B=6
  PRINT "A=";A
ELSE
  PRINT "B=";B
ENDIF

どうですか?
THENの処理1がどこまで続くかわかりやすくなっていませんか?


では、DIRECTモードに戻って実行してみましょう。

2014112602
2パターン試しました。

みなさんも、IFの条件式を変えていろいろ試して見ましょう。
最新コメント
カテゴリー