【JAVA】確認問題4-☆1:ナインゲームを作ろう

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

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

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

<<前のページ JAVA Topへ
次のページ>>

JAVA練習問題3-☆1:ナインゲームを作ろう

ナインゲームはプレイヤーとコンピュータが対戦するゲームです。

このゲームではプレイヤーとコンピュータが1から9までの数字の牌を持ち、それぞれのターンで1つの牌を出して勝負します。

大きい数字の牌を出した方がその数字と同じ点数を獲得し、一度出した牌は再度使用できません。

全ての牌を出し終えた時点でより多くの得点を持っている方が勝利です。

この問題の要件

以下の要件に従ってプログラムを作成してください。

  • ゲーム開始時に「ナインゲームを開始します!」と表示すること。
  • プレイヤーとコンピュータは最初に1から9までの数字の牌を持つこと。
  • 各ターンでプレイヤーが出す牌を入力し、コンピュータが出す牌はランダムに選択すること。
  • 牌を出す前に両者の現在の得点を表示すること。
  • プレイヤーが牌を選択する前に、両者の持っている牌を表示すること。持っていない牌は「-」と表示すること。
  • 牌を選択した後、両者が出した牌を比較し、大きい数字を出した方にその数字と同じ得点を加算すること。
  • 勝負の結果を表示すること。
  • 全ての牌を出し終えたら最終的な得点を比較し、勝者を表示すること。

ただし、以下のような実行結果となること。

----- ↓出力される結果の例↓ -----

ナインゲームを開始します!

【第1回戦】
プレイヤーの得点 : 0点
コンピュータの得点: 0点
☆プレイヤーの持ち牌⇒【1 2 3 4 5 6 7 8 9 】
コンピュータの持ち牌⇒【1 2 3 4 5 6 7 8 9 】
持ち牌の中から出す牌を選択してください > 7
プレイヤーの打牌:7 > 3:コンピュータの打牌
プレイヤーは7点獲得

【第2回戦】
プレイヤーの得点 : 7点
コンピュータの得点: 0点
☆プレイヤーの持ち牌⇒【1 2 3 4 5 6 - 8 9 】
コンピュータの持ち牌⇒【1 2 3 4 5 6 - 8 9 】
持ち牌の中から出す牌を選択してください > 4
プレイヤーの打牌:4 < 8:コンピュータの打牌
コンピュータは8点獲得

...

ゲーム終了!
プレイヤーの得点 : 20点
コンピュータの得点: 25点
コンピュータの勝利です!

この問題を解くヒント

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

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

正解のコードは上から順に以下のような構成となっています。

1:ArrayList、Random、Scannerクラスをインポート
2:NineGameクラスの定義
  □ mainメソッドの定義
  □ □ Scannerオブジェクトscannerの初期化
  □ □ Randomオブジェクトrandomの初期化
  □ □ ArrayListオブジェクトplayerTilesの初期化
  □ □ ArrayListオブジェクトcomputerTilesの初期化
  □ □ forループを1から9まで繰り返してplayerTilesとcomputerTilesに値を追加
  □ □ 変数playerScoreに0を代入
  □ □ 変数computerScoreに0を代入
  □ □ 「ナインゲームを開始します!」と出力
  □ □ forループを1から9まで繰り返す
  □ □ □ 「第{round}回戦」と出力
  □ □ □ プレイヤーとコンピュータの得点を出力
  □ □ □ displayTilesメソッドでプレイヤーの持ち牌を表示
  □ □ □ displayTilesメソッドでコンピュータの持ち牌を表示
  □ □ □ プレイヤーの牌を選択するための無限ループ開始
  □ □ □ □ 「持ち牌の中から出す牌を選択してください」と出力
  □ □ □ □ scanner.nextInt()で入力を取得し、playerChoiceに代入
  □ □ □ □ if文でplayerChoiceがplayerTilesに含まれているか判定
  □ □ □ □ □ 真の場合、playerTilesから選択した牌を-1に設定してループを終了
  □ □ □ □ □ 偽の場合、「無効な選択です。再度選択してください。」と出力
  □ □ □ コンピュータの牌を選択するための無限ループ開始
  □ □ □ □ random.nextIntでランダムな牌を選択し、computerChoiceに代入
  □ □ □ □ if文でcomputerChoiceが-1でないか判定
  □ □ □ □ □ 真の場合、computerTilesから選択した牌を-1に設定してループを終了
  □ □ □ 「プレイヤーの打牌:」とplayerChoiceを出力
  □ □ □ if文でplayerChoiceとcomputerChoiceを比較
  □ □ □ □ 真の場合、playerChoiceが大きいのでプレイヤーがplayerChoice点を獲得し、プレイヤーの得点を出力
  □ □ □ elif文でplayerChoiceがcomputerChoiceより小さいか判定
  □ □ □ □ 真の場合、computerChoice点をコンピュータが獲得し、コンピュータの得点を出力
  □ □ □ else文
  □ □ □ □ 両者が同点のため「引き分けです。得点はなし」と出力
  □ □ 「ゲーム終了!」と出力
  □ □ プレイヤーとコンピュータの最終得点を出力
  □ □ if文でプレイヤーの得点とコンピュータの得点を比較
  □ □ □ 真の場合、「プレイヤーの勝利です!」と出力
  □ □ elif文でプレイヤーの得点がコンピュータの得点より少ないか判定
  □ □ □ 真の場合、「コンピュータの勝利です!」と出力
  □ □ else文
  □ □ □ 「引き分けです!」と出力
  □ □ scannerを閉じる
  □ displayTilesメソッドの定義
  □ □ 引数titleを出力
  □ □ forループでtilesリストを走査
  □ □ □ if文で値が-1か判定
  □ □ □ □ 真の場合、「-」を出力
  □ □ □ □ 偽の場合、値を出力
  □ □ 「】」と出力して持ち牌の表示を終了

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

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

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

