【JAVA】確認問題3-☆1:石取りゲームを作ろう

記事内に商品プロモーションを含む場合があります

この記事の練習問題で使用する知識:
基礎文法(レッスン1)比較演算子と論理演算子if文による条件分岐while文による繰り返し処理繰り返しの制御メソッドの定義と呼出しメソッドの戻り値真偽値を返すメソッド

JAVAのゲームコード一覧はこちら

<<前のページ 問題集Top 次のページ>>

確認問題3-☆1:石取りゲームを作ろう

石取りゲームを作成しましょう。

ゲームではユーザーとコンピュータが交互に石を取り合い、最後の石を取った方が負けとなります。プレイヤーが取れる石の数は1~3個です。

コンピュータのターンでは、ランダムな数の石を取り、最後の石を取らないように戦略をとります。

このゲームを通してメソッドの作成や条件分岐、ループの使い方を練習してください。

この問題の要件

以下の要件に従ってコードを完成させてください。

  1. 石の初期数: 初期値を15個とする。
  2. プレイヤーのターン: 以下の処理を行う playerTurn メソッドを作成すること。
    • プレイヤーに1~3の範囲で石の数を入力させ、その数だけ石を減らす。
    • 入力が無効な場合は再度入力を求め、再入力が正しい数値になるまでループを続ける。
  3. コンピュータのターン: 以下の処理を行う computerTurn メソッドを作成すること。
    • ランダムで1~3個の石を取り、取りすぎないように残りの石に応じて調整する。
    • 取った石の数と残りの石の数を表示する。
  4. 勝敗判定: ゲームが終了しているかを判定する isGameOver メソッドを作成すること。
    • 石の数が0になった場合、どちらの負けかを判定し、メッセージを表示する。

ただし、以下のような実行結果となるコードを書くこと。

*****↓↓正解コードの実行結果の例↓↓*****

=== 石取りゲーム ===
石の数: 15
1ターンに1〜3個の石を取ることができます。
最後の石を取った方が負けです。

取る石の数 (1〜3) を入力してください: 2
あなたは 2 個の石を取りました。残りの石: 13
コンピュータは 3 個の石を取りました。残りの石: 10

取る石の数 (1〜3) を入力してください: 1
あなたは 1 個の石を取りました。残りの石: 9
コンピュータは 2 個の石を取りました。残りの石: 7

取る石の数 (1〜3) を入力してください: 3
あなたは 3 個の石を取りました。残りの石: 4
コンピュータは 3 個の石を取りました。残りの石: 1

取る石の数 (1〜3) を入力してください: 1
あなたは 1 個の石を取りました。残りの石: 0
あなたの負けです!

この問題を解くヒント

1からコードを組み立てることが難しい場合は、以下のヒントを開いて参考にしましょう。

ヒント1【コードの構成を見る】

正解のコードは上から順に以下のような構成となっています。
(※下記の□はコード内のインデントを表しています)

1:RandomクラスとScannerクラスのインポート
2:StoneGameクラスの定義
  □ mainメソッドの定義
  □ □ Scannerオブジェクトscannerの初期化
  □ □ Randomオブジェクトrandomの初期化
  □ □ 変数stonesに15を代入(初期の石の数)
  □ □ 「=== 石取りゲーム ===」と出力
  □ □ 「石の数: 」とstonesの値を出力
  □ □ 「1ターンに1〜3個の石を取ることができます。」と出力
  □ □ 「最後の石を取った方が負けです。」と出力
  □ □ whileループにてstonesが0より大きい間繰り返し処理を開始
  □ □ □ 変数stonesにplayerTurnメソッドの戻り値を代入(プレイヤーのターンを実行)
  □ □ □ if文でisGameOverメソッドの戻り値がtrueであるかを判定(プレイヤーの勝敗判定)
  □ □ □ □ trueの場合、breakでループを終了
  □ □ □ 変数stonesにcomputerTurnメソッドの戻り値を代入(コンピュータのターンを実行)
  □ □ □ if文でisGameOverメソッドの戻り値がtrueであるかを判定(コンピュータの勝敗判定)
  □ □ □ □ trueの場合、breakでループを終了
  □ □ scannerオブジェクトをクローズ

  □ playerTurnメソッドの定義
  □ □ 引数としてint型のstonesとScanner型のscannerを受け取る
  □ □ 「取る石の数 (1〜3) を入力してください: 」と出力
  □ □ playerMove変数にscannerからの整数入力を代入
  □ □ whileループにてplayerMoveが1未満または3超、もしくはstonesより大きい場合の繰り返し処理を開始
  □ □ □ 「無効な入力です。再度1〜3の範囲で入力してください: 」と出力
  □ □ □ playerMoveにscannerからの整数入力を再度代入
  □ □ stonesからplayerMoveの値を減算
  □ □ 「あなたは 」とplayerMoveと「 個の石を取りました。残りの石: 」とstonesの値を出力
  □ □ stonesの値を返す

  □ computerTurnメソッドの定義
  □ □ 引数としてint型のstonesとRandom型のrandomを受け取る
  □ □ 変数computerMoveにrandomから1〜3のランダムな整数を生成し、stonesの最小値を選択して代入
  □ □ stonesからcomputerMoveの値を減算
  □ □ 「コンピュータは 」とcomputerMoveと「 個の石を取りました。残りの石: 」とstonesの値を出力
  □ □ stonesの値を返す

  □ isGameOverメソッドの定義
  □ □ 引数としてint型のstonesとString型のplayerNameを受け取る
  □ □ if文にてstonesが0であるかを判定
  □ □ □ 真の場合、「playerNameの負けです!」と出力
  □ □ □ trueを返す
  □ □ falseを返す

