【演習】[Java入門] コンソールアプリを作って基礎知識を習得しよう! ③解説編(一番詳しく説明)

本記事では、Javaコンソールアプリ演習問題のコーディング方法を解説します。
演習問題が難しくてできなかった方は、解説を読んでプログラムを作成する手順や方法を参考にしてください。

演習問題が解けた方は、自分以外が作ったプログラムを読んで、自分とは異なる実装方法に触れて、新しい知識を得る機会にしてもらえればと思います。


演習問題の内容説明を見ていない方は、以下の記事で紹介しているので、そちらを先に御覧ください。


本記事の内容は、以下の方におすすめです。

おすすめ対象者
  • 演習問題の解説をみたい
  • プログラムの基本構文の使い方をコーディングしながら学びたい
  • プログラマーがプログラムを作成する手順を詳しく知りたい
  • 自分以外の人が作ったプログラムを見て勉強したい

本記事では、以下のスキルについて学ぶことができます。

学べるスキル
  • プログラムの基本構文
    変数、関数、引数、戻り値、繰り返し文(for、while)、条件文(if)、リスト
  • コーディングの順序
  • 処理の関数化
  • データの管理方法

今回の解説方法は、実際に私がコーディングする流れで説明していきます。
プログラマーがどういう単位で処理を分割してどういう順番でコーディングしていくか、などが伝わりやすくなればいいなと思っています。

それでは、演習問題の解説を見ていきましょう!

目次

完成プログラム

プログラムソース

解説用の完成プログラムソースを貼っておきます。
このソースが完成するまでの手順を説明していきます。
※ソースが長いので開閉できるようにしておきます。

プログラム構成

今回作成したクラスと関数の関連図を以下に記載します。

クラス

今回は、以下のクラスを作成することにしました。

作成するクラスの一覧
作成するクラスの一覧

関数

プログラムの関数は、以下のような関連性になっています。

関数の関連図
関数の関連図

すごろくゲームのフローチャート

プログラムのコーディングに入る前に、すごろくゲームのフローチャートを確認しておきましょう。

※フローチャートの作成方法は、以下の記事を参考にしてください。

すごろくゲームのフローチャート
すごろくゲームのフローチャート

上記のフローチャートを大きく2つの処理に分割して、シンプルな構成で考えるようにします。
※プログラムは、すべての処理を一気に作るのではなく機能や処理ごとに分けて作成していきます。
一気に作ろうとすると考える範囲が大きくなり、頭が混乱して迷子になります。

フローチャートを分割
  • フロー①:ゲームコントロール処理 ※[緑の点線部分]
  • フロー②:ゲームプレイ処理 ※[赤の点線部分]

分割したフローチャートは以下になります。

フローチャートを分割 フロー①
フローチャートを分割
ゲームコントロール処理
フローチャートを分割 フロー②
フローチャートを分割
ゲームプレイ処理

少しスッキリした気がしませんか?

ゲームコントロール処理を作成して、
ゲームプレイ処理を作成して、
ゲームコントロール処理からゲームプレイ処理を呼び出すといった実装ができそうですね。

フローチャートが確認できたら、コーディングに入りましょう!

Gameクラスを作成

最初に、Gameクラスを作成して[startUp] 関数を宣言します。
※クラスの作成方法がわからない場合は、以下の記事を参考にしてください。

public class Game {
    /**
     * ゲーム起動
     */
    public void startUp(){
        System.out.println("Game startUp start");

        System.out.println("Game startUp end");
    }
}

次に、Appクラスの[main] 関数から、Gameクラスの[startUp] 関数を呼び出します。

public class App {
    public static void main(String[] args) throws Exception {
        // ゲーム起動
        new Game().startUp();
    }
}

ここまでの状態でプログラムを実行すると、Gameクラスの[startUp] 関数の処理が実行されて、
コンソールに以下の内容が出力されたと思います。

 Game startUp start
 Game startUp end

プログラムの実行方法がわからない場合は、以下の記事を参考にしてください。

すごろくゲームの処理は、Gameクラスの[startUp] 関数に作っていきます!

ゲームコントロール処理を作成しよう!

今回は初めにゲームコントロール処理を作成していきます。

以下のフローチャートに従って、各処理を作成します。

ゲームコントロール処理のフローチャート
ゲームコントロール処理のフローチャート

それでは、ゲームコントロール処理のプログラム作成方法を解説していきます。

ゲームループを追加

はじめに、ゲームループを実装する方法を解説していきます。

改修内容

ゲーム終了が選択されるまで繰り返して処理を実行したいので、ループ処理を作成する。

改修箇所

ゲームループを追加
ゲームループを追加

改修ソース

※ハイライト部分を改修
    /**
     * ゲーム起動
     */
    public void startUp(){
        System.out.println("Game startUp start");

        //===============
        // ゲームループ
        //===============
        boolean isGameContinue = true; // ゲーム継続フラグ(true:継続/false:終了)

        while(isGameContinue){
            
        }

        System.out.println("Game startUp end");
    }

改修ソースの解説

boolean isGameContinue = true; // ゲーム継続フラグ(true:継続/false:終了)

whileのループ継続判定用に 「(boolean変数)ゲーム継続フラグ」を宣言する。

変数に入る内容true:継続/false:終了
初期値true:継続

while(isGameContinue){
}

ループの回数が決まっていないので、while を使ってループ処理をつくる。

ループ条件「ゲーム継続フラグ(isGameContinue)」 の値が「false」 になるまで

※ゲーム終了が選択された時に、「ゲーム継続フラグfalse」を代入することで、このループから抜ける!

[ゲーム開始選択] 処理を追加

ゲーム開始選択処理の実装方法を解説していきます。

改修STEP
改修

① [ゲーム開始選択] 関数を呼び出す

改修

② Gameクラスに[ゲーム開始選択] 関数を作成する

改修箇所

[ゲーム開始選択] 関数を呼び出す
[ゲーム開始選択] 関数を呼び出す

① [ゲーム開始選択] 関数を呼び出す

改修内容

  • [ゲームループ]の中で、[ゲーム開始選択] 関数を呼び出す。
  • [ゲーム開始選択] 関数からの戻り値を変数に受け取る。

改修ソース

※ハイライト部分を改修
    /**
     * ゲーム起動
     */
    public void startUp(){
        System.out.println("Game startUp start");

        //===============
        // ゲームループ
        //===============
        boolean isGameContinue = true; // ゲーム継続フラグ(true:継続/false:終了)

        while(isGameContinue){
            //----------------
            // ゲーム開始選択
            //----------------
            int selectedGameStart = 0; // ゲーム開始選択値(1:開始/1以外:終了)
            selectedGameStart = this.selectGameStart();
            
        }

        System.out.println("Game startUp end");
    }

改修ソースの解説

int selectedGameStart = 0; // ゲーム開始選択値(1:開始/1以外:終了)

コンソールからの入力値(ゲーム開始または終了)を保持する、「(int変数)ゲーム開始選択値」を宣言する。

変数に入る内容1:開始/1以外:終了
初期値0:終了

selectedGameStart = this.selectGameStart();

[ゲーム開始選択] 関数を呼び出して、戻り値を「(変数)ゲーム開始選択値」に代入する。
※thisはGameクラス自身のこと。自身のメンバー変数や関数を扱うときはthisを付けます。

② Gameクラスに[ゲーム開始選択] 関数を作成する

改修内容

  • [ゲーム開始選択] 関数を作成する。
  • [関数の処理内容]
    ・コンソールにゲーム開始、または終了を選択するメッセージを表示する。
    ・コンソールからの入力値をプログラムで受け取る。
    ・上記で受け取った入力値を、この関数を呼び出したところに戻り値で返す。
ゲーム開始選択の詳細
ゲーム開始選択の詳細
コンソール出力メッセージ
****************************
*
* すごろくゲーム
*
****************************
★キーボードから以下の数値を入力してください。
  [1]:ゲームを開始する。
  [1以外]:ゲームを終了する。

改修ソース

[ゲーム開始選択] 関数の作成場所

関数を作成する場所は、以下のハイライト部分になります。
※Gameクラスの中で、startUp関数の外です。

public class Game {
    /**
     * ゲーム起動
     */
    public void startUp(){
        ~~ 省略 ~~
    }

    ※ここに[ゲーム開始選択] 関数を作成します!

}

[ゲーム開始選択] 関数

※ハイライト部分を改修
    /**
     * コンソールでゲーム開始または終了を選択する
     * @return コンソールで入力した数値
     */
    private int selectGameStart(){
        // 選択要求メッセージ
        String requestMsg = "";
        requestMsg = ""
            + "\n"
            + "\n" + "****************************"
            + "\n" + "*"
            + "\n" + "* すごろくゲーム"
            + "\n" + "*"
            + "\n" + "****************************"
            + "\n" + "★ キーボードから以下の数値を入力してください。"
            + "\n" + "  [1]:ゲームを開始する。"
            + "\n" + "  [1以外]:ゲームを終了する。"
            + "\n"
            ;

        System.out.println(requestMsg);

        //コンソールから入力値を受け取る
        Scanner sc = new Scanner(System.in);
        int inputNo  = sc.nextInt();
        
        return inputNo;
    }

改修ソースの解説

private int selectGameStart(){
}

関数を定義する。

引数なし
戻り値コンソールから入力した数値

String requestMsg = "";
requestMsg = ""
        + "\n"
        + "\n" + "****************************"
        + "\n" + "*"
        + "\n" + "* すごろくゲーム"
        + "\n" + "*"
        + "\n" + "****************************"
        + "\n" + "★ キーボードから以下の数値を入力してください。"
        + "\n" + "  [1]:ゲームを開始する。"
        + "\n" + "  [1以外]:ゲームを終了する。"
        + "\n"
        ;

コンソールに出力するメッセージを「(String変数)requestMsg」に代入する。
 ※「\n」という改行コードを使用すると改行できます。
 ※「文字列 + 文字列」 で文字列を結合できます。


System.out.println(requestMsg);

System.out.println関数を使用して、コンソールにメッセージを出力する。


//コンソールから入力値を受け取る
Scanner sc = new Scanner(System.in);
int inputNo  = sc.nextInt();

①Scannerクラスのインスタンスを生成する。
②ScannerクラスのnextInt関数を使ってコンソールから入力された値を変数に受け取る。

※Scannerクラスを使用するためには、java.util.Scannerをimportする必要があります。
 ページの最上部に import java.util.Scanner; を記述する。
※Scannerクラスは、キーボードからの入力を受け取ったり、ファイルの内容を読み込むことができます。


return inputNo;

最後にコンソールから入力された値を、戻り値で返す。

ゲーム開始、ゲーム終了の処理分岐を追加

改修内容

[ゲーム開始選択] 処理で、コンソールから入力された数値によって処理を分岐する。
 分岐1:ゲーム開始が選択された場合のルート
 分岐2:ゲーム終了が選択された場合のルート

改修箇所

ゲーム開始と終了で分岐
ゲーム開始と終了で分岐

改修ソース

