では while 文の練習問題を 6 問 用意して、それぞれに「解答(実行可能な Java コード)」「ステップごとの解説」「よくあるミス」「発展課題」を付けます。手を動かして確かめやすいように、入出力例も載せます。コピーしてそのまま実行できるコードです。
練習問題 1(やさしい) — 1 から n までの偶数の合計
問題
ユーザーが入力した正の整数 n に対して、1 から n までの 偶数 の合計を while を使って求めて表示せよ。
入力例n = 10
期待出力2 + 4 + 6 + 8 + 10 = 30
解答(サンプル)
import java.util.Scanner;
public class SumEven {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("n を入力: ");
int n = sc.nextInt();
int i = 1;
int sum = 0;
while (i <= n) {
if (i % 2 == 0) {
sum += i;
}
i++;
}
System.out.println("偶数の合計 = " + sum);
sc.close();
}
}
Javaステップ解説
iを1で初期化(ループの開始値)。- 条件
i <= nを満たす間ループ。 if (i % 2 == 0)で偶数か判定し、偶数ならsumに加算。i++で必ずiを進める(更新忘れ防止)。- ループ終了後に
sumを表示。
よくあるミス
i++を忘れる → 無限ループ。i = 2からi += 2にして最初から偶数だけ回す(効率的だが初心者は忘れがち)。
発展i = 2; while (i <= n) { sum += i; i += 2; } に書き換えて効率化してみよう。
練習問題 2(基本アルゴリズム) — n の階乗(factorial)
問題
正の整数 n を入力し、n!(階乗)を while で計算して表示せよ。n は 0 以上とする(0! = 1)。
入力例n = 5
期待出力5! = 120
解答(サンプル)
import java.util.Scanner;
public class Factorial {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("n を入力 (0以上): ");
int n = sc.nextInt();
long result = 1;
int i = 1;
while (i <= n) {
result *= i;
i++;
}
System.out.println(n + "! = " + result);
sc.close();
}
}
Javaステップ解説
resultを1で初期化(掛け算の単位元)。- ループ変数
iを1からnまで増やす。 - 各ループで
result *= i(累積的に掛ける)。 i++を忘れずに。n = 0の場合、ループは実行されずresultは1のまま(正しく0! = 1)。
よくあるミス
- 結果を
intにしてオーバーフロー(20!あたりでintは不適)。longを使うか大きな数はBigIntegerを検討。
発展BigInteger を使ってさらに大きな階乗を計算してみよう。
練習問題 3(文字列操作) — 整数の桁を逆順にする
問題
正の整数 n を入力し、数の桁を逆順にして表示せよ(数学的操作で行う — 文字列操作は使わない)。
入力例n = 12340
期待出力04321(数値として出すなら 4321 になるが、0 を保持したい場合は文字列に変換して扱う)
解答(サンプル)(数値として逆にして表示するパターン)
import java.util.Scanner;
public class ReverseDigits {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("正の整数を入力: ");
int n = sc.nextInt();
int rev = 0;
while (n > 0) {
int digit = n % 10; // 末尾の桁を取り出す
rev = rev * 10 + digit; // 逆順に追加
n /= 10; // 末尾の桁を削る
}
System.out.println("逆順 = " + rev);
sc.close();
}
}
Javaステップ解説
n % 10で末尾の桁を取得。rev = rev * 10 + digitで桁を左に詰めつつ追加。n /= 10で元の数の末尾を切り落とす。nが0になるまで続ける。
注意点
- 先頭に 0 があるような表示(例:
12340→04321)を厳密に再現したい場合は、文字列操作で桁数を保存しておく必要がある(このサンプルは数値型で扱うため04321は4321と表示される)。
発展
負の数の処理を追加したり、文字列で 0 を保持して出力するバージョンを作ってみよう。
練習問題 4(入力バリデーション) — 正の数が来るまで読み直す
問題
ユーザーに正の整数を入力してもらう。もし負の数や 0 が入力されたらエラーメッセージを出して再入力を促す(正しい入力が来るまで while で繰り返す)。
入出力の流れ(例)
入力: -3 → 0 → 5 → 終了(5 を受け付ける)
解答(サンプル)
import java.util.Scanner;
public class ReadPositive {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int x;
System.out.print("正の整数を入力してください: ");
x = sc.nextInt();
while (x <= 0) {
System.out.println("入力エラー: 正の整数を入力してください。");
System.out.print("再入力: ");
x = sc.nextInt(); // 再読み込み(必須)
}
System.out.println("入力された正の数 = " + x);
sc.close();
}
}
Javaステップ解説
- 最初に値を読み込む(ループ前読み込みパターン)。
x <= 0の間は「エラー」→再入力を要求し続ける。- 正の数が来たらループ終了。
よくあるミス
- ループの中だけで読み込みをして
初回読み込みを忘れると変な挙動に。 nextInt()が例外を投げる(数以外の入力)ケースは未対処 →try-catchで扱うとより堅牢。
発展try-catch を使って “数以外” 入力時に sc.next() で不正なトークンを捨て、再入力を促すようにする。
練習問題 5(ループ制御) — パスワード試行(失敗回数制限)
問題
正しいパスワード(文字列)を secret として用意し、ユーザーに最大 3 回まで入力させる。正解したら「ログイン成功」、3 回失敗したら「ロック」して終了する。ループは while を使う。
解答(サンプル)
import java.util.Scanner;
public class PasswordTry {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
final String SECRET = "openSesame";
int attempts = 0;
boolean loggedIn = false;
while (attempts < 3) {
System.out.print("パスワード: ");
String input = sc.nextLine();
attempts++;
if (input.equals(SECRET)) {
System.out.println("ログイン成功");
loggedIn = true;
break; // 成功したら抜ける
} else {
System.out.println("パスワードが違います。残り " + (3 - attempts) + " 回");
}
}
if (!loggedIn) {
System.out.println("アカウントはロックされました。");
}
sc.close();
}
}
Javaステップ解説
attempts(試行回数)を 0 で初期化。- 条件
attempts < 3で最大回数を保証。 - 各回
attempts++を行い、equalsで文字列比較(==はダメ)。 - 正解なら
breakでループを抜ける。 - ループ後に
loggedInフラグで成功/失敗を判定。
よくあるミス
- 文字列比較で
==を使ってしまう(オブジェクト参照の比較になり失敗する)。 attempts++の位置を間違えると残り回数表示がズレる。
発展while(true) にして、成功か失敗(回数超過)で break する別スタイルに書き換えてみよう。
練習問題 6(応用) — セントネル値 -1 で最大最小を求める(先頭が -1 の場合の扱い)
問題
ユーザーが整数を何個でも入力する。-1 が入力されたら入力終了(-1 は集計に含めない)。入力された値の最大値と最小値を表示せよ。もし最初の入力が -1(すなわちデータがない)なら、その旨を表示する。
解答(サンプル)
import java.util.Scanner;
public class MinMaxUntilMinusOne {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("整数を入力(-1で終了):");
int num = sc.nextInt();
if (num == -1) {
System.out.println("データがありません。");
sc.close();
return;
}
int min = num;
int max = num;
while (true) {
num = sc.nextInt();
if (num == -1) break;
if (num < min) min = num;
if (num > max) max = num;
}
System.out.println("最小 = " + min + ", 最大 = " + max);
sc.close();
}
}
Javaステップ解説
- 最初の入力をループの外で取り、
-1なら「データなし」で終了(特別処理)。 - 最小・最大
minmaxを最初の値で初期化。 while(true)で次々読み込み、-1が来たらbreak。- 各値で
minとmaxを更新。 - 最後に結果を表示。
よくあるミス
- 最初の
-1をそのままmin/maxに入れてしまう(すると集計に含まれてしまう)。 while (num != -1)という書き方でもできるが、初回とその後の読み方に注意(読み込み位置の取り扱いを間違いやすい)。
発展
平均や個数も同時に保持して表示する(0 除算やデータなしのケースに注意)。
最後に(学習のコツ)
- まずは 紙に処理の流れを図示(初期値→条件→本体→更新→終了)すると書きやすくなります。
- 自分で「想定入力」を決めて、手で変数を書きながらループを追い、各変数がどう変わるか確認すると理解が深まります。
- エラーや無限ループに出会ったら、ループの最初に
System.out.printlnで変数を出力して値の変遷を追跡しましょう。