ヒント2【穴埋め問題にする】

以下のコードをコピーし、コメントに従ってコードを完成させて下さい。

import java.util.Random;
import java.util.Scanner;

public class StoneGame {

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        Random random = new Random();

        int stones = 15; // 初期の石の数
        System.out.println("=== 石取りゲーム ===");
        System.out.println("石の数: " + stones);
        System.out.println("1ターンに1〜3個の石を取ることができます。");
        System.out.println("最後の石を取った方が負けです。");

        while (stones > 0) {
            // プレイヤーのターン
            stones = playerTurn(stones, scanner);

            // 勝敗判定
            if (isGameOver(stones, "あなた")) {
                break;
            }

            // コンピュータのターン
            stones = computerTurn(stones, random);

            // 勝敗判定
            if (isGameOver(stones, "コンピュータ")) {
                break;
            }
        }
    }

    /* 【穴埋め問題1】
    ここにプレイヤーのターンを処理するplayerTurnメソッドを定義し、プレイヤーが1〜3個の石を取る処理を書いてください。
    また、不正な入力があった場合には再度入力を促す処理も含めてください。
    */

    /* 【穴埋め問題2】
    ここにコンピュータのターンを処理するcomputerTurnメソッドを定義し、ランダムに1〜3個の石を取る処理を書いてください。
    コンピュータが取る石の数は残りの石の数以内である必要があります。
    */

    /* 【穴埋め問題3】
    ここに勝敗判定を行うisGameOverメソッドを定義し、残りの石が0個であればゲームが終了する処理を書いてください。
    プレイヤー名を表示して、どちらが負けたかを知らせてください。
    */
}

この問題の穴埋めコードは以上です。

このヒントを見てもまだ回答を導き出すのが難しいと感じる場合は、先に正解のコードと解説を見て内容を理解するようにしましょう。

解答例と解説

この問題の一つの正解例とそのコードの解説を以下に示します。

正解コードの例

例えば以下のようなプログラムが考えられます。

import java.util.Random;
import java.util.Scanner;

public class StoneGame {

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        Random random = new Random();

        int stones = 15; // 初期の石の数
        System.out.println("=== 石取りゲーム ===");
        System.out.println("石の数: " + stones);
        System.out.println("1ターンに1〜3個の石を取ることができます。");
        System.out.println("最後の石を取った方が負けです。");

        while (stones > 0) {
            // プレイヤーのターン
            stones = playerTurn(stones, scanner);

            // 勝敗判定
            if (isGameOver(stones, "あなた")) {
                break;
            }

            // コンピュータのターン
            stones = computerTurn(stones, random);

            // 勝敗判定
            if (isGameOver(stones, "コンピュータ")) {
                break;
            }
        }
    }

    // プレイヤーのターンを処理するメソッド
    public static int playerTurn(int stones, Scanner scanner) {
        System.out.print("取る石の数 (1〜3) を入力してください: ");
        int playerMove = scanner.nextInt();

        while (playerMove < 1 || playerMove > 3 || playerMove > stones) {
            System.out.print("無効な入力です。再度1〜3の範囲で入力してください: ");
            playerMove = scanner.nextInt();
        }

        stones -= playerMove;
        System.out.println("あなたは " + playerMove + " 個の石を取りました。残りの石: " + stones);
        return stones;
    }

    // コンピュータのターンを処理するメソッド
    public static int computerTurn(int stones, Random random) {
        int computerMove = Math.min(random.nextInt(3) + 1, stones);
        stones -= computerMove;
        System.out.println("コンピュータは " + computerMove + " 個の石を取りました。残りの石: " + stones);
        return stones;
    }

    // 勝敗判定を行うメソッド
    public static boolean isGameOver(int stones, String playerName) {
        if (stones == 0) {
            System.out.println(playerName + "の負けです!");
            return true;
        }
        return false;
    }
}

正解コードの解説