※ハイライト部分を改修
    /**
     * ゲーム起動
     */
    public void startUp(){
        System.out.println("Game startUp start");

        //===============
        // ゲームループ
        //===============
        boolean isGameContinue = true; // ゲーム継続フラグ(true:継続/false:終了)

        while(isGameContinue){
            //----------------
            // ゲーム開始選択
            //----------------
            int selectedGameStart = 0; // ゲーム開始選択値(1:開始/1以外:終了)
            selectedGameStart = this.selectGameStart();

            //-------------------
            // ゲーム開始終了分岐
            //-------------------
            // ゲーム終了(1以外)が入力された場合
            if(selectedGameStart != 1){
            }
            // ゲーム開始(1)が入力された場合
            else{
            }
        }

        System.out.println("Game startUp end");
    }

改修ソースの解説

if(selectedGameStart != 1){
}
else{
}

if で処理を分岐させる。

分岐①if(selectedGameStart != 1)「(変数)ゲーム開始選択値」が「1以外」
 ※ゲーム終了が選択された場合
分岐②else「(変数)ゲーム開始選択値」が「1」
 ※ゲーム開始が選択された場合

ゲーム終了が選択された場合の処理を追加

改修STEP
改修

① [ゲーム終了] 関数の呼び出し、ゲーム継続フラグを更新する

改修

② Gameクラスに[ゲーム終了] 関数を作成する

改修箇所

ゲームを終了する場合の処理を追加
ゲームを終了する場合の処理を追加

① [ゲーム終了] 関数の呼び出し、ゲーム継続フラグを更新する

改修内容

  • [ゲーム終了]関数を呼び出す。
  • 「(変数)ゲーム開始選択値」に「false」を代入する。
     ⇒ ここでfalseを代入することで、ゲームループから抜けることができる!

改修ソース

※ハイライト部分を改修
    /**
     * ゲーム起動
     */
    public void startUp(){
        System.out.println("Game startUp start");

        //===============
        // ゲームループ
        //===============
        boolean isGameContinue = true; // ゲーム継続フラグ(true:継続/false:終了)

        while(isGameContinue){
            //----------------
            // ゲーム開始選択
            //----------------
            int selectedGameStart = 0; // ゲーム開始選択値(1:開始/1以外:終了)
            selectedGameStart = this.selectGameStart();

            //-------------------
            // ゲーム開始終了分岐
            //-------------------
            // ゲーム終了(1以外)が入力された場合
            if(selectedGameStart != 1){
                //-------------------
                // ゲーム終了
                //-------------------
                this.printGameFinish();

                isGameContinue = false; // ゲーム継続フラグ(false:終了)
            }
            // ゲーム開始(1)が入力された場合
            else{
            }
        }

        System.out.println("Game startUp end");
    }

改修ソースの解説

this.printGameFinish();

[ゲーム終了] 関数を呼び出して、コンソールにゲーム終了メッセージを出力する。


isGameContinue = false; // ゲーム継続フラグ(false:終了)

ゲームループから抜けるため、「(変数)ゲーム開始選択値」に「false」を代入する。

② Gameクラスに[ゲーム終了] 関数を作成する

改修内容

  • [ゲーム終了] 関数を作成する。
  • [関数の処理内容]
    ・コンソールにゲーム終了のメッセージを表示する。
ゲーム終了処理の詳細
ゲーム終了処理の詳細
コンソール出力メッセージ
ゲームを終了しました。

改修ソース

関数を作成する場所は、[selectGameStart] 関数の下に作成します。
※Gameクラスの中で、他の関数の外であればどこに作成しても大丈夫です!

※ハイライト部分を改修
    /**
     * ゲーム終了のメッセージを出力する
     */
    private void printGameFinish(){
        // ゲーム終了メッセージ
        String printMsg = "";
        printMsg = ""
            + "\n"
            + "\n" + "ゲームを終了しました。"
            + "\n"
            ;

        System.out.println(printMsg);
    }

改修ソースの解説

private void printGameFinish(){
}

関数を定義する。

引数なし
戻り値コンソールから入力した数値

// ゲーム終了メッセージ
String printMsg = "";
printMsg = ""
    + "\n"
    + "\n" + "ゲームを終了しました。"
    + "\n"
    ;

System.out.println(printMsg);

①コンソールに出力するメッセージを「(String変数)printMsg」に代入する。
②System.out.println関数を使用して、コンソールにメッセージを出力する。

ゲーム開始が選択された場合の処理を追加

改修STEP
改修

① [ゲームプレイ] 関数の呼び出し、ゲーム継続フラグを更新する

改修

② Gameクラスに[ゲームプレイ] 関数を定義する

① [ゲームプレイ] 関数の呼び出し、ゲーム継続フラグを更新する

改修内容

  • [ゲームプレイ]関数を呼び出す。
  • 「(変数)ゲーム継続フラグ」に、[ゲームプレイ] 関数の戻り値を代入する。
    ※[ゲームプレイ]関数の戻り値は、以下を想定して作成する。
     ①ゴールに到達した場合は、false(ゲーム終了)
     ②途中終了した場合は、true(ゲーム継続)

     ⇒ false(ゲーム終了)を代入すると、ゲームループから抜ける!
     ⇒ true(ゲーム継続)を代入すると、ゲームループから抜けずに[ゲーム開始選択]から繰り返す。

改修箇所

ゲームを開始する場合の処理を追加
ゲームを開始する場合の処理を追加

改修ソース

※ハイライト部分を改修
    /**
     * ゲーム起動
     */
    public void startUp(){
        System.out.println("Game startUp start");

        //===============
        // ゲームループ
        //===============
        boolean isGameContinue = true; // ゲーム継続フラグ(true:継続/false:終了)

        while(isGameContinue){
            //----------------
            // ゲーム開始選択
            //----------------
            int selectedGameStart = 0; // ゲーム開始選択値(1:開始/1以外:終了)
            selectedGameStart = this.selectGameStart();

            //-------------------
            // ゲーム開始終了分岐
            //-------------------
            // ゲーム終了(1以外)が入力された場合
            if(selectedGameStart != 1){
                //-------------------
                // ゲーム終了
                //-------------------
                this.printGameFinish();

                isGameContinue = false; // ゲーム継続フラグ(false:終了)
            }
            // ゲーム開始(1)が入力された場合
            else{
                //-------------------
                // ゲームプレイ処理
                //-------------------
                // ゴールに到達した場合はfalse(終了)、途中終了した場合はtrue(継続)
                isGameContinue = this.playGame();
            }
        }

        System.out.println("Game startUp end");
    }

改修ソースの解説

isGameContinue = this.playGame();

[ゲームプレイ] 関数を呼び出して、戻り値を「(変数)ゲーム継続フラグ」に代入する。

② Gameクラスに[ゲームプレイ] 関数を定義する

改修内容

  • ゲームプレイ処理を実行する[ゲームプレイ] 関数を作成する。
  • [ゲームプレイ] 関数の戻り値は、ゲーム継続フラグを返す。
     ①ゴールに到達した場合は、false(ゲーム終了)
     ②途中終了した場合は、true(ゲーム継続)
ゲームプレイ処理の中身
ゲームプレイ処理の中身

改修ソース

関数を作成する場所は、[startUp] 関数の下に作成します。
※Gameクラスの中で、他の関数の外であればどこに作成しても大丈夫です!

※ハイライト部分を改修
    /**
     * ゲームプレイ
     * @return ゲーム継続フラグ(true:継続/false:終了)
     */
    private boolean playGame(){
        boolean isGameContinue = true; // ゲーム継続フラグ(true:継続/false:終了)
        
        return isGameContinue;
    }

改修ソースの解説

private boolean playGame(){
}

関数を定義する。

引数なし
戻り値ゲームを継続するか、終了するかを示す値(true:継続/false:終了)

boolean isGameContinue = true; // ゲーム継続フラグ(true:継続/false:終了)

関数の戻り値として返す「(変数)ゲーム継続フラグ」を宣言する。

変数に入る内容true:継続/false:終了
初期値true:継続

return isGameContinue;

最後に戻り値として「(変数)ゲーム継続フラグ」を返す。

ゲームプレイ処理を作成しよう!

次にゲームプレイ処理を作成していきます。

ゲームプレイ処理は、Gameクラスの[playGame] 関数に作っていきます!

以下のフローチャートに従って、各処理を作成します。

ゲームプレイ処理のフローチャート
ゲームプレイ処理のフローチャート

それでは、ゲームプレイ処理のプログラム作成方法を解説していきます。

行動ループを追加

改修内容

ゴールするまでは同じ処理を繰り返し実行したいので、ループ処理を作成する。

行動ループを追加
行動ループを追加

改修ソース

※ハイライト部分を改修
    /**
     * ゲームプレイ
     * @return ゲーム継続フラグ(true:継続/false:終了)
     */
    private boolean playGame(){
        boolean isGameContinue = true; // ゲーム継続フラグ(true:継続/false:終了)
        
        //===============
        // 行動ループ
        //===============
        boolean isActionContinue = true; // 行動継続フラグ(true:継続/false:終了)

        while(isActionContinue){
            
        }

        return isGameContinue;
    }

改修ソースの解説

boolean isActionContinue = true; // 行動継続フラグ(true:継続/false:終了)

whileのループ継続判定用に 「(boolean変数)行動継続フラグ」を宣言する。

変数に入る内容true:継続/false:終了
初期値true:継続

while(isActionContinue){
}

ループの回数が決まっていないので、while を使ってループ処理をつくる。

ループ条件「行動継続フラグ(isActionContinue)」の値が「false」 になるまで

※ゴールに到達した時に、「行動継続フラグ」に「false」を代入することで、このループから抜ける!

[移動、終了選択] 処理を追加

改修STEP
改修

① [移動、終了選択] 関数を呼び出す

改修

② Gameクラスに[移動、終了選択] 関数を作成する

① [移動、終了選択] 関数を呼び出す

改修内容

  • [行動ループ]の中で、[移動・終了選択] 関数を呼び出す。
  • [移動・終了選択] 関数からの戻り値を変数に受け取る。

改修箇所

[移動、終了選択] 関数を呼び出す
[移動、終了選択] 関数を呼び出す

改修ソース

※ハイライト部分を改修
    /**
     * ゲームプレイ
     * @return ゲーム継続フラグ(true:継続/false:終了)
     */
    private boolean playGame(){
        boolean isGameContinue = true; // ゲーム継続フラグ(true:継続/false:終了)
        
        //===============
        // 行動ループ
        //===============
        boolean isActionContinue = true; // 行動継続フラグ(true:継続/false:終了)

        while(isActionContinue){
            //----------------
            // 移動、終了選択
            //----------------
            int selectedMoveOrStop = 0; // 移動終了選択値(1:移動/1以外:途中終了)
            selectedMoveOrStop = this.selectMoveOrStop();
        }

        return isGameContinue;
    }

改修ソースの解説

int selectedMoveOrStop = 0; // 移動終了選択値(1:移動/1以外:途中終了)

コンソールからの入力値を保持する「(変数)移動終了選択値」を宣言する。