public class NineGame {

    public static void main(String[] args) {
        /* 【穴埋め問題1】
           ここにScannerとRandomクラスのオブジェクトをそれぞれ初期化するコードを書いてください。
        */

        /* 【穴埋め問題2】
           ここにArrayListを使ってplayerTilesとcomputerTilesを初期化するコードを書いてください。
        */

        /* 【穴埋め問題3】
           forループを使って、playerTilesとcomputerTilesの両方に1から9までの値を追加するコードを書いてください。
        */

        int playerScore = 0;
        int computerScore = 0;

        System.out.println("ナインゲームを開始します!");

        for (int round = 1; round <= 9; round++) {
            System.out.println("\n【第" + round + "回戦】");
            System.out.println("プレイヤーの得点 : " + playerScore + "点");
            System.out.println("コンピュータの得点: " + computerScore + "点");

            /* 【穴埋め問題4】
               displayTilesメソッドを呼び出して、プレイヤーの持ち牌を表示してください。
            */

            /* 【穴埋め問題5】
               displayTilesメソッドを呼び出して、コンピュータの持ち牌を表示してください。
            */

            // プレイヤーの牌を選択
            int playerChoice;
            while (true) {
                System.out.print("持ち牌の中から出す牌を選択してください > ");
                /* 【穴埋め問題6】
                   scannerを使ってplayerChoiceに値を代入し、選択された牌を-1に設定するコードを書いてください。
                   無効な選択が行われた場合には再度選択を求めるようにしてください。
                */
            }

            // コンピュータの牌を選択
            int computerChoice;
            while (true) {
                /* 【穴埋め問題7】
                   randomを使用してcomputerTilesからランダムな牌を選択し、選択された牌を-1に設定するコードを書いてください。
                */
            }

            // 両者の牌を比較
            System.out.print("プレイヤーの打牌:" + playerChoice);
            if (playerChoice > computerChoice) {
                System.out.println(" > " + computerChoice + ":コンピュータの打牌");
                /* 【穴埋め問題8】
                   プレイヤーの得点にplayerChoiceを加算し、得点を出力するコードを書いてください。
                */
            } else if (playerChoice < computerChoice) {
                System.out.println(" < " + computerChoice + ":コンピュータの打牌");
                /* 【穴埋め問題9】
                   コンピュータの得点にcomputerChoiceを加算し、得点を出力するコードを書いてください。
                */
            } else {
                System.out.println(" = " + computerChoice + ":コンピュータの打牌");
                System.out.println("引き分けです。得点はなし");
            }
        }

        // 最終結果を表示
        System.out.println("\nゲーム終了!");
        System.out.println("プレイヤーの得点 : " + playerScore + "点");
        System.out.println("コンピュータの得点: " + computerScore + "点");

        /* 【穴埋め問題10】
           if文を使ってプレイヤーの得点とコンピュータの得点を比較し、勝敗または引き分けを出力するコードを書いてください。
        */
    }

    // 持ち牌を表示するメソッド
    private static void displayTiles(String title, ArrayList<Integer> tiles) {
        System.out.print(title + "⇒【");
        for (int i = 0; i < tiles.size(); i++) {
            if (tiles.get(i) == -1) {
                System.out.print("- ");
            } else {
                System.out.print(tiles.get(i) + " ");
            }
        }
        System.out.println("】");
    }
}

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

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

