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

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

ただいまの
回答率

89.63%

なぜかHashSetのcontainsがうまく動きません。

受付中

回答 1

投稿

  • 評価
  • クリップ 1
  • VIEW 487

F.Yosida

score 2

 前提・実現したいこと

クイズのゲームです。なぜかcontainsがうまく動きません。
hashCodeを使うといいと聞いてエクリプスの機能で実装してみましたがうまくいきませんでした。

注釈
問題文や選択肢の部分には不具合はないものとする。jarの中身も同様。
(あえて読めないようにしてあるので、その部分は調査しなくて良い)

 発生している問題・エラーメッセージ

以下のcontainがうまく動きません

if (!usedQuestions.contains(question)) {
                usedQuestions.add(question);
                return question;
            }```  

 該当のソースコード

package jp.co.bbreak.debugchallenge;  

import java.io.File;  
import java.io.FileInputStream;  
import java.io.IOException;  
import java.io.ObjectInputStream;  
import java.nio.charset.Charset;  
import java.nio.file.Files;  
import java.nio.file.Path;  
import java.nio.file.Paths;  
import java.util.ArrayList;  
import java.util.HashSet;  
import java.util.List;  
import java.util.Random;  
import java.util.Scanner;  
import java.util.Set;  

import org.apache.commons.lang3.StringUtils;  

/**  
* クイズゲーム  
*  
* @author Kenta Kawasaki  
*/  
public class Quiz {  

/** 成績 */  
private final QuizScore score = new QuizScore();  

/** 問題リスト */  
private final List<String> questionPaths = new ArrayList<>();  

/** 使用済みの問題 */  
private final Set<Question> usedQuestions = new HashSet<>();  

/**  
* エントリポイント  
*  
* @param args  
*/  
public static void main(String[] args) {  
Quiz quiz = new Quiz();  
quiz.play();  
}  

/**  
* コンストラクタ  
*/  
public Quiz() {  
questionPaths.addAll(loadQuestionPaths());  
}  

/**  
* クイズを出す  
*/  
public void play() {  
for (int i = 0; i < questionPaths.size(); i++) {  
Question question = selectQuestion();  
set(question);  
System.out.println("----------------------------------------");  
}  
showResult();  
}  

/**  
* 次に出題する問題を選んで返す。  
* @return 出題する問題  
*/  
public Question selectQuestion() {  
while (true) {  
// ランダムに1問選ぶ  
int idx = new Random().nextInt(questionPaths.size());  
Question question = loadQuestion(questionPaths.get(idx));  
if (!usedQuestions.contains(question)) {  
usedQuestions.add(question);  
return question;  
}  
}  
}  

/**  
* クイズを出題する。  
*  
* @param questionNo  
*            問題番号  
* @param question  
*            出題する問い  
*/  
private void set(Question question) {  
question.show();  

boolean isCorrectAnswer;  
while (true) {  
String yourAnswer = chooseAnswer();  
if (question.hasAnswer(yourAnswer)) {  
isCorrectAnswer = question.answer(yourAnswer);  
break;  
} else {  
if (StringUtils.isEmpty(yourAnswer)) {  
System.out.println("回答が選択されていません。");  
} else {  
System.out.println(yourAnswer + " は回答の選択肢に存在しません。");  
}  
}  
}  

if (isCorrectAnswer) {  
System.out.println("正解です");  
score.incrementCorrectCount();  
} else {  
System.out.println("間違いです");  
score.incrementIncorrectCount();  
}  
}  

/**  
* ユーザに回答を選択させます。  
*  
* @return ユーザの選択した回答  
*/  
private String chooseAnswer() {  
System.out.print("あなたの回答:");  
@SuppressWarnings("resource")  
final String yourAnswer = new Scanner(System.in).nextLine();  
return yourAnswer;  
}  

/**  
* 結果を表示する。  
*/  
private void showResult() {  
System.out.println("正解率:" + score.getCorrectAnswerPercentage() + "%");  
}  

/**  
* 問題リストのパスを読み込む。  
*  
* @return  
*/  
private List<String> loadQuestionPaths() {  
try {  
Path path = Paths.get("resource/questions.txt");  
return Files.readAllLines(path, Charset.defaultCharset());  
} catch (IOException e) {  
// 課題の趣旨と関係ないので省略  
throw new RuntimeException("問題ファイルの読み込みに失敗しました");  
}  
}  

/**  
* 指定ファイルの問題を読み込む。  
*  
* @return  
*/  
private Question loadQuestion(String filePath) {  
File file = Paths.get(filePath).toFile();  
try (FileInputStream s = new FileInputStream(file);  
ObjectInputStream o = new ObjectInputStream(s)) {  

Question question = (Question) o.readObject();  
return question;  
} catch (IOException | ClassNotFoundException e) {  
// 課題の趣旨と関係ないので省略  
throw new RuntimeException("問題ファイルの読み込みに失敗しました");  
}  
}  
}  
package jp.co.bbreak.debugchallenge;  

import java.io.Serializable;  
import java.util.ArrayList;  
import java.util.List;  

import org.apache.commons.lang3.math.NumberUtils;  

/**  
* クイズゲーム:問題  
*   
* @author Kenta Kawasaki  
*/  
public class Question implements Serializable {  

private static final long serialVersionUID = 9185957365396112593L;  

/** 問題文 */  
private String sentence;  

/** 選択肢のリスト */  
private List<Answer> answers = new ArrayList<>();  

/**  
* 問題文を取得します。  
*   
* @return 問題文  
*/  
public String getSentence() {  
return sentence;  
}  

/**  
* クイズに回答します。  
*   
* @param yourAnswer  
*            選択された回答番号  
* @return 回答が正解かどうか。正解を選択していればtrue、それ以外はfalse  
*/  
public boolean answer(final String selectedAnswerString) {  
if (!NumberUtils.isNumber(selectedAnswerString)) {  
// #hasAnswer() でtrueになった値であればここは通らない  
throw new NumberFormatException();  
}  

int selectedAnswer = NumberUtils.toInt(selectedAnswerString);  
for (final Answer answer : answers) {  
if (answer.getAnswerIndex() == selectedAnswer) {  
return answer.isCorrect();  
}  
}  
throw new IllegalStateException(selectedAnswerString + "は存在しない回答番号です。");  
}  

/**  
* 問題を表示します。  
*/  
public void show() {  
final StringBuilder builder = new StringBuilder();  
builder.append(sentence + "\n\n");  
for (Answer answer : answers) {  
builder.append(answer.getSentence() + "\n");  
}  
System.out.println(builder.toString());  
}  

/**  
* 与えられた回答が選択肢として存在する場合、trueを返します。  
*   
* @param selectedAnswerString  
* @return 回答が存在する場合true、それ以外はfalse  
*/  
public boolean hasAnswer(final String selectedAnswerString) {  
if (NumberUtils.isNumber(selectedAnswerString)) {  
int selectedAnswer = NumberUtils.toInt(selectedAnswerString);  
for (final Answer answer : answers) {  
if (answer.getAnswerIndex() == selectedAnswer) {  
return true;  
}  
}  
}  
return false;  
}  
}  
package jp.co.bbreak.debugchallenge;  

import java.io.Serializable;  

/**  
* クイズゲーム:回答  
*   
* @author Kenta Kawasaki  
*/  
public class Answer implements Serializable {  

private static final long serialVersionUID = -2607171250093907133L;  

/** 回答 */  
private String sentence;  

/** 回答番号 */  
private int answerIndex;  

/** 正解フラグ */  
private boolean correct = false;  

/**  
* 回答を取得します。  
*   
* @return  
*/  
public String getSentence() {  
return answerIndex + ": " + sentence;  
}  

/**  
* 回答番号を取得します。  
*   
* @return  
*/  
public int getAnswerIndex() {  
return answerIndex;  
}  

/**  
* この回答が正しければ、trueを返します。  
*   
* @return 回答が正しければtrue、間違っていればfalse  
*/  
public boolean isCorrect() {  
return correct;  
}  
}  

 試したこと

ここに問題に対して試したことを記載してください。

 補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

質問への追記・修正、ベストアンサー選択の依頼

  • Udomomo

    2018/04/03 18:31

    具体的にどんなエラーメッセージが出たのでしょうか?

    キャンセル

  • asahina1979

    2018/04/03 18:37

    jp.co.bbreak.debugchallenge;  会社名出ちゃいますが(修正で削除しても履歴で見れます)

    キャンセル

  • asahina1979

    2018/04/03 18:45

    ハッシュコードの実装方法がわかってない情報漏洩予備軍なんじゃない?

    キャンセル

  • deadjupiter

    2018/04/04 05:47

    Kenta Kawasaki泣いてそう

    キャンセル

回答 1

0

hashCodeを実装したと言いつつコードにそれが無いようですが…?

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

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

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

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