変数に入る内容1:移動/1以外:途中終了
初期値0:途中終了

selectedMoveOrStop = this.selectMoveOrStop();

[移動、終了選択] 関数を呼び出して、戻り値を「(変数)移動終了選択値」に代入する。

② Gameクラスに[移動、終了選択] 関数を作成する

改修内容

  • [移動、終了選択] 関数を作成する。
  • [関数の処理内容]
    ・コンソールに移動、または途中終了を選択するメッセージを表示する。
    ・コンソールからの入力値をプログラムで受け取る。
    ・上記で受け取った入力値を、この関数を呼び出したところに戻り値で返す。
移動、終了選択の詳細
移動、終了選択の詳細
コンソール出力メッセージ
★キーボードから以下の数値を入力してください。
  [1]:移動する。
  [9]:ゲームを途中で終了して、開始画面に戻る。

改修ソース

関数を作成する場所は、[printGameFinish] 関数の下に作成します。
※Gameクラスの中で、他の関数の外であればどこに作成しても大丈夫です!

※ハイライト部分を改修
    /**
     * コンソールで移動またはゲーム途中終了を選択する
     * @return コンソールで入力した数値
     */
    private int selectMoveOrStop(){
        // 選択要求メッセージ
        String requestMsg = "";
        requestMsg = ""
            + "\n"
            + "\n" + "★ キーボードから以下の数値を入力してください。"
            + "\n" + "  [1]:移動する。"
            + "\n" + "  [9]:ゲームを途中で終了して、開始画面に戻る。"
            + "\n"
            ;

        System.out.println(requestMsg);

        //コンソールから入力値を受け取る
        Scanner sc = new Scanner(System.in);
        int inputNo  = sc.nextInt();
        
        return inputNo;
    }

改修ソースの解説

private int selectMoveOrStop(){
}

関数を定義する。

引数なし
戻り値コンソールから入力した数値

Scanner sc = new Scanner(System.in);
int inputNo  = sc.nextInt();

return inputNo;

①ScannerクラスのnextInt関数を使ってコンソールから入力された値を変数に受け取る。
②最後にコンソールから入力された値を、戻り値で返す。

移動、途中終了の処理分岐を追加

改修内容

  • 移動が選択された場合と途中終了が選択された場合で処理を分岐する。
     分岐1:途中終了が選択された場合のルート
     分岐2:移動が選択された場合のルート
  • 途中終了が選択された場合のルートでは、行動ループから抜ける処理を追加する。

改修箇所

移動する場合と途中終了する場合で処理を分岐する
移動する場合と途中終了する場合で処理を分岐する

改修ソース

※ハイライト部分を改修
    /**
     * ゲームプレイ
     * @return ゲーム継続フラグ(true:継続/false:終了)
     */
    private boolean playGame(){
        boolean isGameContinue = true; // ゲーム継続フラグ(true:継続/false:終了)
        
        //===============
        // 行動ループ
        //===============
        boolean isActionContinue = true; // 行動継続フラグ(true:継続/false:終了)

        while(isActionContinue){
            //----------------
            // 移動、終了選択
            //----------------
            int selectedMoveOrStop = 0; // 移動終了選択値(1:移動/1以外:途中終了)
            selectedMoveOrStop = this.selectMoveOrStop();

            //-----------------
            // 移動途中終了分岐
            //-----------------
            // 途中終了(1以外)が入力された場合
            if(selectedMoveOrStop != 1){
                break;  // 行動ループから抜ける
            }
            // 移動(1)が入力された場合
            else{
            }
        }

        return isGameContinue;
    }

改修ソースの解説

if(selectedMoveOrStop != 1){
}
else{
}

if で処理を分岐させる。

分岐①if(selectedMoveOrStop != 1)「(変数)移動終了選択値」が「1以外」
 ※途中終了が選択された場合
分岐②else「(変数)移動終了選択値」が「1」
 ※移動が選択された場合

break;

分岐①の場合は、行動ループを抜ける。
※「break」を実行すると、すぐにループ処理から抜けることができる!

行動ループを抜けた後は、戻り値を返す処理に続く。(return isGameContinue;)
※このときの[ゲームプレイ] 関数の戻り値は、初期値の「true:継続」のまま呼び出し側に返る。

[移動する] 処理を追加

改修STEP
改修

① [移動マス計算] 関数の呼び出し、現在位置の計算処理を追加する

改修

② Gameクラスに[移動マス計算] 関数を作成する

改修

③ Gameクラスに[ランダム数値取得] 関数を作成する

① [移動マス計算] 関数の呼び出し、現在位置の計算処理を追加する

改修内容

  • 移動が選択された場合の分岐ルート内で、[移動マス計算] 関数を呼び出す。
  • [移動マス計算] 関数で、今回の移動マス数が計算されるので、その移動マス数と現在位置のマス数を足して、移動後のマス数を計算する。
[移動する] 処理の詳細
[移動する] 処理の詳細

改修箇所

[移動する] 処理を追加
[移動する] 処理を追加

改修ソース

※ハイライト部分を改修
    /**
     * ゲームプレイ
     * @return ゲーム継続フラグ(true:継続/false:終了)
     */
    private boolean playGame(){
        boolean isGameContinue = true; // ゲーム継続フラグ(true:継続/false:終了)
        
        // プレイヤー情報 ------------------------
        int currentPosition = 0;    // 現在位置のマス数(スタート地点を0とする)
        //---------------------------------------

        //===============
        // 行動ループ
        //===============
        boolean isActionContinue = true; // 行動継続フラグ(true:継続/false:終了)

        while(isActionContinue){
            //----------------
            // 移動、終了選択
            //----------------
            int selectedMoveOrStop = 0; // 移動終了選択値(1:移動/1以外:途中終了)
            selectedMoveOrStop = this.selectMoveOrStop();

            //-----------------
            // 移動途中終了分岐
            //-----------------
            // 途中終了(1以外)が入力された場合
            if(selectedMoveOrStop != 1){
                break;  // 行動ループから抜ける
            }
            // 移動(1)が入力された場合
            else{
                //-------------------
                // 移動する
                //-------------------
                // 移動マス数を計算
                int moveValue = this.calculateMoveValue();
                
                // 移動後の現在位置マス数を計算
                currentPosition += moveValue;
            }
        }

        return isGameContinue;
    }

改修ソースの解説

int currentPosition = 0;    // 現在位置のマス数(スタート地点を0とする)

プレイヤーの現在位置を保持する「(変数)現在位置のマス数」を宣言する。

変数に入る内容プレイヤーの現在位置のマス数
初期値0:スタート地点を0とする

// 移動マス数を計算
int moveValue = this.calculateMoveValue();

[移動マス計算] 関数を呼び出して、戻り値を「(変数)移動マス数」に代入する。


currentPosition += moveValue;

上記の「(変数)移動マス数」を「(変数)現在位置のマス数」に足して、移動後の位置を計算する。
※currentPosition += moveValue; は、currentPosition = currentPosition + moveValue; を簡略化した書き方。

② Gameクラスに[移動マス計算] 関数を作成する

改修内容

  • [移動マス計算] 関数を作成する。
  • [関数の処理内容]
    ・[ランダム数値取得] 関数を呼び出し、「移動マス数」を取得する。
    ・取得した「移動マス数」を、この関数を呼び出したところに戻り値で返す。
[移動マス計算] 関数の詳細
[移動マス計算] 関数の詳細

改修ソース

関数を作成する場所は、[selectMoveOrStop] 関数の下に作成します。
※Gameクラスの中で、他の関数の外であればどこに作成しても大丈夫です!

※ハイライト部分を改修
    /**
     * 移動するマス数を計算する
     * @return 移動するマス数
     */
    private int calculateMoveValue(){
        //----------------------
        // 通常の移動マス数を取得
        //----------------------
        // 1~3の範囲でランダムな数値を取得する
        int val = this.getRandomValue(3);

        return val;
    }

改修ソースの解説

private int calculateMoveValue(){
}

関数を定義する。

引数なし
戻り値移動するマス数

// 1~3の範囲でランダムな数値を取得する
int val = this.getRandomValue(3);

return val;

[ランダム数値取得] 関数を呼び出して、関数の戻り値を「(変数)移動マス数」に代入する。
最後に「val (移動マス数)」を、戻り値で返す。

③ Gameクラスに[ランダム数値取得] 関数を作成する

改修内容

  • [ランダム数値取得] 関数を作成する。
  • [関数の処理内容]
    ・1~3の範囲でランダムな数値を取得する。
    ・上記で取得した「ランダムな数値」を、この関数を呼び出したところに戻り値で返す。
[ランダム数値取得] 関数の詳細
[ランダム数値取得] 関数の詳細

改修ソース

関数を作成する場所は、[calculateMoveValue] 関数の下に作成します。
※Gameクラスの中で、他の関数の外であればどこに作成しても大丈夫です!

※ハイライト部分を改修
    /**
     * ランダムな数値を取得する
     * @param max ランダム値の最大値
     * @return ランダム値
     */
    private int getRandomValue(int max){
        Random rand = new Random();
        int val = rand.nextInt(max) + 1;
        return val;
    }

改修ソースの解説

private int getRandomValue(int max){
}

関数を定義する。

引数ランダム値の最大値
戻り値取得したランダムな数値

Random rand = new Random();
int val = rand.nextInt(max) + 1;

RandomクラスのnextInt関数を使用して、1~3の範囲内のランダム値を取得する。

nextInt関数

0から引数に指定した数値未満の整数値を返す。
例)nextInt(3)の場合、0,1,2のいずれかの数値を返す。

※Randomクラスを使用するためには、java.util.Randomをimportする必要があります。
 ページの最上部に import java.util.Random; を記述する。
Randomクラスは、乱数を生成することができるクラスです。


return val;

最後に1~3の範囲内のランダム値を、戻り値で返す。

ゴール到達、未到達の処理分岐を追加

改修内容

移動処理を行った後に、プレイヤーがゴールした場合、していない場合で処理を分岐する。
 分岐1:ゴールに到達した場合のルート
 分岐2:ゴールに到達していない場合のルート

改修箇所

ゴールに到達した場合と到達していない場合の処理分岐を追加
ゴールに到達した場合としていない場合の処理分岐を追加

改修ソース

メンバー変数「squareNum」を追加

※ハイライト部分を改修
import java.util.Random;
import java.util.Scanner;

public class Game {

    //=======================
    // メンバー変数
    //=======================
    /**
     * スタートとゴールまでのマス数
     */
    private int squareNum = 10;

    /**
     * ゲーム起動
     */
    public void startUp(){
        ~~ 省略 ~~
    }

    ~~ 省略 ~~
}

処理分岐を追加