解答例

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

正解コードの例

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

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

public class NineGame {

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

        ArrayList<Integer> playerTiles = new ArrayList<>();
        ArrayList<Integer> computerTiles = new ArrayList<>();

        for (int i = 1; i <= 9; i++) {
            playerTiles.add(i);
            computerTiles.add(i);
        }

        int playerScore = 0;
        int computerScore = 0;

        System.out.println("ナインゲームを開始します!");

        for (int round = 1; round <= 9; round++) {
            System.out.println("\n【第" + round + "回戦】");
            System.out.println("プレイヤーの得点 : " + playerScore + "点");
            System.out.println("コンピュータの得点: " + computerScore + "点");

            displayTiles("☆プレイヤーの持ち牌", playerTiles);
            displayTiles("コンピュータの持ち牌", computerTiles);

            // プレイヤーの牌を選択
            int playerChoice;
            while (true) {
                System.out.print("持ち牌の中から出す牌を選択してください > ");
                playerChoice = scanner.nextInt();
                if (playerTiles.contains(playerChoice)) {
                    playerTiles.set(playerTiles.indexOf(playerChoice), -1);
                    break;
                } else {
                    System.out.println("無効な選択です。再度選択してください。");
                }
            }

            // コンピュータの牌を選択
            int computerChoice;
            while (true) {
                computerChoice = computerTiles.get(random.nextInt(computerTiles.size()));
                if (computerChoice != -1) {
                    computerTiles.set(computerTiles.indexOf(computerChoice), -1);
                    break;
                }
            }

            // 両者の牌を比較
            System.out.print("プレイヤーの打牌:" + playerChoice);
            if (playerChoice > computerChoice) {
                System.out.println(" > " + computerChoice + ":コンピュータの打牌");
                playerScore += playerChoice;
                System.out.println("プレイヤーは" + playerChoice + "点獲得");
            } else if (playerChoice < computerChoice) {
                System.out.println(" < " + computerChoice + ":コンピュータの打牌");
                computerScore += computerChoice;
                System.out.println("コンピュータは" + computerChoice + "点獲得");
            } else {
                System.out.println(" = " + computerChoice + ":コンピュータの打牌");
                System.out.println("引き分けです。得点はなし");
            }
        }

        // 最終結果を表示
        System.out.println("\nゲーム終了!");
        System.out.println("プレイヤーの得点 : " + playerScore + "点");
        System.out.println("コンピュータの得点: " + computerScore + "点");

        if (playerScore > computerScore) {
            System.out.println("プレイヤーの勝利です!");
        } else if (playerScore < computerScore) {
            System.out.println("コンピュータの勝利です!");
        } else {
            System.out.println("引き分けです!");
        }

    }

    // 持ち牌を表示するメソッド
    private static void displayTiles(String title, ArrayList<Integer> tiles) {
        System.out.print(title + "⇒【");
        for (int i = 0; i < tiles.size(); i++) {
            if (tiles.get(i) == -1) {
                System.out.print("- ");
            } else {
                System.out.print(tiles.get(i) + " ");
            }
        }
        System.out.println("】");
    }
}

正解コードの解説

このコードではプレイヤーとコンピュータが1から9の牌を使って対戦する「ナインゲーム」を実装しています。

コードの各部分をブロックごとに解説し、Javaの基本的な文法や処理の流れを学んでいきましょう。

クラスとメインメソッドの開始

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

