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

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

新規登録して質問してみよう
ただいま回答率
85.50%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

解決済

2回答

1791閲覧

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

DaiAoki

総合スコア67

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

0グッド

0クリップ

投稿2015/08/24 07:48

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

出題と答え合わせを行うメソッドを持つpersonクラスを定義して、簡単なクイズゲームを作りました。
*以下、コードを抜粋。

Java

1//メインクラス 2public static void main(String[] args){ 3//インスタンスの生成 4 person A=new person( ); 5 helper h=new helper( ); 6//値の初期化 7 int answer=0; 8 boolean value=true; 9//質問メソッドを実行する。数字の入力を受付け、5(ヒント)以外が入力されるまでループ。 10 do{ 11 A.question( ); 12 do{ 13 int answer=new java.util.Scanner(System.in).nextInt( ); 14 if(answer==5){ 15 h.hint( ); 16 } 17 }while(answer==5); 18//5以外が入力されたら、入力された数字をAオブジェクトの回答メソッドに引数として渡し、boolean型の変数で返す。正解するまで繰り返す。 19 A.response(answer); 20 boolean value=A.response(answer); 21 }while(value==false); 22} 23 24 25 26//出題者クラス 27public static class person{ 28 public void question( ){ 29 //画面上に4択問題を表示。 30 //5を入力すればヒントがもらえると表示。 31 } 32 public boolean response(int a){ 33 if(a==1){ 34 System.out.println("正解です。"); 35 return true; 36 }else{ 37 System.out.println("不正解です。やり直してください。"); 38 return false; 39 } 40 } 41} 42 43//helperクラスは画面にヒントを表示するヘルパーメソッドを持っています

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

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

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

何がおかしいのでしょうか?
助言のほどよろしくお願いします。

気になる質問をクリップする

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

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

投稿2015/08/24 08:00

swordone

総合スコア20649

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

DaiAoki

2015/08/24 08:08

御回答ありがとうございます。 言葉足らずで申し訳ありません。補足です。 上記のコードだとおっしゃる通りコンパイルエラーになりました。 (内側の)doの中で数字入力を受け付けたいのですが、その場合(外側の)doでその数字を使えないという問題が発生してしまいました。おそらくスコープの問題だと思うのですが・・・ この場合、どのように対処したら良いでしょうか。
swordone

2015/08/24 08:18

内側で変数名の前に型名を付けているため,「宣言」の扱いになっています. 型名を外せば変数へのアクセスになるので使うことができるようになります.
DaiAoki

2015/08/24 13:09

御返答ありがとうございます。 「変数の前に型名を付けると「宣言」扱いになり、型名を外せば変数へのアクセスになる」ということをお恥ずかしながら認識しておりませんでした。 勉強不足でした。 一度宣言したものを定義し直したいときは、「宣言」ではなく「アクセス」するということで良いでしょうか。
swordone

2015/08/24 13:19

若干語弊がある気がしますがまあその通りです. あと質問とは関係無いですがクラス名が小文字始まりになってたり 変数名が大文字始まりになっていたり ヒント表示のループをするたびScannerを生成していたりと 気になる点が多いです.
DaiAoki

2015/08/24 13:32

御指摘ありがとうございます。 変数名やクラス名の命名にもこだわりたいと思います。 「ヒント表示のループをするたびScannerを生成していたり」 というのは、answer=new java.util.Scanner(System.in).nextInt( );の部分の位置がわるいのでしょうか。 そもそも、コードを複雑にしすぎているのでしょうか。 質問が多くなってしまい申し訳ありません。 「5が入力されたらヒントを表示し、再度数字の入力をさせる」というコードを書こうと思った時にどういった書き方が考えられるでしょうか。
swordone

2015/08/24 13:39

Scannerは1個あれば十分なのです.あとは入力要求された時にその都度入力するようにすればいいのです. なのでループに入る前に,(java.util.Scannerをimportして,) Scanner s = new Scanner(System.in); これでScannerを確保します. あとは入力させたいタイミングで answer = s.nextInt(); とすれば,キーボードからの整数の入力を取り出せます.
DaiAoki

2015/08/24 15: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』やオライリーから出ている専門書なども読んだ方が良いのでしょうか。
swordone

2015/08/24 15:40

メリットは2つあります. 1.「インスタンスの生成」という動作のコストを節約できる インスタンスの生成には当然クラスのロード,インスタンスのためのメモリの確保等,メモリや時間を消費します.この動作をもとのコードでは「ヒントを表示するたびに」生成しているのです.はじめに1つ生成しておけばそれを節約できます. 2.ガベージコレクタのコスト節約 もとのコードではScannerが変数に入っていないので,入力が終わるとどこからも参照されなくなります.つまり,ガベージコレクタの対象になるのです. そして同じ用途のインスタンスが生まれては消え生まれては消えを繰り返すことになります.非常に無駄なことになります. 1個Scannerを置いておけば標準入力からの入力はすべてそこから取り出せるので,いくつも生成する必要はないのです.
DaiAoki

2015/08/24 15:57

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

0

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 09:22

tsunex

総合スコア206

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

DaiAoki

2015/08/24 13:11

御回答ありがとうございます。 RPGを作るのはまだまだ先になりそうです・・・GUIについて学ぶにつれて、それ以前の部分の理解がまだまだだと思うところが多くて、勉強し直しています。 年内に必ずRPG作ります! 御指摘があったところを直してコードを書き直して再度投稿します。
DaiAoki

2015/08/24 13:23

int answer=0; boolean value=true; //質問メソッドを実行する。数字の入力を受付け、5(ヒント)以外が入力されるまでループ。 do{ A.question( ); do{ answer=new java.util.Scanner(System.in).nextInt( ); if(answer==5){ h.hint( ); } }while(answer==5); //5以外が入力されたら、入力された数字をAオブジェクトの回答メソッドに引数として渡し、boolean型の変数で返す。正解するまで繰り返す。 A.response(answer); }while(value==false); } 書き直したところコンパイルに成功しました! 無事に文字入力もできました。 数字をいれて検証してみたのですが、どの数字を入力してもループを抜けてしまいます。 1を入力→正常に動作 5を入力→ヒントが表示されず、不正解。さらにループを抜けてしまう。 それ以外の数字→不正解なのにループを抜けてしまう。 「ループを抜けてしまう」、「正解・不正解はきちんと表示される」ということは、引数を渡して画面に正解か不正解かを表示するところまでは、answerがしっかり機能していますが、その後、すべて戻り値がtrueになってしまっていると思うので、返したあとになぜかtrueになってしまっているのだと思いました。 自分でも頭の中が混乱していて、うまく伝えられてないような気がしますが・・・ ヒントが表示されないのがなぜなのかは皆目検討もつきません。 何かヒントをいただけないでしょうか。
swordone

2015/08/24 13:33

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

2015/08/24 15:12

御返答ありがとうございます。 以下のように変更したところ、意図した通りに動きました! }while(answer==5); value=A.response(answer); }while(value==false); また、以下のように書いても同様に動くことを確認しました。 }while(answer==5); }while(A.response(answer)==false); 引数を渡して、値を返す時に 一度valueとして受け取り、valueをその後のコードで使うのか、 新たに受け取ることはせずにそのまま使うのか の違いということですね。 メソッドから値を返すことで、変数のように使う(表現が適切かわかりませんが・・・)ことができるのですね。 とても参考になりました。 (valueは)一度きりの変数なので、わざわざ宣言せずに後者の方で進めていきたいと思います。 本当にありがとうございました!
tsunex

2015/08/25 01:40

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問