※ハイライト部分を改修
    /**
     * ゲームプレイ
     * @return ゲーム継続フラグ(true:継続/false:終了)
     */
    private boolean playGame(){
        boolean isGameContinue = true; // ゲーム継続フラグ(true:継続/false:終了)
        
        // プレイヤー情報 ------------------------
        int currentPosition = 0;    // 現在位置のマス数(スタート地点を0とする)
        //---------------------------------------

        //===============
        // 行動ループ
        //===============
        boolean isActionContinue = true; // 行動継続フラグ(true:継続/false:終了)

        while(isActionContinue){
            //----------------
            // 移動、終了選択
            //----------------
            int selectedMoveOrStop = 0; // 移動終了選択値(1:移動/1以外:途中終了)
            selectedMoveOrStop = this.selectMoveOrStop();

            //-----------------
            // 移動途中終了分岐
            //-----------------
            // 途中終了(1以外)が入力された場合
            if(selectedMoveOrStop != 1){
                break;  // 行動ループから抜ける
            }
            // 移動(1)が入力された場合
            else{
                //-------------------
                // 移動する
                //-------------------
                // 移動マス数を計算
                int moveValue = this.calculateMoveValue();
                
                // 移動後の現在位置マス数を計算
                currentPosition += moveValue;

                //---------------
                // ゴール到達分岐
                //---------------
                // ゴールに到達した場合
                if(currentPosition > this.squareNum){
                }
                // ゴールに到達していない場合
                else{
                }
            }
        }

        return isGameContinue;
    }

改修ソースの解説

private int squareNum = 10;

Gameクラスにメンバー変数「squareNum ※マップのマス数」を宣言する。

変数に入る内容マップのマス数 ※スタートとゴールを除く
初期値10 ※マップのマス数は10とする

if(currentPosition > this.squareNum){
}
else{
}

if で処理を分岐させる。

分岐①if(currentPosition > this.squareNum)
※this.squareNumの値は10
「(変数)現在位置のマス数」が「10より大きい」
 ※ゴールに到達した場合
分岐②else「(変数)現在位置のマス数」が「10以下」
 ※ゴールに到達していない場合

スタート
 ○  ←プレイヤーがこの位置にいる場合、現在位置のマス数は「1」
 ○  ←同様に、現在位置のマス数は「2」
 ○  ←同様に、現在位置のマス数は「3」
 ○  ←同様に、現在位置のマス数は「4」
 ○  ←同様に、現在位置のマス数は「5」
 ○  ←同様に、現在位置のマス数は「6」
 ○  ←同様に、現在位置のマス数は「7」
 ○  ←同様に、現在位置のマス数は「8」
 ○  ←同様に、現在位置のマス数は「9」
 ○  ←同様に、現在位置のマス数は「10」
ゴール ←同様に、現在位置のマス数は「10より大きい」

ゴールに到達した場合の処理を追加

改修STEP
改修

① [ゴール] 関数の呼び出し、行動継続フラグを更新、ゲーム継続フラグを更新する

改修

② Gameクラスに[ゴール] 関数を作成する

① [ゴール] 関数の呼び出し、行動継続フラグを更新、ゲーム継続フラグを更新する

改修内容

ゴールに到達した場合の分岐ルート内に以下の処理を追加する。

  • [ゴール]関数を呼び出す。
  • 「(変数)行動継続フラグ」に「false」を代入する。
     ⇒ ここでfalseを代入することで、行動ループから抜ける!
  • 「ゲーム継続フラグ」に「false」を代入する。
     ⇒ ここでfalseを代入することで、この関数の戻り値で「false」が返される!

改修箇所

ゴールした場合の処理を追加
ゴールした場合の処理を追加

改修ソース

※ハイライト部分を改修
    /**
     * ゲームプレイ
     * @return ゲーム継続フラグ(true:継続/false:終了)
     */
    private boolean playGame(){
        boolean isGameContinue = true; // ゲーム継続フラグ(true:継続/false:終了)
        
        // プレイヤー情報 ------------------------
        int currentPosition = 0;    // 現在位置のマス数(スタート地点を0とする)
        //---------------------------------------

        //===============
        // 行動ループ
        //===============
        boolean isActionContinue = true; // 行動継続フラグ(true:継続/false:終了)

        while(isActionContinue){
            //----------------
            // 移動、終了選択
            //----------------
            int selectedMoveOrStop = 0; // 移動終了選択値(1:移動/1以外:途中終了)
            selectedMoveOrStop = this.selectMoveOrStop();

            //-----------------
            // 移動途中終了分岐
            //-----------------
            // 途中終了(1以外)が入力された場合
            if(selectedMoveOrStop != 1){
                break;  // 行動ループから抜ける
            }
            // 移動(1)が入力された場合
            else{
                //-------------------
                // 移動する
                //-------------------
                // 移動マス数を計算
                int moveValue = this.calculateMoveValue();
                
                // 移動後の現在位置マス数を計算
                currentPosition += moveValue;

                //---------------
                // ゴール到達分岐
                //---------------
                // ゴールに到達した場合
                if(currentPosition > this.squareNum){
                    //-------------------
                    // ゴール
                    //-------------------
                    this.printGameClear();

                    isActionContinue = false;   // 行動継続フラグ(false:終了)
                    isGameContinue = false;     // ゲーム継続フラグ(false:終了)
                }
                // ゴールに到達していない場合
                else{
                }
            }
        }

        return isGameContinue;
    }

改修ソースの解説

this.printGameClear();

[ゴール] 関数を呼び出して、コンソールにゲームクリアメッセージを出力する。


isActionContinue = false;   // 行動継続フラグ(false:終了)

行動ループから抜けるため、「(変数)行動継続フラグ」に「false」を代入する。


isGameContinue = false;     // ゲーム継続フラグ(false:終了)

ゲームループから抜けるため、「(変数)ゲーム継続フラグ」に「false」を代入する。
※[ゲームプレイ] 関数の戻り値で、呼び出し側に「false」が返されることで、ゲームループから抜ける。

ゲームループから抜ける仕組みは、以下となります。

  1. ゲームループ内で、[ゲームプレイ] 関数を呼び出す。
  2. [ゲームプレイ] 関数が実行され、戻り値として「false」が返される。
  3. 上記の戻り値「false」をゲームループ内の「(変数)ゲーム継続フラグ」に代入する。
  4. 次のゲームループ継続判定で、
    「(変数)ゲーム継続フラグがfalse」のため条件不成立となりループから抜ける。
[ゲームプレイ] 関数の戻り値の使われ方
[ゲームプレイ] 関数の戻り値の使われ方

② Gameクラスに[ゴール] 関数を作成する

改修内容

  • [ゴール] 関数を作成する。
  • [関数の処理内容]
    ・コンソールにゲームクリアのメッセージを表示する。
ゴール処理の詳細
ゴール処理の詳細
コンソール出力メッセージ
★★★★★★★★★★★★★★

 おめでとうございます!
 ゲームをクリアしました!!

★★★★★★★★★★★★★★

改修ソース

関数を作成する場所は、[getRandomValue] 関数の下に作成します。
※Gameクラスの中で、他の関数の外であればどこに作成しても大丈夫です!

※ハイライト部分を改修
    /**
     * ゲームクリアのメッセージを出力する
     */
    private void printGameClear(){
        // ゲームクリアメッセージ
        String printMsg = "";
        printMsg = ""
            + "\n"
            + "\n" + "★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★"
            + "\n" + ""
            + "\n" + " おめでとうございます!"
            + "\n" + " ゲームをクリアしました!!"
            + "\n" + ""
            + "\n" + "★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★"
            + "\n"
            ;

        System.out.println(printMsg);
    }

改修ソースの解説

private void printGameClear(){
}

関数を定義する。

引数なし
戻り値なし

// ゲームクリアメッセージ
String printMsg = "";
printMsg = ""
        + "\n"
        + "\n" + "★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★"
        + "\n" + ""
        + "\n" + " おめでとうございます!"
        + "\n" + " ゲームをクリアしました!!"
        + "\n" + ""
        + "\n" + "★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★"
        + "\n"
        ;

System.out.println(printMsg);

①コンソールに出力するメッセージを「(String変数)printMsg」に代入する。
②System.out.println関数を使用して、コンソールにメッセージを出力する。

ゴールに到達していない場合の処理を追加

改修STEP
改修

① イベント内容のデータを作成する、[マップを書く] 関数を呼び出す

改修

② Gameクラスに[マップを書く] 関数を作成する

① イベント内容のデータを作成する、[マップを書く] 関数を呼び出す

改修内容

  • 各マスに表示するイベント内容のデータを作成する。
  • ゴールに到達していない場合の分岐ルート内に以下の処理を追加する。
    ・[マップを書く] 関数を呼び出す。

改修箇所

[マップを書く] 関数を呼び出す
[マップを書く] 関数を呼び出す

改修ソース

メンバー変数「squareContentList」を追加
※メンバー変数「squareNum」より上に追加してください

※ハイライト部分を改修
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.Scanner;

public class Game {

    //=======================
    // メンバー変数
    //=======================

    /**
     * 各マスごとのイベント内容リスト
     */
    private List<String> squareContentList = new ArrayList<String>(){
        {
            add("なし。");
            add("少し眠たくなった。1回休み。");
            add("体が軽い。2マス進む。");
            add("なし。");
            add("なし。");
            add("後ろ歩きしてみた。1マス戻る。");
            add("なし。");
            add("レンタカーを借りた。次は2倍進む。");
            add("なぜかゴールに到着する。");
            add("用事を思い出した。3マス戻る。");
        }
    };
    
    /**
     * マップのマス数
     */
    private int squareNum = this.squareContentList.size();

    /**
     * ゲーム起動
     */
    public void startUp(){
        ~~ 省略 ~~
    }

    ~~ 省略 ~~
}

[マップを書く] 関数を呼び出す

※ハイライト部分を改修
    /**
     * ゲームプレイ
     * @return ゲーム継続フラグ(true:継続/false:終了)
     */
    private boolean playGame(){
        boolean isGameContinue = true; // ゲーム継続フラグ(true:継続/false:終了)
        
        // プレイヤー情報 ------------------------
        int currentPosition = 0;    // 現在位置のマス数(スタート地点を0とする)
        //---------------------------------------

        //===============
        // 行動ループ
        //===============
        boolean isActionContinue = true; // 行動継続フラグ(true:継続/false:終了)

        while(isActionContinue){
            //----------------
            // 移動、終了選択
            //----------------
            int selectedMoveOrStop = 0; // 移動終了選択値(1:移動/1以外:途中終了)
            selectedMoveOrStop = this.selectMoveOrStop();

            //-----------------
            // 移動途中終了分岐
            //-----------------
            // 途中終了(1以外)が入力された場合
            if(selectedMoveOrStop != 1){
                break;  // 行動ループから抜ける
            }
            // 移動(1)が入力された場合
            else{
                //-------------------
                // 移動する
                //-------------------
                // 移動マス数を計算
                int moveValue = this.calculateMoveValue();
                
                // 移動後の現在位置マス数を計算
                currentPosition += moveValue;

                //---------------
                // ゴール到達分岐
                //---------------
                // ゴールに到達した場合
                if(currentPosition > this.squareNum){
                    //-------------------
                    // ゴール
                    //-------------------
                    this.printGameClear();

                    isActionContinue = false;   // 行動継続フラグ(false:終了)
                    isGameContinue = false;     // ゲーム継続フラグ(false:終了)
                }
                // ゴールに到達していない場合
                else{
                    //---------------------------
                    // マップを書く※イベント発生後
                    //---------------------------
                    this.printMap(this.squareContentList, currentPosition);
                }
            }
        }

        return isGameContinue;
    }