public class NineGame {
    public static void main(String[] args) {

最初にimport文でArrayListRandomScannerというクラスを取り込んでいます。

これらのクラスはそれぞれリスト操作、ランダムな値の生成、ユーザーからの入力を扱うために必要です。

mainメソッドはJavaプログラムの開始点であり、ここからゲームの実行が始まります。

スキャナー、ランダム、リストの初期化

        Scanner scanner = new Scanner(System.in);
        Random random = new Random();

        ArrayList<Integer> playerTiles = new ArrayList<>();
        ArrayList<Integer> computerTiles = new ArrayList<>();

Scannerオブジェクトでユーザー入力を受け取り、Randomオブジェクトでランダムな数を生成します。

またArrayListを使ってプレイヤーとコンピュータの持ち牌をリスト形式で管理します。

持ち牌の追加

        for (int i = 1; i <= 9; i++) {
            playerTiles.add(i);
            computerTiles.add(i);
        }

ここではforループを使い、1から9までの数字をそれぞれプレイヤーとコンピュータの持ち牌リストに追加しています。

スコアの初期化

        int playerScore = 0;
        int computerScore = 0;

playerScorecomputerScoreという変数を0で初期化し、ゲーム中に得点を加算するための準備をしています。

各ラウンドの進行

        for (int round = 1; round <= 9; round++) {
            System.out.println("\n【第" + round + "回戦】");
            System.out.println("プレイヤーの得点 : " + playerScore + "点");
            System.out.println("コンピュータの得点: " + computerScore + "点");

ここでは9回戦を行うためのループ処理を行っています。

各ラウンドの始めにラウンド番号と現在の得点を表示します。

持ち牌の表示

            displayTiles("☆プレイヤーの持ち牌", playerTiles);
            displayTiles("コンピュータの持ち牌", computerTiles);

プレイヤーとコンピュータの持ち牌を表示するため、displayTilesメソッドを呼び出しています。

このメソッドは牌の状態を一覧で表示する役割を果たします。

プレイヤーの牌を選択

            int playerChoice;
            while (true) {
                System.out.print("持ち牌の中から出す牌を選択してください > ");
                playerChoice = scanner.nextInt();
                if (playerTiles.contains(playerChoice)) {
                    playerTiles.set(playerTiles.indexOf(playerChoice), -1);
                    break;
                } else {
                    System.out.println("無効な選択です。再度選択してください。");
                }
            }

プレイヤーはリストに含まれている牌を選びます。

選択された牌は-1に置き換えられ、再度選択できないようにします。無効な選択をした場合には再入力を求めます。

コンピュータの牌をランダムに選択

            int computerChoice;
            while (true) {
                computerChoice = computerTiles.get(random.nextInt(computerTiles.size()));
                if (computerChoice != -1) {
                    computerTiles.set(computerTiles.indexOf(computerChoice), -1);
                    break;
                }
            }

コンピュータはランダムに牌を選び、選択された牌も-1に置き換えます。

これにより同じ牌を複数回使うことを防ぎます。

牌の比較と得点計算

            System.out.print("プレイヤーの打牌:" + playerChoice);
            if (playerChoice > computerChoice) {
                System.out.println(" > " + computerChoice + ":コンピュータの打牌");
                playerScore += playerChoice;
                System.out.println("プレイヤーは" + playerChoice + "点獲得");
            } else if (playerChoice < computerChoice) {
                System.out.println(" < " + computerChoice + ":コンピュータの打牌");
                computerScore += computerChoice;
                System.out.println("コンピュータは" + computerChoice + "点獲得");
            } else {
                System.out.println(" = " + computerChoice + ":コンピュータの打牌");
                System.out.println("引き分けです。得点はなし");
            }

プレイヤーとコンピュータの打牌を比較し、得点を計算します。

プレイヤーの牌が大きければプレイヤーに得点が入り、コンピュータが大きければコンピュータに得点が入ります。

同点の場合は引き分けとして得点は入りません。

ゲームの終了と最終結果の表示

        System.out.println("\nゲーム終了!");
        System.out.println("プレイヤーの得点 : " + playerScore + "点");
        System.out.println("コンピュータの得点: " + computerScore + "点");

        if (playerScore > computerScore) {
            System.out.println("プレイヤーの勝利です!");
        } else if (playerScore < computerScore) {
            System.out.println("コンピュータの勝利です!");
        } else {
            System.out.println("引き分けです!");
        }

ゲームが終了すると、プレイヤーとコンピュータの最終得点が表示され、勝敗または引き分けの結果が発表されます。

持ち牌表示メソッド

    private static void displayTiles(String title, ArrayList<Integer> tiles) {
        System.out.print(title + "⇒【");
        for (int i = 0; i < tiles.size(); i++) {
            if (tiles.get(i) == -1) {
                System.out.print("- ");
            } else {
                System.out.print(tiles.get(i) + " ");
            }
        }
        System.out.println("】");
    }
}

displayTilesメソッドは持ち牌のリストを表示するためのメソッドです。

-1の部分は「-」として表示され、使用可能な牌だけが数字として見えるようになっています。

まとめ

この「ナインゲーム」のコードを通じて、ArrayListの使用法、Randomクラスによるランダムな値の生成、if文による条件分岐、forループを使った繰り返し処理など、Javaの基礎的な文法を学ぶことができました。

初心者の方はこのコードを改良したり、他の条件分岐や得点ルールを追加して、自分だけのゲームを作成する楽しさを体験してください。

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

<<前のページ JAVA Topへ 次のページ>>

この問題への質問・コメント

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

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






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