RGSS2の条件分岐についての質問

開拓者2017-12-04に開始した「ツクールVX/VXAce」の中の討論

  1. 開拓者

    開拓者 ユーザー

    こんにちは、現在ヘルプのRGSS3講座を見ながら
    RGSS3の基本的な動きについて勉強しているのですが

    条件分岐の or を試していると不可解な現象が起きました。

    #------------------------------------

    # or
    # || ~ または ~である
    # andとは違い、一つが間違っていても もう一つが合っていればtrueである

    print "100は50以上 または 25*4である\n\n"
    p (100 >= 50 or 25 * 4)

    print "\n"

    print "100は50以上 または 5+5である\n\n"
    p (100 >= 50 or 5 + 5)

    print "\n"

    print "1は50以上 または 5+5である\n\n"
    p (1 >= 50 or 5 + 5)

    print "\n"

    #---------------------------------------


    コンソールで勉強しているので"\n"で見やすくしているのですが
    3番目の条件分岐がtrueやfalse ではなく5+5の結果が表示されてしまいます。

    2番目をコピーして0を削るだけでも同じ現象が起きてしまうので
    文法の間違いなのか、RGSS3の不具合なのか分からないのが現状です……

    これは、どこか間違えているのでしょうか?
    勉強中のデータもアップするので誰か教えてください。
    https://www.axfc.net/u/3868211
     
    #1
    神無月サスケ がいいね!しました
  2. ツミオ

    ツミオ ユーザー

    こんにちは。
    Rubyは門外漢ですが、わかる範囲でお答えします。

    最初の条件分岐を見てみます。
    コード:
    (100 >= 50 || 25 * 4)
    100は50以上であるため、この条件式はtrueになります。
    このとき、100 >= 50がtrueであるため、or以降は判定されません(100 >= 50がtrueなら、or以降が何であっても条件式全体は必ずtrueになるため)。
    つまり25 * 4は演算されません。
    これをショートサーキットと言います。
    大切なので、このショートサーキットを念頭に置いて続きを読んでいただけると助かります。

    二番目の条件分岐を見てみます。
    コード:
    (100 >= 50 || 5 + 5)
    これも100は50以上がtrueであるため、5 + 5は評価されません。
    一番目と同じです。

    では三番目の条件分岐はどうでしょうか。
    コード:
    p(1 >= 50 || 5 + 5)
    「1は50以上である」はfalseなので(falseならば続く条件式を見なければならない)、次に5+5が評価されます。
    この結果として10が表示されています。

    簡単ですが、以上で説明を終わります。


    以下は「あまり参考にならないかもしれない解説」です。

    JavaScriptのイディオムの一つに以下のようなものがあります。
    コード:
    var hoge = hoge || defaultValue;
    これは「hogeがfalseとして扱える値を返すなら、defaultValueを代入せよ」と命令しています。
    おそらくRGSS2のorもこれと同じ使い方ができるのではないでしょうか?
    つまり上の例で言うと、「1が50以上でなければ5+5の結果を表示せよ」ということです。

    ただ僕がRubyに詳しくないため、上記の説明は単なる予想であることを書き添えておきます。
    間違っていたら申し訳ありません;_;

    追記:
    トップの書き込みを見て思ったのですが、or演算子が何と何を区切っているのかを確認してみてください。
    塊は以下のような感じです。
    コード:
    ((100 >= 50) || (5 + 5))
     
    最後に編集: 2017-12-04
    #2
    神無月サスケ開拓者 がいいね!しています
  3. 開拓者

    開拓者 ユーザー

    なるほど……
    ショートサーキットという仕様は初めて知りました。

    複雑な文章が読めないのでJavaScriptのほうは分かりませんが
    1回目と2回目は最初の分岐でTrueだったから
    それ以降の間違いを感知していなかったという訳ですね。

    andで作った文章とorで作った文章をじっくり比べてみたのですが

    コード:
    p (100 >= 20 and 1+1 == 2) 
    100は20以上であり、1+1は2である は
    100は20以上か? と 1+1は2か? を別々に調べているけれど

    コード:
    p (1 >= 50 or 5 + 5)
    1は50以上 または 5+5である は 
    1は50以上か、それとも5+5なのかを区切らないで調べようとしていて

    1は50以上か、5+5は1か のように2つに分ける必要があったんですね。
    コード:
    p ((1 >= 50 ) or (5 + 5 == 1))
    だとちゃんとfalseと表示されました!

    完成されたRPGを作れないのは苦しいと思っていたけど
    RGSSの勉強をしていると考えがガラッと変わりました。
    1つの課題をクリアするのが1個の作品を作るのに等しくて
    ちゃんと結果が残るし、知らない事を学んで成長しているんですよね。

    RGSSを勉強しようと思って良かったです。
    それと相談してみてよかったです、ありがとうございました!
     
    最後に編集: 2017-12-04
    #3
    神無月サスケツミオ がいいね!しています
  4. 神無月サスケ

    神無月サスケ ユーザー

    どうも、開拓者さん。
    説明すべきことは、ほぼすべてツミオさんが説明してくれているので、
    蛇足的な説明をいくつか。

    if ( a > 5 && b > 2) {
    // ...
    }

    のように、&& または and がついた構文の場合、前から評価していき、
    ひとつでも false が出たらそこで評価を打ち切ります。
    なぜなら、ひとつでも false があれば、もう false が確定だからです。
    このため、仮に a > 5 が成り立たない場合、 b > 2 は無視されます。

    逆に || または or の場合を考えましょう。

    if (a > 5 || b > 2) {
    // ...
    }

    この場合、a > 5 が trueになったら、そこで評価を打ち切り、 b > 2 の評価は行われません。
    なぜなら、|| や or はひとつでもtrueがあれば成り立つのですから、
    どれかひとつが成り立った時点で、残りの処理は冗長ですからね。

    僕が知っている限りの言語では、皆、これと同じメカニズムで判断しています。

    なお、これが一番役に立つのが、プラグイン作成です。
    プラグインに新しい変数を追加して、バージョンアップを行う場合、
    前のバージョンのプラグインが入ったゲームだと、新しい変数の値が undefined になります。

    そうでなくても、「制作中に新しいプラグインを作って入れた」場合も
    該当するでしょう。

    この場合、this.newValue = 5; などと initialize で宣言するだけでなく、
    この値を参照する直前に
    this.newValue = this.newValue || 5;
    と書く必要があります。

    この場合、すでにthis.newValueが与えられていればそのまま、
    そうでない場合、初期値の5が入ります。

    セーブデータをロードした場合、initializeは呼び出されませんので、
    こう書かないと、this.newValue が undefined のままで、
    処理がおかしくなてしまいます。

    以上、何かご参考になれば幸いです。
     
    #4
    開拓者 がいいね!しました

このページを共有