改修ソースの解説

private List<String> squareContentList = new ArrayList<String>(){
    {
        add("なし。");
        add("少し眠たくなった。1回休み。");
        add("体が軽い。2マス進む。");
        add("なし。");
        add("なし。");
        add("後ろ歩きしてみた。1マス戻る。");
        add("なし。");
        add("レンタカーを借りた。次は2倍進む。");
        add("なぜかゴールに到着する。");
        add("用事を思い出した。3マス戻る。");
    }
};

Gameクラスにメンバー変数「squareContentList ※各マスごとのイベント内容リスト」を宣言する。
情報をまとめて管理したいので、リストを使用する。
※上記の書き方は、リストの変数宣言と同時に要素を追加している。

※ArrayListクラスを使用するためには、java.util.ArrayListをimportする必要があります。
 ページの最上部に import java.util.ArrayList; を記述する。
Listクラスを使用するためには、java.util.Listをimportする必要があります。
 ページの最上部に import java.util.List; を記述する。

squareContentList

indexイベント内容
0なし。
1少し眠たくなった。1回休み。
2体が軽い。2マス進む。
3なし。
4なし。
5後ろ歩きしてみた。1マス戻る。
6なし。
7レンタカーを借りた。次は2倍進む。
8なぜかゴールに到着する。
9用事を思い出した。3マス戻る。

private int squareNum = this.squareContentList.size();

squareNumの値を固定値「10」から「各マスごとのイベント内容」の要素数に変更する。
スタートからゴールまでのマス数(10)は、「各マスのイベント内容リスト」の要素数(10)と同じ
リストの要素数にしておけば、リストの要素数(ゴールまでのマス数)を変更したときも、この部分を修正する必要がなくなる


this.printMap(this.squareContentList, currentPosition);

[マップを書く] 関数を呼び出して、コンソールにすごろくのマップを出力する。
引数に「this.squareContentList(各マスごとのイベント内容)」と「currentPosition(現在位置のマス数)」を渡す。

② Gameクラスに[マップを書く] 関数を作成する

改修内容

  • [マップを書く] 関数を作成する。
  • [関数の処理内容]
     1. 「スタート」マスを出力する
     2. 以下の処理をスタートからゴールまでのマス分繰り返す
       マスを○で出力する ※現在位置は●で出力する
       マスにイベント内容を出力する
     3. 「ゴール」マスを出力する

マップを書く処理について、詳しく説明したいと思います。

マップを書く処理は、いくつかの処理が合わさってマップが完成します。

[マップを書く] 処理を詳細な項目に分割してみましょう。

分割STEP01. マップを書く
分割STEP11. スタートからゴールまでのマスを出力する ※現在位置は●で出力する
2. 各マスにイベント内容を出力する
分割STEP21. 「スタート」マスを出力する
2. 以下の処理をスタートからゴールまでのマス分繰り返す
  マスを○で出力する ※現在位置は●で出力する
  マスにイベント内容を出力する
3. 「ゴール」マスを出力する

言葉で書くと、分割STEP2に書いた処理が合わさって、マップを書く処理が完成します。

以下に分割のイメージと分割STEP2のフローチャートを記載しました。

分割の流れと分割STEP2のフローチャート
分割の流れと分割STEP2のフローチャート

[分割STEP2のフローチャートの処理動作イメージ]

  1. 最初に、「スタート」マスを出力する。
  2. ループ処理の1回目で、1マス目の「マス」と「イベント内容」を出力する。
  3. ループ処理の2回目で、2マス目の「マス」と「イベント内容」を出力する。
  4. ~ 途中省略 ~
  5. ループ処理の10回目で、10マス目の「マス」と「イベント内容」を出力する。
  6. 最後に、「ゴール」マスを出力する。

改修ソース

関数を作成する場所は、[printGameFinish] 関数の下に作成します。
※Gameクラスの中で、他の関数の外であればどこに作成しても大丈夫です!

※ハイライト部分を改修
    /**
     * マップを書く
     * スタートからゴールまでのマスを○で出力する
     * ※ただし、現在位置のマスは●で出力する
     * 各マスにイベント内容を出力する
     * @param contentList 各マスごとのイベント内容リスト
     * @param currentPos 現在位置のマス数
     */
    private void printMap(List<String> contentList, int currentPos){

        // 「スタート」を出力する
        System.out.println("スタート" + "\n" + "|");

        // スタートからゴールまでのマスとイベント内容を出力する
        for(int index = 0; index < contentList.size(); index++){
            int loopCnt = index + 1;    // ループ回数目
            String printSquare = "";    // 1マスに出力する内容

            //------------------------
            // マスの出力内容を分岐する
            //------------------------
            String squareKind = "〇";   // デフォルトのマスは〇で出力する

            // ループ回数目が現在位置のマス数と同じか?
            if(loopCnt == currentPos){
                squareKind = "● ";      // 現在位置のマスは●で出力する
            }

            //---------------------------
            // イベント内容をリストから取得
            //---------------------------
            String eventContent = contentList.get(index);

            //--------------------------
            // 各マスに出力する内容を生成
            //  〇 イベント内容
            //  |
            //--------------------------
            printSquare += squareKind + "  " + eventContent;
            printSquare += "\n" + "|";
            
            System.out.println(printSquare);
        }

        // 「ゴール」を出力する
        System.out.println("ゴール");
    }

改修ソースの解説

private void printMap(List<String> contentList, int currentPos){
}

関数を定義する。

引数各マスごとのイベント内容リスト、現在位置のマス数
戻り値なし

System.out.println("スタート" + "\n" + "|");

System.out.println関数を使用して、コンソールに「スタート」を出力する。


for(int index = 0; index < contentList.size(); index++){
}

スタートからゴールまでのマスの数だけ処理を繰り返したいので、ループ処理を書く。
※今回は、繰り返す回数が決まっているので、「for」を使用します。
スタートからゴールまでのマス数(10)は、「各マスのイベント内容リスト」の要素数(10)と同じ


String squareKind = "〇";   // デフォルトのマスは〇で出力する

// ループ回数目が現在位置のマス数と同じか?
if(loopCnt == currentPos){
    squareKind = "● ";      // 現在位置のマスは●で出力する
}

if で処理を分岐して、マスの種類を決定する。※[〇通常マス]と[●現在位置マス]

分岐①if(loopCnt == currentPos)「ループ回数」が「現在位置のマス数と同じ」
 ※現在位置のマスを出力する場合

分岐①の場合は、「マスの種類(squareKind)」を「●」に変更する。
※「マスの種類(squareKind)」の初期値を〇にしているため、現在位置以外のマスは「〇」で出力される。


String eventContent = contentList.get(index);

「各マスのイベント内容リスト」からループ回数に応じたindexの要素を取得して、「イベント内容(eventContent)」に代入する。

[ループ回数とリストのindexの対応イメージ]

1回目のループ ⇒ リストのindexが[0]の要素を取得
2回目のループ ⇒ リストindexが[1]の要素を取得

10回目のループ ⇒ リストindexが[9]の要素を取得


printSquare += squareKind + "  " + eventContent;
printSquare += "\n" + "|";

「1マスに出力する内容(printSquare)」に、「マスの種類(squareKind)」と「イベント内容(eventContent)」を文字列結合して代入する。
さらに、上下のマスをつなぐ「|」を文字列結合する。


System.out.println(printSquare);

上記で生成した「1マスに出力する内容」を出力する。
※1回のループで1マス分の内容をコンソールに出力する。


System.out.println("ゴール");

ループ処理が終わった後に、System.out.println関数を使用して、「ゴール」を出力する。

[マップを書く※初期表示]、[マップを書く※移動後] 処理を追加

改修内容

マップを書く処理を以下の2箇所に追加する。
 ① ゲーム開始を選択した後 ※[マップを書く※初期表示]
 ② 移動した後 ※[マップを書く※移動後]

改修箇所

[マップを書く] 処理を2箇所に追加
[マップを書く] 処理を2箇所に追加

改修ソース

※ハイライト部分を改修
    /**
     * ゲームプレイ
     * @return ゲーム継続フラグ(true:継続/false:終了)
     */
    private boolean playGame(){
        boolean isGameContinue = true; // ゲーム継続フラグ(true:継続/false:終了)
        
        // プレイヤー情報 ------------------------
        int currentPosition = 0;    // 現在位置のマス数(スタート地点を0とする)
        //---------------------------------------

        //----------------------
        // マップを書く※初期表示
        //----------------------
        this.printMap(this.squareContentList, currentPosition);

        //===============
        // 行動ループ
        //===============
        boolean isActionContinue = true; // 行動継続フラグ(true:継続/false:終了)

        while(isActionContinue){
            //----------------
            // 移動、終了選択
            //----------------
            int selectedMoveOrStop = 0; // 移動終了選択値(1:移動/1以外:途中終了)
            selectedMoveOrStop = this.selectMoveOrStop();

            //-----------------
            // 移動途中終了分岐
            //-----------------
            // 途中終了(1以外)が入力された場合
            if(selectedMoveOrStop != 1){
                break;  // 行動ループから抜ける
            }
            // 移動(1)が入力された場合
            else{
                //-------------------
                // 移動する
                //-------------------
                // 移動マス数を計算
                int moveValue = this.calculateMoveValue();
                
                // 移動後の現在位置マス数を計算
                currentPosition += moveValue;
                
                //--------------------
                // マップを書く※移動後
                //--------------------
                this.printMap(this.squareContentList, currentPosition);

                //---------------
                // ゴール到達分岐
                //---------------
                // ゴールに到達した場合
                if(currentPosition > this.squareNum){
                    //-------------------
                    // ゴール
                    //-------------------
                    this.printGameClear();

                    isActionContinue = false;   // 行動継続フラグ(false:終了)
                    isGameContinue = false;     // ゲーム継続フラグ(false:終了)
                }
                // ゴールに到達していない場合
                else{
                    //---------------------------
                    // マップを書く※イベント発生後
                    //---------------------------
                    this.printMap(this.squareContentList, currentPosition);
                }
            }
        }

        return isGameContinue;
    }

改修ソースの解説

this.printMap(this.squareContentList, currentPosition);

2箇所で[マップを書く] 関数を呼び出して、コンソールにすごろくのマップを出力する。
引数に「this.squareContentList(各マスごとのイベント内容)」と「currentPosition(現在位置のマス数)」を渡す。

[イベント発生] 処理を追加

改修STEP
改修

① [イベント発生] 関数を呼び出す

改修

② Gameクラスに[イベント発生] 関数を作成する

① [イベント発生] 関数を呼び出す

改修内容

[マップを書く ※移動後]処理をした後に、[イベント発生] 関数を呼び出す処理を追加する。

改修箇所

[イベント発生] 関数を呼び出す
[イベント発生] 関数を呼び出す

改修ソース