以下にJavaで作成された石取りゲームの初心者向けの解説を行います。

この解説ではコードをブロックごとに分割し、各ブロックで使用されている文法とその意味について説明します。

パッケージのインポートとメインクラスの宣言

import java.util.Random;
import java.util.Scanner;

public class StoneGame {
  1. import java.util.Random;import java.util.Scanner;:
    • これは、JavaのライブラリからRandomScannerクラスをインポートしています。Randomクラスは乱数(ランダムな数)を生成するために使い、Scannerクラスはユーザーからの入力を読み取るために使用します。
  2. public class StoneGame {:
    • StoneGameという名前のクラスを定義しています。このクラスの中に、ゲームの全ての処理を記述します。

メインメソッドと初期設定

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        Random random = new Random();

        int stones = 15; // 初期の石の数
        System.out.println("=== 石取りゲーム ===");
        System.out.println("石の数: " + stones);
        System.out.println("1ターンに1〜3個の石を取ることができます。");
        System.out.println("最後の石を取った方が負けです。");
  1. public static void main(String[] args):
    • Javaプログラムの実行が始まる「エントリーポイント」です。mainメソッドが呼び出され、ゲームが開始されます。
  2. Scanner scanner = new Scanner(System.in);Random random = new Random();:
    • scannerはユーザーからの入力を受け取るために使います。
    • randomはコンピュータのターンでランダムな数を生成するために使用します。
  3. int stones = 15;:
    • stonesは残りの石の数を示す変数で、初期値を15に設定しています。
  4. System.out.println(...):
    • ゲームのルールや石の数を表示します。

ゲームのループ処理

        while (stones > 0) {
            stones = playerTurn(stones, scanner);

            if (isGameOver(stones, "あなた")) {
                break;
            }

            stones = computerTurn(stones, random);

            if (isGameOver(stones, "コンピュータ")) {
                break;
            }
        }
    }
  1. while (stones > 0):
    • 石がまだ残っている間、ループを繰り返してゲームを続けます。
  2. stones = playerTurn(stones, scanner);:
    • プレイヤーのターンを実行するためのメソッドplayerTurnを呼び出します。戻り値で石の数が更新されます。
  3. if (isGameOver(stones, "あなた")) { break; }:
    • isGameOverメソッドを使ってゲーム終了の判定を行い、プレイヤーが最後の石を取った場合にはゲームを終了します。

プレイヤーのターン処理

    public static int playerTurn(int stones, Scanner scanner) {
        System.out.print("取る石の数 (1〜3) を入力してください: ");
        int playerMove = scanner.nextInt();

        while (playerMove < 1 || playerMove > 3 || playerMove > stones) {
            System.out.print("無効な入力です。再度1〜3の範囲で入力してください: ");
            playerMove = scanner.nextInt();
        }

        stones -= playerMove;
        System.out.println("あなたは " + playerMove + " 個の石を取りました。残りの石: " + stones);
        return stones;
    }
  1. System.out.print(...)scanner.nextInt();:
    • プレイヤーに1〜3の石を選ぶように入力を求め、nextIntで数値を取得します。
  2. whileループ:
    • 1〜3の範囲外、または残りの石より多く取る選択をした場合、再度正しい入力を求めます。
  3. stones -= playerMove;:
    • 石の数を更新し、選択した石の数だけ減らします。

コンピュータのターン処理

    public static int computerTurn(int stones, Random random) {
        int computerMove = Math.min(random.nextInt(3) + 1, stones);
        stones -= computerMove;
        System.out.println("コンピュータは " + computerMove + " 個の石を取りました。残りの石: " + stones);
        return stones;
    }

random.nextInt(3) + 1:1〜3のランダムな数を生成します。Math.minを使って残りの石が少ない場合に3以上取らないようにしています。

勝敗判定

    public static boolean isGameOver(int stones, String playerName) {
        if (stones == 0) {
            System.out.println(playerName + "の負けです!");
            return true;
        }
        return false;
    }
}

isGameOverメソッド:stonesが0になったときに敗者を判定し、ゲームが終了したことを表示します。

まとめ

このプログラムは石を1〜3個ずつ取り合い、最後の石を取った方が負けとなるシンプルなゲームです。

プログラムの流れやループ処理を理解することで、初心者でも基本的なJavaの構造やループ・条件文の使い方を学ぶことができます。

ぜひこのゲームの仕組みを参考に、自分で異なる条件やルールのゲームを作ってみましょう。

JAVAのゲームコード一覧はこちら

<<前のページ 問題集Top 次のページ>>

この記事への質問・コメント

この記事を作成するにあたりAIを活用しています。

問題ないことは確認していますが、もし間違いや表現の違和感などありましたら、ご指摘頂けると大変助かります。






    JAVAテキスト&問題集へ戻る
    トップページへ戻る