質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.05%

戻り値をうまく返せません.do-while内にdo-while

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 1,331

score 67

以前、Javaの勉強方針について質問した時はたくさんの方から助言をいただきました。ありがとうございました。
https://teratail.com/questions/13496
RPGゲームはまだ難しいと感じたので、コマンドラインで動作する簡単なゲーム作りをしています。

出題と答え合わせを行うメソッドを持つpersonクラスを定義して、簡単なクイズゲームを作りました。
*以下、コードを抜粋。
//メインクラス
public static void main(String[] args){
//インスタンスの生成
  person A=new person( );
  helper h=new helper( );
//値の初期化
  int answer=0;
  boolean value=true;
//質問メソッドを実行する。数字の入力を受付け、5(ヒント)以外が入力されるまでループ。
  do{
    A.question( );
    do{
      int answer=new java.util.Scanner(System.in).nextInt( );
      if(answer==5){
        h.hint( );
      }
    }while(answer==5);
//5以外が入力されたら、入力された数字をAオブジェクトの回答メソッドに引数として渡し、boolean型の変数で返す。正解するまで繰り返す。
    A.response(answer);
    boolean value=A.response(answer);
  }while(value==false);
}



//出題者クラス
public static class person{
  public void question( ){
    //画面上に4択問題を表示。
    //5を入力すればヒントがもらえると表示。
  }
  public boolean response(int a){
    if(a==1){
      System.out.println("正解です。");
      return true;
    }else{
      System.out.println("不正解です。やり直してください。");
      return false;
    }
  }
}
  
//helperクラスは画面にヒントを表示するヘルパーメソッドを持っています

自分の意図としては、
①数字の入力を受け付ける
②5なら画面上にヒントを表示し、もう一度数字の入力を受け付ける
③1が入力されたら(正解を表す)trueを返し、ループを抜け出す
④1以外が入力されたら(不正解を表す)falseを返し、繰り返す(ループ継続)
です。

当初は、answerやvalueをネストの深いところ(?)で宣言していたので、変数のスコープが狭くなり、値をうまく使えていなかったのですが、ループのブロックの外で宣言することで、ひとまず値は使えるようになりました。

しかし、実際に実行してみると、自分の意図したように動きません。

何がおかしいのでしょうか?
助言のほどよろしくお願いします。
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+3

doの前で宣言しているanswerと,doの中で宣言しているanswerと,2つのanswerを宣言しています.
普通ならコンパイルエラーになりそうなのですが・・・

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/08/25 00:28

    御返答ありがとうございます。
    Scannerをそのような方法で使ったことがなかったので、私の理解で正しいかどうか確認していただいてもよろしいでしょうか。

    >> Scanner s=new Scanner(System.in);
    コンストラクタにSystem.inを渡して、Scannerクラスのインスタンスsをnewする。

    >>answer=s.nextInt();
    sのnextInt()メソッドを実行した結果をanswerに代入する。

    そもそもこうすることのメリッドは何でしょうか?
    mainメソッドにScannerクラスのsというオブジェクトを作ってしまうことで、その都度Scannerクラスにアクセスする必要がないのでメモリを節約できるのでしょうか。
    まだ入門書を読み終えたレベルですので、正直、検討もつきません。このような知識を得るには、初心者を対象とした入門書の他に、やはり『Effective Java』やオライリーから出ている専門書なども読んだ方が良いのでしょうか。

    キャンセル

  • 2015/08/25 00:40

    メリットは2つあります.
    1.「インスタンスの生成」という動作のコストを節約できる
    インスタンスの生成には当然クラスのロード,インスタンスのためのメモリの確保等,メモリや時間を消費します.この動作をもとのコードでは「ヒントを表示するたびに」生成しているのです.はじめに1つ生成しておけばそれを節約できます.

    2.ガベージコレクタのコスト節約
    もとのコードではScannerが変数に入っていないので,入力が終わるとどこからも参照されなくなります.つまり,ガベージコレクタの対象になるのです.
    そして同じ用途のインスタンスが生まれては消え生まれては消えを繰り返すことになります.非常に無駄なことになります.

    1個Scannerを置いておけば標準入力からの入力はすべてそこから取り出せるので,いくつも生成する必要はないのです.

    キャンセル

  • 2015/08/25 00:57

    詳細な御説明ありがとうございます。
    相手がコンピュータといえど、人間と同じように「なるべく作業は単純に」するのがスピード面(処理速度)・体力面(メモリ容量)ともに良いということですね。
    入門書でもメモリやガベージコレクタについては触れられていましたが何となく読み飛ばしていました。
    今一度、復習したいと思います。

    何から何まで丁寧に御説明していただき、大変助かりました。
    また質問した際には、どうぞよろしくお願いします。

    ありがとうございました。

    キャンセル

+1

RPG期待してます!
理由は先の方がおっしゃられているとおりかと思います。
宣言の重複を直します。

int answer=new java.util.Scanner(System.in).nextInt( );
→値の初期化の箇所ですでに宣言しているためintは必要ない。
answer=new java.util.Scanner(System.in).nextInt( );
boolean value=A.response(answer);
→行ごと削除。value=A.response(answer)の行は既にあるため。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/08/24 22:33

    上の回答で1つ間違っています.
    A.response(answer)の返り値はvalueに入れなければ正常に動作しないので,
    この文の前にvalue=は必要です.
    もっとも,valueという変数を使わなくともwhileの条件判定の中で
    }while(A.response(answer) == false);
    としてもいいですが.

    キャンセル

  • 2015/08/25 00:12

    御返答ありがとうございます。
    以下のように変更したところ、意図した通りに動きました!

    }while(answer==5);
    value=A.response(answer);
    }while(value==false);

    また、以下のように書いても同様に動くことを確認しました。
    }while(answer==5);
    }while(A.response(answer)==false);

    引数を渡して、値を返す時に
    一度valueとして受け取り、valueをその後のコードで使うのか、
    新たに受け取ることはせずにそのまま使うのか
    の違いということですね。
    メソッドから値を返すことで、変数のように使う(表現が適切かわかりませんが・・・)ことができるのですね。

    とても参考になりました。
    (valueは)一度きりの変数なので、わざわざ宣言せずに後者の方で進めていきたいと思います。
    本当にありがとうございました!

    キャンセル

  • 2015/08/25 10:40

    見るのが遅れどうもスミマセン。。
    いやはや勉強になりますね。
    swordoneさんご回答いただきありがとうございました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.05%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る