※ハイライト部分を改修
    /**
     * ゲームプレイ
     * @return ゲーム継続フラグ(true:継続/false:終了)
     */
    private boolean playGame(){
        boolean isGameContinue = true; // ゲーム継続フラグ(true:継続/false:終了)
        
        // プレイヤー情報 ------------------------
        int currentPosition = 0;    // 現在位置のマス数(スタート地点を0とする)
        //---------------------------------------

        //----------------------
        // マップを書く※初期表示
        //----------------------
        this.printMap(this.squareContentList, currentPosition);

        //===============
        // 行動ループ
        //===============
        boolean isActionContinue = true; // 行動継続フラグ(true:継続/false:終了)

        while(isActionContinue){
            //----------------
            // 移動、終了選択
            //----------------
            int selectedMoveOrStop = 0; // 移動終了選択値(1:移動/1以外:途中終了)
            selectedMoveOrStop = this.selectMoveOrStop();

            //-----------------
            // 移動途中終了分岐
            //-----------------
            // 途中終了(1以外)が入力された場合
            if(selectedMoveOrStop != 1){
                break;  // 行動ループから抜ける
            }
            // 移動(1)が入力された場合
            else{
                //-------------------
                // 移動する
                //-------------------
                // 移動マス数を計算
                int moveValue = this.calculateMoveValue();
                
                // 移動後の現在位置マス数を計算
                currentPosition += moveValue;
                
                //--------------------
                // マップを書く※移動後
                //--------------------
                this.printMap(this.squareContentList, currentPosition);

                //-------------------
                // イベント発生
                //-------------------
                // 現在位置マス数がゴールまでのマス数より大きい場合は、
                // ゴールしていると想定されるためイベント発生の処理をしない
                if(currentPosition <= this.squareNum){
                    //--------------------------
                    // 発生したイベント内容を出力
                    //--------------------------
                    this.printEvent(this.squareContentList, currentPosition);
                }

                //---------------
                // ゴール到達分岐
                //---------------
                // ゴールに到達した場合
                if(currentPosition > this.squareNum){
                    //-------------------
                    // ゴール
                    //-------------------
                    this.printGameClear();

                    isActionContinue = false;   // 行動継続フラグ(false:終了)
                    isGameContinue = false;     // ゲーム継続フラグ(false:終了)
                }
                // ゴールに到達していない場合
                else{
                    //---------------------------
                    // マップを書く※イベント発生後
                    //---------------------------
                    this.printMap(this.squareContentList, currentPosition);
                }
            }
        }

        return isGameContinue;
    }

改修ソースの解説

if(currentPosition <= this.squareNum){
    this.printEvent(this.squareContentList, currentPosition);
}

移動した後にまだゴールしていない場合のみ、イベントが発生するように条件分岐する。

分岐①if(currentPosition <= this.squareNum)現在位置のマス数がゴールまでのマス数以下
※まだゴールしていない場合

 現在位置のマス数が0~10 ⇒ イベント発生する
 現在位置のマス数が11以上 ⇒ イベント発生しない

分岐①の場合は、[イベント発生] 関数を呼び出して、コンソールに発生したイベント内容を出力する。
引数に「this.squareContentList(各マスごとのイベント内容)」と「currentPosition(現在位置のマス数)」を渡す。

② Gameクラスに[イベント発生] 関数を作成する

改修内容

  • [イベント発生] 関数を作成する。
  • [関数の処理内容]
    ・コンソールに発生したイベントの内容を表示する。
[イベント発生] 処理の詳細
[イベント発生] 処理の詳細
コンソール出力メッセージ
------------------------------
★★★イベントが発生★★★
 なし。
------------------------------
コンソール出力メッセージ
------------------------------
★★★イベントが発生★★★
 少し眠たくなった。1回休み。
------------------------------

改修ソース

関数を作成する場所は、[getRandomValue] 関数の下に作成します。
※Gameクラスの中で、他の関数の外であればどこに作成しても大丈夫です!

※ハイライト部分を改修
    /**
     * 発生したイベント内容を出力する
     * @param contentList イベント内容リスト
     * @param currentPos 現在位置マス
     */
    private void printEvent(List<String> contentList, int currentPos){
        String printEvent = "";    // 出力するイベント

        // 現在位置マスのイベント内容をリストから取得
        // ※リストのIndexは0始まりのため現在位置マス-1
        String eventContent = contentList.get(currentPos-1);

        // 出力用の形式に整える
        printEvent = ""
            + "\n"
            + "\n" + "------------------------------"
            + "\n" + "★ ★ ★ イベントが発生 ★ ★ ★"
            + "\n" + " " + eventContent
            + "\n" + "------------------------------"
            + "\n"
            ;

        System.out.println(printEvent);
    }

改修ソースの解説

private void printEvent(List<String> contentList, int currentPos){
}

関数を定義する。

引数各マスごとのイベント内容リスト、現在位置のマス数
戻り値なし

String eventContent = contentList.get(currentPos-1);

「各マスのイベント内容リスト」から「現在位置のマス数」に応じたindexの要素を取得して、「イベント内容(eventContent)」に代入する。

[現在位置のマス数とリストのindexの対応イメージ]


// 出力用の形式に整える
printEvent = ""
    + "\n"
    + "\n" + "------------------------------"
    + "\n" + "★ ★ ★ イベントが発生 ★ ★ ★"
    + "\n" + " " + eventContent
    + "\n" + "------------------------------"
    + "\n"
    ;

System.out.println(printEvent);

上記で取得した「イベント内容(eventContent)」を使い、メッセージを作成してコンソールに出力する。

イベントで発生効果のデータを追加

改修内容

各マスのイベントで発生する効果データをリストで作成します。

まず、各マスで発生する効果を以下の3種類に分類します。
 ①休み付与、②マス加算、③移動倍率

イベント内容発生する効果分類
なし。なしなし
少し眠たくなった。1回休み。次回、1回休み①休み付与
体が軽い。2マス進む。2マス進む②マス加算
なし。なしなし
なし。なしなし
後ろ歩きしてみた。1マス戻る。1マス戻る※言い換えると-1マス進む②マス加算
なし。なしなし
レンタカーを借りた。次は2倍進む。次回、移動マス数×2③移動倍率
なぜかゴールに到着する。ゴールする※言い換えるとゴールまで進む②マス加算
用事を思い出した。3マス戻る。3マス戻る※言い換えると-3マス進む②マス加算
イベント効果の分類表

次に、分類ごとに各マスの効果データを作成します。

①休み付与 … 各マスの行動休み付与回数リスト
②マス加算 … 各マスの加算マス数リスト
③移動倍率 … 各マスの移動倍率リスト

各マスのイベント効果リストたち
各マスのイベント効果リストたち

改修ソース

メンバー変数「addBreakNumList」を追加
メンバー変数「addPosNumList」を追加
メンバー変数「moveMultipleList」を追加

※ハイライト部分を改修
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.Scanner;

public class Game {

    //=======================
    // メンバー変数
    //=======================

    /**
     * 各マスごとのイベント内容リスト
     */
    private List<String> squareContentList = new ArrayList<String>(){
        {
            add("なし。");
            add("少し眠たくなった。1回休み。");
            add("体が軽い。2マス進む。");
            add("なし。");
            add("なし。");
            add("後ろ歩きしてみた。1マス戻る。");
            add("なし。");
            add("レンタカーを借りた。次は2倍進む。");
            add("なぜかゴールに到着する。");
            add("用事を思い出した。3マス戻る。");
        }
    };

    /**
     * 各マスごとの行動休み付与回数リスト
     */
    private List<Integer> addBreakNumList = new ArrayList<Integer>(){
        {
            add(0); // 1マス目:なし
            add(1); // 2マス目:1回休み
            add(0); // 3マス目:2マス進む
            add(0); // 4マス目:なし
            add(0); // 5マス目:なし
            add(0); // 6マス目:1マス戻る
            add(0); // 7マス目:なし
            add(0); // 8マス目:次は2倍進む
            add(0); // 9マス目:ゴールに到着する
            add(0); // 10マス目:3マス戻る
        }
    };

    /**
     * 各マスごとの加算マス数リスト
     */
    private List<Integer> addPosNumList = new ArrayList<Integer>(){
        {
            add(0); // なし
            add(0); // 1回休み
            add(2); // 2マス進む
            add(0); // なし
            add(0); // なし
            add(-1); // 1マス戻る
            add(0); // なし
            add(0); // 次は2倍進む
            add(99); // ゴールに到着する
            add(-3); // 3マス戻る
        }
    };

    /**
     * 各マスごとの移動倍率リスト
     */
    private List<Integer> moveMultipleList = new ArrayList<Integer>(){
        {
            add(1); // なし
            add(1); // 1回休み
            add(1); // 2マス進む
            add(1); // なし
            add(1); // なし
            add(1); // 1マス戻る
            add(1); // なし
            add(2); // 次は2倍進む
            add(1); // ゴールに到着する
            add(1); // 3マス戻る
        }
    };
    
    /**
     * マップのマス数
     */
    private int squareNum = this.squareContentList.size();

    ~~ 省略 ~~
}

改修ソースの解説

private List<Integer> addBreakNumList = new ArrayList<Integer>(){
    {
        add(0); // 1マス目:なし
        add(1); // 2マス目:1回休み
        add(0); // 3マス目:2マス進む
        add(0); // 4マス目:なし
        add(0); // 5マス目:なし
        add(0); // 6マス目:1マス戻る
        add(0); // 7マス目:なし
        add(0); // 8マス目:次は2倍進む
        add(0); // 9マス目:ゴールに到着する
        add(0); // 10マス目:3マス戻る
    }
};

Gameクラスにメンバー変数「addBreakNumList ※各マスごとの行動休み付与回数リスト」を宣言する。
情報をまとめて管理したいので、リストを使用する。
※上記の書き方は、リストの変数宣言と同時に要素を追加している。

addBreakNumList

index休み付与回数
00
11
20
30
40
50
60
70
80
90

private List<Integer> addPosNumList = new ArrayList<Integer>(){
    {
        add(0); // なし
        add(0); // 1回休み
        add(2); // 2マス進む
        add(0); // なし
        add(0); // なし
        add(-1); // 1マス戻る
        add(0); // なし
        add(0); // 次は2倍進む
        add(99); // ゴールに到着する
        add(-3); // 3マス戻る
    }
};

Gameクラスにメンバー変数「addPosNumList ※各マスごとの加算マス数リスト」を宣言する。
情報をまとめて管理したいので、リストを使用する。

addPosNumList

index加算マス数
00
10
22
30
40
5-1
60
70
899
9-3

private List<Integer> moveMultipleList = new ArrayList<Integer>(){
   {
        add(1); // なし
        add(1); // 1回休み
        add(1); // 2マス進む
        add(1); // なし
        add(1); // なし
        add(1); // 1マス戻る
        add(1); // なし
        add(2); // 次は2倍進む
        add(1); // ゴールに到着する
        add(1); // 3マス戻る
    }
};

