演習: ミニゲーム集
各問題のコードは、Main クラスの main メソッドの中に書く前提です。標準入力には Scanner、乱数には Math.random() または java.util.Random を使ってください。各問題は1〜3時間で完成する規模で、易しい順に並んでいます。
9-A. サイコロの目を当てる
Section titled “9-A. サイコロの目を当てる”3ラウンド行います。各ラウンドで、ユーザーが 1〜6 のいずれかを予想します。コンピュータがサイコロを振り、出た目と一致した回数を最後に表示します。
出力例:
サイコロを3回振ります。1〜6 のどれが出るかを毎回予想してください。
ラウンド 1 > 3出た目: 5 → 外れラウンド 2 > 2出た目: 2 → 当たり!ラウンド 3 > 6出た目: 1 → 外れ結果: 3回中 1回 的中ステップ
- ユーザーの予想を入力で受け取り、サイコロの目を乱数で生成して、当たり/外れを表示する。
- これを3ラウンド繰り返し、最後に当たり回数を表示する。
ヒント
1〜6 の整数は (int)(Math.random() * 6) + 1 で生成できます。
ユーザーの予想は Scanner の nextInt() で受け取れます。for ループで 3 ラウンド回し、予想と出た目が一致した回数をカウンタ変数に貯めて、ループを抜けた後に表示します。
9-B. 数当てゲーム
Section titled “9-B. 数当てゲーム”コンピュータが 1〜100 の中からランダムに整数を1つ選びます。ユーザーが 1〜100 の整数を入力するたびに、コンピュータは「もっと大きい」「もっと小さい」を返します。正解したら何回で当てたかを表示してください。
出力例:
1〜100 の数字を当ててください。> 50もっと大きい> 75もっと小さい> 60もっと小さい> 55正解! 4回で当てました。ステップ
- 答えを固定値(例:
47)にしておき、ユーザー入力を1回受け取って「もっと大きい」「もっと小さい」「正解」を表示する。 - 答えを乱数で生成し、正解するまで繰り返して試行回数を表示する。
ヒント
答えは (int)(Math.random() * 100) + 1 で 1〜100 の整数を作り、ループに入る前に1度だけ決めておきます。
while ループの構造:
- 試行回数を 0 で初期化
- ループの中で入力を1つ受け取り、試行回数を +1
- 答えと比較して「もっと大きい」「もっと小さい」「正解」を表示
- 正解なら
breakでループを抜ける
正解時のメッセージで試行回数を表示します。
9-C. High & Low
Section titled “9-C. High & Low”コンピュータが 1〜13 のカードを次々と引いていきます。ユーザーは、現在表示されている「場のカード」に対して、次に引かれるカードがそれより大きい(H)か小さい(L)かを予想します。
予想が当たれば、新しく引いたカードが次の場のカードになり、次のラウンドへ進みます。引いたカードが場のカードと同じ値だった場合は引き分けで、連続正解のカウントは変えずに、場のカードはそのままで再度予想します。
5回連続で正解すれば勝ち、1回でも外せば負けです。
出力例:
場のカード: 7H or L? > H引いたカード: 11 → 当たり (1/5)
場のカード: 11H or L? > L引いたカード: 4 → 当たり (2/5)
場のカード: 4H or L? > H引いたカード: 4 → 引き分け(再予想)
場のカード: 4H or L? > H引いたカード: 9 → 当たり (3/5)...5回連続で当てました!勝利。ステップ
- 場のカードと引いたカードを乱数で生成し、ユーザーの予想(H/L)を入力で受け取って、正誤を表示する。
- 5連続正解か1回外しになるまで繰り返す。
- 引き分けのときは、連続正解数を増やさず、同じ場のカードでもう一度予想を受け付ける。
ヒント
カードは 1〜13 の整数で表現します。場のカードと引いたカードの2つの変数を持ち、ラウンドごとに引いたカードを新しい場のカードに上書きします(引き分けのときは上書きしません)。
入力は Scanner.next() で文字列として受け取り、"H" "L" との比較は大文字小文字を吸収するため equalsIgnoreCase を使います。
while ループの中で、連続正解数を管理する変数(例: streak)を進めます:
- 当たり →
streak++、次ラウンドへ - 引き分け →
streakはそのまま、同じ場のカードでもう一度入力を受け付ける - 外れ → 負けて
break streak == 5で勝利してbreak
9-D. Hit & Blow(ヌメロン)
Section titled “9-D. Hit & Blow(ヌメロン)”コンピュータが、重複しない 3桁の数字(例: 547)をランダムに決めます。ユーザーは3桁の数字を入力して当てに行き、コンピュータは結果を以下の形で返します。
- Hit: 数字も位置も合っている桁の数
- Blow: 数字は合っているが位置が違う桁の数
例: 答えが 547、ユーザー入力が 527 の場合
5(1桁目): 答えの1桁目と一致 → Hit2(2桁目): 答えに含まれない → なし7(3桁目): 答えの3桁目と一致 → Hit- 結果: 2 Hit, 0 Blow
3 Hit になればクリア。何回で当てたかを最後に表示します。
出力例:
重複しない3桁の数字を当ててください。> 1231 Hit, 1 Blow> 1450 Hit, 2 Blow> 5473 Hit! 7回で当てました。ステップ
- 答えとユーザー入力を固定値として、Hit と Blow を計算してコンソールに表示する。
- ユーザー入力を受け取り、3 Hit になるまで繰り返す。試行回数も数え、勝ったときに表示する。答えは固定のまま。
- 固定値だった答えを乱数で生成する。この時点では重複が出てもよい。
- 重複しない3桁を生成するように変える。
ヒント
判定は、答えとユーザー入力をそれぞれ3要素の配列にして、各位置を比較します。
- 同じ位置で同じ数字 → Hit
- それ以外で、答えに含まれる数字 → Blow
入力 123 を桁ごとに分けるには、2つの方法があります。
Stringで受け取りcharAt(i)で1文字ずつ取り出す。charを整数に直すには'5' - '0'のように'0'を引きます。- 整数で受け取り、
100 の位 = n / 100、10 の位 = (n / 10) % 10、1 の位 = n % 10で取り出します。
答えの3桁を作る方法も2つあります。
- 0〜9 の配列を 5-L. Fisher-Yates シャッフルでシャッフルし、先頭の3つを取る
- 重複が出るたびに引き直す
発展課題
- 手書き Fisher-Yates を
Collections.shuffleに、Blow 判定の二重ループをList.containsに置き換える - 不正な入力(
"abc"や"12"など)を弾き、再入力を促す - 答えの生成や入力検証を独立したメソッドに切り出し、コード中のマジックナンバーを名前付き定数にする
9-E. 神経衰弱
Section titled “9-E. 神経衰弱”4×4 の盤面に、1〜8 の数字を2枚ずつランダムに配置します(合計16マス)。ユーザーは2マスの位置を順に指定し、同じ数字なら開いたまま、違えば次のターンに進む際に再び伏せられます。全ペアを揃えるまでに何手かかったかを表示します(1手 = 2マス開く)。
出力例(簡略化):
盤面:? ? ? ?? ? ? ?? ? ? ?? ? ? ?
1枚目の位置(行 列) > 0 02枚目の位置(行 列) > 1 23 ? ? ?? ? 3 ?? ? ? ?? ? ? ?ペア!
1枚目の位置(行 列) > 0 12枚目の位置(行 列) > 2 23 5 ? ?? ? 3 ?? ? 7 ?? ? ? ?ペアではありません
[次のターンの開始時に、(0,1) と (2,2) は再び ? に戻る]...
すべて揃いました! 13手で完了。ヒント
盤面の管理には2つの2次元配列を使います。
int[][] board: 各マスの数字(1〜8)boolean[][] revealed: 各マスが公開されているかどうか
盤面の作り方:
- 1〜8 を2回ずつ並べた長さ 16 の1次元配列を作る
- 5-L. Fisher-Yates シャッフルでシャッフルする
- 4×4 の
boardに順に詰めていく
1ターンの流れ:
- 盤面を表示(
revealed[i][j]がtrueなら数字、falseなら?) - 1枚目の位置を入力で受け取り、
revealedをtrueにして再表示 - 2枚目の位置を入力で受け取り、同様に表示
- 数字が一致すればそのまま、違えば両マスの
revealedをfalseに戻す
すべてのマスが true になったら終了。手数のカウンタは2枚目を開いたタイミングで +1 します。
入力の妥当性チェック(範囲外、既に公開済み)も入れると堅牢になります。
9-F. 簡易ブラックジャック
Section titled “9-F. 簡易ブラックジャック”カードの合計を 21 に近づけるカードゲームです。プレイヤーとディーラーが対戦します。
ルール:
- カードは 1〜13 が引くたびにランダムに決まります(無限デッキとして扱い、同じ数字が複数回出ても構いません)
11、12、13(J・Q・K)は 10点 として扱う1(A)は 1点 または 11点 のうち、合計が 21 を超えないように有利な方を採用- プレイヤーは最初に2枚配られ、その後「ヒット(もう1枚引く)」か「スタンド(やめる)」を選ぶ。何度でも繰り返せる
- 合計が 22 以上になったら バスト(その時点で負け確定)
- プレイヤーがスタンドしたら、ディーラーが合計17以上になるまでヒットする
- 双方の合計を比較し、バストしていない方が勝ち。両方バストならディーラー勝ち、同点ならプレイヤー負け(簡易ルール)
出力例:
あなたの手札: [10, 7] = 17ヒット (h) or スタンド (s) > sディーラーの手札: [9, 5, 13] = 24 → バストあなたの勝ち!ヒント
手札は ArrayList<Integer> で持つと、add でカード追加・size で枚数取得が楽です。
カード値の補正:
- 11・12・13(J・Q・K)は得点計算時に 10 として扱う
- 1(A)は、まず全部 11 として合計を計算し、22 を超えるなら A を1枚ずつ 1 に降ろしていく
合計を計算するメソッド(例: score(ArrayList<Integer> hand))を切り出すと、プレイヤーとディーラーの両方で使い回せます。
ゲームの流れ:
- プレイヤーに2枚配る
- プレイヤーの手番:
whileループでヒット/スタンドを受け付ける。バストかs入力で抜ける - ディーラーの手番: 合計が 17 以上になるまで
whileループで引く - 最後に両方の合計を比較