前提・実現したいこと
android studioでandroidアプリ開発のための学習をしている初学者です。
言語はjavaです。
「たった1日で基本が身に付く androidアプリ開発超入門」という本のビンゴアプリを作成しました。
問題なく完成したのですが、タップをし続けると強制終了してしまいます。
この原因を突き止めて強制終了を回避したいのです。
発生している問題
出目の最大値は初期値として75を設定してあるのですが、任意の数字に変更できます。
アプリが完成した後に夫に実機で試してもらいました。
夫がタップしながら「これってちゃんと最大値まで全部出るのかな」というので、
「じゃあ最大値を5に設定して全部の出目がでるかどうか見てみたら」とすすめて15全部の数字が出るか確認してもらいました。5の数字が出た後もタップしていたら、フリーズしたあとに強制終了しました。
ランダムに1
エミュレーターでも同じようにフリーズしたあとに強制終了しました。
ログで出た内容は以下の通りです。
出目が揃ったあとは「重複したので再生成」と「uid=10135~」をずっと繰り返してます。
D/MainActivity: maxNumber: 5 D/MainActivity: [4] D/MainActivity: [4, 2] D/MainActivity: 重複したので再生成 D/MainActivity: [4, 2, 5] D/MainActivity: [4, 2, 5, 3] D/MainActivity: 重複したので再生成 D/MainActivity: [4, 2, 5, 3, 1] D/MainActivity: 重複したので再生成 I/chatty: uid=10135(com.example.mybingo2) identical 77 lines D/MainActivity: 重複したので再生成 D/MainActivity: 重複したので再生成 I/chatty: uid=10135(com.example.mybingo2) identical 34958 lines ・ ・ ・
該当のソースコード
java
1package com.example.mybingo2; 2 3import androidx.appcompat.app.AppCompatActivity; 4 5import android.os.Bundle; 6import android.util.Log; 7import android.view.View; 8import android.widget.Button; 9import android.widget.EditText; 10import android.widget.TextView; 11 12import java.util.ArrayList; 13 14 15public class MainActivity extends AppCompatActivity { 16 17// 最大値を管理するための変数を用意する。これはインスタンス変数・・アクティビティ内のすべてのメソッドからアクセスできる。他にローカル変数がある・・メソッドの{}で囲まれた範囲内で有効 18// アクセス修飾子privateはクラスの中でしか使えない。publicはクラスの外からでも使える。intはデータ型。maxNumberは変数名。75を代入。 19 private int maxNumber = 75; 20// 「数字の履歴」のインスタンス変数を宣言 21// privateはクラスの中でしか使えないアクセス修飾子。ArrayList<String>は文字列型のデータ型。historyは変数名。 22 private ArrayList<String> history = new ArrayList<>(); 23// 「最大値の入力欄」のインスタンス変数を宣言 24// privateはクラスの中でしか使えないアクセス修飾子。EditTextはデータ型。maxNumberEditTextは変数名。 25// EditText や Button は、Android が提供するクラスであり、データ型の一種。 26 private EditText maxNumberEditText; 27// 「最大値の設定ボタン」のインスタンス変数を宣言 28// privateはクラスの中でしか使えないアクセス修飾子。Buttonはデータ型。registerMaxNumberButtonは変数名。 29 private Button registerMaxNumberButton; 30// 「次の数字を出すボタン」のインスタンス変数を宣言 31// privateはクラスの中でしか使えないアクセス修飾子。Buttonはデータ型。nextNumberButtonは変数名。 32 private Button nextNumberButton; 33// 「現在の数字を表示するTextView」のインスタンス変数を宣言 34// privateはクラスの中でしか使えないアクセス修飾子。TextViewはデータ型。currentNumberTextViewは変数名。 35 private TextView currentNumberTextView; 36 37 38 @Override 39 protected void onCreate(Bundle savedInstanceState) { 40 super.onCreate(savedInstanceState); 41 setContentView(R.layout.activity_main); 42 43// ビューの変数を初期化する 44 maxNumberEditText = findViewById(R.id.max_number); 45 registerMaxNumberButton = findViewById(R.id.register_max_number); 46 nextNumberButton = findViewById(R.id.next_number); 47 currentNumberTextView = findViewById(R.id.current_number); 48 49 50// 最大値の初期値をEditTextにセットする。画面に75が表示される。 51 maxNumberEditText.setText("" + maxNumber); 52 53// 最大値を更新する 54 registerMaxNumberButton.setOnClickListener(new View.OnClickListener(){ 55 56 @Override 57 public void onClick(View v){ 58// 入力値を文字列で取り出す 59 String maxNumberString = maxNumberEditText.getText().toString(); 60// int型に変換してから代入する。EditTextは入力値を文字列でしか扱うことができない。 61 maxNumber = Integer.valueOf(maxNumberString); 62 63 Log.d("MainActivity", "maxNumber: " + maxNumber); 64 65 } 66 }); 67 68// 表示中の数字を更新する 69 nextNumberButton.setOnClickListener(new View.OnClickListener(){ 70 @Override 71 public void onClick(View v){ 72 onClickNextNumber(); 73 } 74 }); 75 } 76 77// nextNumberButtonがタップされたときの処理 78 private void onClickNextNumber(){ 79// Log.d("MainActivity","onClickNextNumber"); 80 81// maxNumberを考慮したランダムな数値 82 int nextNumber = createRandomNumber(); 83 84// 重複している数値だった場合は数値の生成をやり直す 85 while (history.contains("" + nextNumber)){ 86 Log.d("MainActivity", "重複したので再生成"); 87 nextNumber = createRandomNumber(); 88 } 89 90// nextNumberを文字列に変換する 91 String nextNumberStr = "" + nextNumber; 92 93// nextNumberを画面に表示する 94 currentNumberTextView.setText(nextNumberStr); 95 96// 履歴を残す 97 history.add(nextNumberStr); 98 Log.d("MainActivity", history.toString()); 99 100// 「1~75のランダムな数値を生成したい」 101// 0.0~74.0の数値を生成する(最大値が初期値の75の場合) 102// Math.randomメソッドは0.0~1.0未満までのdouble型の小数値をランダムに生成する。これに75(-1しない。75のまま)をかけて、0.0~75.0未満にする。 103// double randomNumber = Math.random() * (maxNumber); 104// 1~75の整数値を生成する(最大値が初期値の75の場合) 105// doubleからintへの縮小変換キャストをして、0~74にする。(小数点から整数にする)さらに+1で1~75にして、nextNumberへ代入。 106// int nextNumber = (int) randomNumber + 1; 107 108// nextNumberを画面に表示する。 109// currentNumberTextView.setText("" + nextNumber); 110 111// Log.d("MainActivity","nextNumber: " + nextNumber); 112 } 113 114// maxNumberを考慮したランダムな数値を生成する 115 private int createRandomNumber(){ 116// 0.0~74.0の数値を生成する 117 double randomNumber = Math.random() * (maxNumber); 118// 1~75の整数値を生成する 119 return (int) randomNumber + 1; 120 } 121 122 123 124// Log.d("MainActivity", "maxNumber: " + maxNumber); 125}
試したこと
①出版元のサポートページを確認しましたが、とくに該当の記述はありませんでした。
②入力ミスがないかチェックして、最初から順番にエラーの確認をしました。
以下のコードの後に問題のエラーが出たように思いました。
// 重複している数値だった場合は数値の生成をやり直す while (history.contains("" + nextNumber)){ Log.d("MainActivity", "重複したので再生成"); nextNumber = createRandomNumber(); }
何か間違って入力しているのか、足りないコードがあるのかわかりません。
よろしくご教示ください。
ビンゴアプリなので、1つずつ数字を出していって、最大値以上にタップすることはあまり無いかとは思いますが、
もし対策があるなら試してみたいのです。