Gameクラスにメンバー変数「moveMultipleList ※各マスごとの移動倍率リスト」を宣言する。
情報をまとめて管理したいので、リストを使用する。

moveMultipleList

index移動倍率
01
11
21
31
41
51
61
72
81
91

[休み] 処理を追加

改修STEP
改修

① [休み] 関数の呼び出し、[イベント発生] 処理に[休み付与] 処理を追加する

改修

② Gameクラスに[休み] 関数を作成する

① [休み] 関数の呼び出し、[イベント発生] 処理に[休み付与] 処理を追加する

改修内容

  • 「移動する」が選択された場合のルートの最初で、[休み] 関数を呼び出す。
     ※休みの効果は、移動前に発揮したいので、[移動する] 処理の前に追加する。
  • [イベント発生]処理に以下の機能を追加する。
     ・休み付与の効果があるマスに止まった場合、プレイヤーの休み回数を更新する。
[イベント発生] 処理に休み付与の処理を追加する
[イベント発生] 処理に休み付与の処理を追加する

改修箇所

[休み] 関数の呼び出し、[イベント発生]処理を改修する
[休み] 関数の呼び出し、[イベント発生] 処理を改修する

改修ソース

※ハイライト部分を改修
    /**
     * ゲームプレイ
     * @return ゲーム継続フラグ(true:継続/false:終了)
     */
    private boolean playGame(){
        boolean isGameContinue = true; // ゲーム継続フラグ(true:継続/false:終了)
        
        // プレイヤー情報 ------------------------
        int currentPosition = 0;    // 現在位置のマス数(スタート地点を0とする)
        int breakNum = 0;           // 行動休み回数
        //---------------------------------------

        //----------------------
        // マップを書く※初期表示
        //----------------------
        this.printMap(this.squareContentList, currentPosition);

        //===============
        // 行動ループ
        //===============
        boolean isActionContinue = true; // 行動継続フラグ(true:継続/false:終了)

        while(isActionContinue){
            //----------------
            // 移動、終了選択
            //----------------
            int selectedMoveOrStop = 0; // 移動終了選択値(1:移動/1以外:途中終了)
            selectedMoveOrStop = this.selectMoveOrStop();

            //-----------------
            // 移動途中終了分岐
            //-----------------
            // 途中終了(1以外)が入力された場合
            if(selectedMoveOrStop != 1){
                break;  // 行動ループから抜ける
            }
            // 移動(1)が入力された場合
            else{
                //-------------------
                // 休み処理
                //-------------------
                if(breakNum > 0){
                    // 休みメッセージ出力
                    this.printBreakTime();

                    breakNum -= 1;  // 休み回数から1回分引く
                    continue;  // 次のループへ
                }

                //-------------------
                // 移動する
                //-------------------
                // 移動マス数を計算
                int moveValue = this.calculateMoveValue();
                
                // 移動後の現在位置マス数を計算
                currentPosition += moveValue;
                
                //--------------------
                // マップを書く※移動後
                //--------------------
                this.printMap(this.squareContentList, currentPosition);

                //-------------------
                // イベント発生
                //-------------------
                // 現在位置マス数がゴールまでのマス数より大きい場合は、
                // ゴールしていると想定されるためイベント発生の処理をしない
                if(currentPosition <= this.squareNum){
                    //--------------------------
                    // 発生したイベント内容を出力
                    //--------------------------
                    this.printEvent(this.squareContentList, currentPosition);
                    
                    //-------------------
                    // イベント効果を反映
                    //-------------------
                    // 現在位置マス数-1 がリストのIndex位置と対応している
                    int listIndex = currentPosition - 1;
                    
                    // 行動休み回数
                    breakNum = this.addBreakNumList.get(listIndex);
                }

                //---------------
                // ゴール到達分岐
                //---------------
                // ゴールに到達した場合
                if(currentPosition > this.squareNum){
                    //-------------------
                    // ゴール
                    //-------------------
                    this.printGameClear();

                    isActionContinue = false;   // 行動継続フラグ(false:終了)
                    isGameContinue = false;     // ゲーム継続フラグ(false:終了)
                }
                // ゴールに到達していない場合
                else{
                    //---------------------------
                    // マップを書く※イベント発生後
                    //---------------------------
                    this.printMap(this.squareContentList, currentPosition);
                }
            }
        }

        return isGameContinue;
    }

改修ソースの解説

int breakNum = 0;           // 行動休み回数

playGame関数にローカル変数「breakNum ※行動休み回数」を宣言する。

変数に入る内容プレイヤーの休み回数
初期値0:休みなし

if(breakNum > 0){
}

プレイヤーに休み効果が付与されている場合のみ、[休み] 処理が発生するように条件分岐する。

分岐①if(breakNum > 0)休み回数が0より大きい
※休み効果が付与されている場合

this.printBreakTime();

[休み] 関数を呼び出して、コンソールに休み(行動不可)メッセージを出力する。


breakNum -= 1;

1回休んだので、現在の休み回数から1回分引く。※0になったら、休みなしの状態となる
※breakNum -= 1; は、breakNum = breakNum – 1; を簡略化した書き方。


continue;  // 次のループへ

休みの場合は、行動できないので、今回のループは終了させて、次のループに移動する。


int listIndex = currentPosition - 1;

現在位置のマス数(currentPosition)に対応する「各マスの行動休み付与回数リスト」のindexを計算する。

[現在位置のマス数とリストのindexの対応イメージ]

現在位置のマス数が「1」 ⇒ 対応するリストのindexは「0」
現在位置のマス数が「2」 ⇒ 対応するリストのindexは「1」

現在位置のマス数が「10」 ⇒ 対応するリストのindexは「9」


breakNum = this.addBreakNumList.get(listIndex);

「各マスの行動休み付与回数リスト」から、現在位置のマス数に応じたindexの要素を取得して、「行動休み回数(breakNum)」に代入する。

② Gameクラスに[休み] 関数を作成する

改修内容

  • [休み] 関数を作成する。
  • [関数の処理内容]
    ・コンソールに休み中(行動不可)のメッセージを表示する。
[休み] 処理の詳細
[休み] 処理の詳細
コンソール出力メッセージ
------------------------------
 休み中。
 今回は何もしない。
------------------------------

改修ソース

関数を作成する場所は、[printGameClear] 関数の下に作成します。
※Gameクラスの中で、他の関数の外であればどこに作成しても大丈夫です!

※ハイライト部分を改修
    /**
     * 休み中のメッセージを出力する
     */
    private void printBreakTime(){
        // 休みメッセージ
        String printMsg = "";
        printMsg = ""
            + "\n"
            + "\n" + "------------------------------"
            + "\n" + " 休み中。"
            + "\n" + " 今回は何もしない。            "
            + "\n" + "------------------------------"
            + "\n"
            ;

        System.out.println(printMsg);
    }

改修ソースの解説

private void printBreakTime(){
}

関数を定義する。

引数なし
戻り値なし

// 休みメッセージ
String printMsg = "";
printMsg = ""
        + "\n"
        + "\n" + "------------------------------"
        + "\n" + " 休み中。"
        + "\n" + " 今回は何もしない。            "
        + "\n" + "------------------------------"
        + "\n"
        ;

System.out.println(printMsg);

①コンソールに出力するメッセージを「(String変数)printMsg」に代入する。
②System.out.println関数を使用して、コンソールにメッセージを出力する。

[マス加算] 処理を追加

[イベント発生] 処理に[マス加算] 処理を追加する

改修内容

[イベント発生] 処理に以下の機能を追加する。
・マス加算の効果があるマスに止まった場合、プレイヤーの現在位置を更新する。

[イベント発生] 処理にマス加算の処理を追加する
[イベント発生] 処理にマス加算の処理を追加する

改修箇所

[イベント発生] 処理に[マス加算] 処理を追加する
[イベント発生] 処理に[マス加算] 処理を追加する

改修ソース

※ハイライト部分を改修
    /**
     * ゲームプレイ
     * @return ゲーム継続フラグ(true:継続/false:終了)
     */
    private boolean playGame(){
        boolean isGameContinue = true; // ゲーム継続フラグ(true:継続/false:終了)
        
        // プレイヤー情報 ------------------------
        int currentPosition = 0;    // 現在位置のマス数(スタート地点を0とする)
        int breakNum = 0;           // 行動休み回数
        //---------------------------------------

        //----------------------
        // マップを書く※初期表示
        //----------------------
        this.printMap(this.squareContentList, currentPosition);

        //===============
        // 行動ループ
        //===============
        boolean isActionContinue = true; // 行動継続フラグ(true:継続/false:終了)

        while(isActionContinue){
            //----------------
            // 移動、終了選択
            //----------------
            int selectedMoveOrStop = 0; // 移動終了選択値(1:移動/1以外:途中終了)
            selectedMoveOrStop = this.selectMoveOrStop();

            //-----------------
            // 移動途中終了分岐
            //-----------------
            // 途中終了(1以外)が入力された場合
            if(selectedMoveOrStop != 1){
                break;  // 行動ループから抜ける
            }
            // 移動(1)が入力された場合
            else{
                //-------------------
                // 休み処理
                //-------------------
                if(breakNum > 0){
                    // 休みメッセージ出力
                    this.printBreakTime();

                    breakNum -= 1;  // 休み回数から1回分引く
                    continue;  // 次のループへ
                }

                //-------------------
                // 移動する
                //-------------------
                // 移動マス数を計算
                int moveValue = this.calculateMoveValue();
                
                // 移動後の現在位置マス数を計算
                currentPosition += moveValue;
                
                //--------------------
                // マップを書く※移動後
                //--------------------
                this.printMap(this.squareContentList, currentPosition);

                //-------------------
                // イベント発生
                //-------------------
                // 現在位置マス数がゴールまでのマス数より大きい場合は、
                // ゴールしていると想定されるためイベント発生の処理をしない
                if(currentPosition <= this.squareNum){
                    //--------------------------
                    // 発生したイベント内容を出力
                    //--------------------------
                    this.printEvent(this.squareContentList, currentPosition);
                    
                    //-------------------
                    // イベント効果を反映
                    //-------------------
                    // 現在位置マス数-1 がリストのIndex位置と対応している
                    int listIndex = currentPosition - 1;

                    // 行動休み回数
                    breakNum = this.addBreakNumList.get(listIndex);
                    // 現在位置にイベント効果のマス数を加算
                    currentPosition += this.addPosNumList.get(listIndex);
                }

                //---------------
                // ゴール到達分岐
                //---------------
                // ゴールに到達した場合
                if(currentPosition > this.squareNum){
                    //-------------------
                    // ゴール
                    //-------------------
                    this.printGameClear();

                    isActionContinue = false;   // 行動継続フラグ(false:終了)
                    isGameContinue = false;     // ゲーム継続フラグ(false:終了)
                }
                // ゴールに到達していない場合
                else{
                    //---------------------------
                    // マップを書く※イベント発生後
                    //---------------------------
                    this.printMap(this.squareContentList, currentPosition);
                }
            }
        }

        return isGameContinue;
    }

改修ソースの解説

currentPosition += this.addPosNumList.get(listIndex);

「各マスの加算マス数リスト」から、現在位置のマス数に応じたindexの要素を取得して、「現在位置のマス数(currentPosition)」に加算する。
※currentPosition += this.addPosNumList.get(listIndex); は、
 currentPosition = currentPosition + this.addPosNumList.get(listIndex); を簡略化した書き方。

[移動倍率] 処理を追加

改修STEP
改修

① [イベント発生] 処理に[移動倍率] 処理を追加する

改修

② [移動する] 処理に移動倍率を追加する

改修箇所

[移動倍率] 処理を追加する
[移動倍率] 処理を追加する

① [イベント発生] 処理に[移動倍率] 処理を追加する

改修内容

[イベント発生] 処理に以下の機能を追加する。
・移動倍率変更効果があるマスに止まった場合、プレイヤーの次回の移動倍率を更新する。

ランダムで決定した移動数に移動倍率をかける
ランダムで決定した移動数に移動倍率をかける

改修ソース

※ハイライト部分を改修
    /**
     * ゲームプレイ
     * @return ゲーム継続フラグ(true:継続/false:終了)
     */
    private boolean playGame(){
        boolean isGameContinue = true; // ゲーム継続フラグ(true:継続/false:終了)
        
        // プレイヤー情報 ------------------------
        int currentPosition = 0;    // 現在位置のマス数(スタート地点を0とする)
        int breakNum = 0;           // 行動休み回数
        int moveMultiple = 1;       // 移動倍率
        //---------------------------------------

        //----------------------
        // マップを書く※初期表示
        //----------------------
        this.printMap(this.squareContentList, currentPosition);

        //===============
        // 行動ループ
        //===============
        boolean isActionContinue = true; // 行動継続フラグ(true:継続/false:終了)

        while(isActionContinue){
            //----------------
            // 移動、終了選択
            //----------------
            int selectedMoveOrStop = 0; // 移動終了選択値(1:移動/1以外:途中終了)
            selectedMoveOrStop = this.selectMoveOrStop();

            //-----------------
            // 移動途中終了分岐
            //-----------------
            // 途中終了(1以外)が入力された場合
            if(selectedMoveOrStop != 1){
                break;  // 行動ループから抜ける
            }
            // 移動(1)が入力された場合
            else{
                //-------------------
                // 休み処理
                //-------------------
                if(breakNum > 0){
                    // 休みメッセージ出力
                    this.printBreakTime();

                    breakNum -= 1;  // 休み回数から1回分引く
                    continue;  // 次のループへ
                }

                //-------------------
                // 移動する
                //-------------------
                // 移動マス数を計算
                int moveValue = this.calculateMoveValue();
                
                // 移動後の現在位置マス数を計算
                currentPosition += moveValue;
                
                //--------------------
                // マップを書く※移動後
                //--------------------
                this.printMap(this.squareContentList, currentPosition);

                //-------------------
                // イベント発生
                //-------------------
                // 現在位置マス数がゴールまでのマス数より大きい場合は、
                // ゴールしていると想定されるためイベント発生の処理をしない
                if(currentPosition <= this.squareNum){
                    //--------------------------
                    // 発生したイベント内容を出力
                    //--------------------------
                    this.printEvent(this.squareContentList, currentPosition);
                    
                    //-------------------
                    // イベント効果を反映
                    //-------------------
                    // 現在位置マス数-1 がリストのIndex位置と対応している
                    int listIndex = currentPosition - 1;

                    // 行動休み回数
                    breakNum = this.addBreakNumList.get(listIndex);
                    // 現在位置にイベント効果のマス数を加算
                    currentPosition += this.addPosNumList.get(listIndex);
                    // 移動倍率
                    moveMultiple = this.moveMultipleList.get(listIndex);
                }

                //---------------
                // ゴール到達分岐
                //---------------
                // ゴールに到達した場合
                if(currentPosition > this.squareNum){
                    //-------------------
                    // ゴール
                    //-------------------
                    this.printGameClear();

                    isActionContinue = false;   // 行動継続フラグ(false:終了)
                    isGameContinue = false;     // ゲーム継続フラグ(false:終了)
                }
                // ゴールに到達していない場合
                else{
                    //---------------------------
                    // マップを書く※イベント発生後
                    //---------------------------
                    this.printMap(this.squareContentList, currentPosition);
                }
            }
        }

        return isGameContinue;
    }

改修ソースの解説

int moveMultiple = 1;       // 移動倍率

playGame関数にローカル変数「moveMultiple ※移動倍率」を宣言する。

変数に入る内容プレイヤーの次回移動マス数にかける倍率
初期値1:×1倍

moveMultiple = this.moveMultipleList.get(listIndex);

「各マスの移動倍率リスト」から、現在位置のマス数に応じたindexの要素を取得して、「移動倍率(moveMultiple)」に代入する。
次回の移動マスに移動倍率をかける。

② [移動する] 処理に移動倍率を反映する処理を追加する

改修内容

  • [移動マス計算] 関数を呼び出す時の引数に「移動倍率」を渡すように変更する。
  • [移動マス計算] 関数を以下のように改修する。
    ・引数に「移動倍率」を受け取る。
    ・ランダムで決定した移動マス数に移動倍率を掛ける。
[移動マス計算] 関数に移動倍率を追加する
[移動マス計算] 関数に移動倍率を追加する

改修ソース

[移動マス計算] 関数の呼び出しを改修

※ハイライト部分を改修
    /**
     * ゲームプレイ
     * @return ゲーム継続フラグ(true:継続/false:終了)
     */
    private boolean playGame(){
        boolean isGameContinue = true; // ゲーム継続フラグ(true:継続/false:終了)
        
        // プレイヤー情報 ------------------------
        int currentPosition = 0;    // 現在位置のマス数(スタート地点を0とする)
        int breakNum = 0;           // 行動休み回数
        int moveMultiple = 1;       // 移動倍率
        //---------------------------------------

        //----------------------
        // マップを書く※初期表示
        //----------------------
        this.printMap(this.squareContentList, currentPosition);

        //===============
        // 行動ループ
        //===============
        boolean isActionContinue = true; // 行動継続フラグ(true:継続/false:終了)

        while(isActionContinue){
            //----------------
            // 移動、終了選択
            //----------------
            int selectedMoveOrStop = 0; // 移動終了選択値(1:移動/1以外:途中終了)
            selectedMoveOrStop = this.selectMoveOrStop();

            //-----------------
            // 移動途中終了分岐
            //-----------------
            // 途中終了(1以外)が入力された場合
            if(selectedMoveOrStop != 1){
                break;  // 行動ループから抜ける
            }
            // 移動(1)が入力された場合
            else{
                //-------------------
                // 休み処理
                //-------------------
                if(breakNum > 0){
                    // 休みメッセージ出力
                    this.printBreakTime();

                    breakNum -= 1;  // 休み回数から1回分引く
                    continue;  // 次のループへ
                }

                //-------------------
                // 移動する
                //-------------------
                // 移動マス数を計算
                int moveValue = this.calculateMoveValue(moveMultiple);
                
                // 移動後の現在位置マス数を計算
                currentPosition += moveValue;
                
                //--------------------
                // マップを書く※移動後
                //--------------------
                this.printMap(this.squareContentList, currentPosition);

                //-------------------
                // イベント発生
                //-------------------
                // 現在位置マス数がゴールまでのマス数より大きい場合は、
                // ゴールしていると想定されるためイベント発生の処理をしない
                if(currentPosition <= this.squareNum){
                    //--------------------------
                    // 発生したイベント内容を出力
                    //--------------------------
                    this.printEvent(this.squareContentList, currentPosition);
                    
                    //-------------------
                    // イベント効果を反映
                    //-------------------
                    // 現在位置マス数-1 がリストのIndex位置と対応している
                    int listIndex = currentPosition - 1;

                    // 行動休み回数
                    breakNum = this.addBreakNumList.get(listIndex);
                    // 現在位置にイベント効果のマス数を加算
                    currentPosition += this.addPosNumList.get(listIndex);
                    // 移動倍率
                    moveMultiple = this.moveMultipleList.get(listIndex);
                }

                //---------------
                // ゴール到達分岐
                //---------------
                // ゴールに到達した場合
                if(currentPosition > this.squareNum){
                    //-------------------
                    // ゴール
                    //-------------------
                    this.printGameClear();

                    isActionContinue = false;   // 行動継続フラグ(false:終了)
                    isGameContinue = false;     // ゲーム継続フラグ(false:終了)
                }
                // ゴールに到達していない場合
                else{
                    //---------------------------
                    // マップを書く※イベント発生後
                    //---------------------------
                    this.printMap(this.squareContentList, currentPosition);
                }
            }
        }

        return isGameContinue;
    }

[移動マス計算] 関数の改修

    /**
     * 移動するマス数を計算する
     * @param moveMultiple 移動倍率
     * @return 移動するマス数
     */
    private int calculateMoveValue(int moveMultiple){
        //----------------------
        // 通常の移動マス数を取得
        //----------------------
        // 1~3の範囲でランダムな数値を取得する
        int val = this.getRandomValue(3);

        //----------------------------
        // イベントの効果を移動力に反映
        //----------------------------
        // 移動倍率をかける
        val = val * moveMultiple;

        return val;
    }

改修ソースの解説

[移動マス計算] 関数の呼び出しを改修

int moveValue = this.calculateMoveValue(moveMultiple);

[移動マス計算] 関数を呼び出す時の引数を変更する。
移動倍率を引数に渡す。


[移動マス計算] 関数の改修

private int calculateMoveValue(int moveMultiple){

引数に「移動倍率」を追加する。


val = val * moveMultiple;

ランダムで決定した今回移動するマス数に「移動倍率」をかける。


以上で演習問題のプログラムが完成しました。

プログラムを作成する順番や、どの処理を関数にするか、などコーディングする感覚が掴めたでしょうか?

まとめ:思考錯誤して自分に合ったプログラムの作り方を身につけよう!

本記事では、演習問題を題材にJava言語の基本構文やコーディングの手順を解説しました。

この演習問題のプログラムには、以下のプログラミングの知識・スキルが含まれていました。

学習した知識・スキル
  • プログラムの基本構文
    変数、関数、引数、戻り値、繰り返し文(for、while)、条件文(if)、リスト
  • コーディングの順序
  • 処理の関数化
  • リストを使ったデータの管理方法

理解できていない内容があった方は、ネットや書籍で調べて、知識を定着させましょう。

プログラムは実際に自分で作らないと身につかないので、どんどんプログラミングしてみてください!

本記事の内容が、みなさんのプログラミング学習のお役に立てれば嬉しいです。


質問や相談がある方は、コメントを頂ければと思います。
みなさん本日も頑張りました。お疲れ様でした!

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

SE歴16年。
システム開発会社で開発部長をしています。

【主な仕事内容】
 ・Webシステム開発
 ・新入社員育成
 ・社員採用

IT業界が好きで、プログラミングが好きです。
社内の新入社員育成に情熱を注いでいます。

コメント

コメントする

CAPTCHA


目次
閉じる