Java ミニゲーム ソース付き 〜RPGの戦闘シーンを作る2 in Console〜

今回は、入力〜戦闘を行い、次のターンへ進む処理を実装します。

前回は、以下の画面を表示するところまで実装しました。

作成したクラス一覧
GameMain
TextRpgGame
Monster
Player
CheckeerUtils

1ターンの戦闘

1ターン分の戦闘を行うのに、「攻撃力、防御力」のパラメータが必要になります。
具体的には下のようなイメージです。

プレーヤー
HP: XX
MP: XX
攻撃力:XX
防御力:XX

こんな感じです。これは当然モンスターにも必要になります。

ここで、ちょっと注意というか、気がつく(実装したから気がついた)のが、PlayerクラスとMonsterクラスの実装が「ほぼ同じ」だということです。
PlayerクラスとMonsterクラスの違いはクラス名くらいなのです。
なので、このPayerクラスとMonsterクラスの同じような処理はまとめてしまいましょう!

クラスの処理をまとめる

まとめる方法は色々とありますが、今回は「スーパークラス(親クラス)」を使用します。
イメージは下のような感じです。

上のような図はUMLのクラス図と言います。
UMLに関しては他の記事に記載しているので。。。

  1. UMLツール 〜Star UMLを使う〜
  2. UMLツール Star UML〜ユースケース図を書いて見た〜

今回は、実装の方を進めます。
上の図にあるように、Charactorクラスを作成します。
そして、PlayerとMonsterで同じ実装をしている部分をCharactorクラスに引っ越ししてしまいます。

具体的には下のような実装です(GetterとSetterは省略)

public class Charactor {
    /** HP */
    protected int hp;
    /** MP */
    protected int mp;
    /** Level */
    protected int level;
    /** 攻撃力 */
    protected int atack;
    /** 防御力 */
    protected int defence;
    /** 武器 */
    protected Wepons wepons;
    /** 防具 */
    protected Armors armor;

ちなみに、武器と防具はまた別にクラスを作成しました。
中身はまだ決まっていません。とりあえずは、武器なら攻撃力、防具なら防御力をフィールド(要素)として持っています。

そして、PlayerクラスとMonsterクラスには攻撃、防御のコマンドが必要になります。
しかし、これも共通するのでスーパークラスに作成します。
ここで「実装」という言葉を使わなかったのはわけがあります。

抽象メソッド

書き方はインターフェースの時と同じです。
public void XXXXX();というように、メソッドの宣言のみを記述します。

具体的に下のように実装しました。

public abstract class Charactor {
    /** HP */
    protected int hp;
    /** MP */
    protected int mp;
    /** Level */
    protected int level;
    /** 攻撃力 */
    protected int atack;
    /** 防御力 */
    protected int defence;
    /** 武器 */
    protected Wepons wepons;
    /** 防具 */
    protected Armors armor;

    /** 抽象メソッド: 攻撃 */
    public abstract int attack();

    /** 抽象メソッド: 防御 */
    public abstract int diffence();
}

クラスを通常のクラスから抽象クラスへ変更:public classからpublic abstract classへ修正
そして、これを継承するクラスは、下のようにエラーが出ます。

抽象メソッドはオーバーライド

これを行わないと上のようにビルドエラーが出ます。
Javaのプログラミングルールみたいなものです。
逆にいうと、抽象メソッドは「必ずオーバーライドする」ことが約束されるので、「XXXクラス(インターフェース )を実装するクラスには△△△というメソッドが必ずある」ということになりますので、下のような実装が可能になります。

List listA = new ArrayList();
List listB = new LinkedList();

listA.add(オブジェクト1);
listB.add(オブジェクト2);

今回のPlayerクラスとMonsterクラスにも同じことが言えて、下のような実装が可能です。※多分使わないけど。。。

Charactor ch1 = new Player(10, 10);
Charactor ch2 = new Monster(5, 5);

ch1.attack();
ch2.attack();

こんな感じで動きました。
最終的なソースはこちらにあります。元のソースと比較している画面が見れます。

マルチスレッドについて

今まで、記載してないのですが、戦闘シーンのみはちょっと寂しいので拡張するということも考慮に入れてマルチスレッドに対応させています。というかLWJGLがすでに対応しているというか、そうのようにする必要があります。

実際LWJGLでは、ウィンドウに描画する(OpenGLの使用)処理があるのでマルチスレッドでの実装が必須です。

しかし、今回のマルチスレッドの実装は自前のものになってしまうので、サンプルの作成と起動確認を行ってみました。

メインにするスレッドとサブにするスレッドを「synchronized」修飾子をつけて区別をつける必要がありました。

サンプルコードは以下になります。
<実装コード(Github)>
ThreadMain
Thread1Cls
Thread2Cls

<処理内容>

  1. メインメソッド(ThreadMain)から処理を起動
  2. 主軸(メイン)になるスレッド(Thread1Cls)と付随するスレッド(Thread2Cls)を起動
  3. 主軸(メイン)になるスレッド(Thread1Cls)で以下の処理を行う
    • ”Thread1Cls: 処理を開始します"を表示
    • 入力受付、入力値の表示
    • 3秒待機(出力には「5秒」とあるが実装ミス)
  4. 付随するスレッド(Thread2Cls)で以下の処理を行う
    • 3秒待機(出力には「5秒」とあるが実装ミス)
    • ”Thread2Cls: 処理を開始します"を表示
    • 入力受付、入力値の表示

でわでわ。。。

<!— BODY広告 —>



関連ページ

関連ページ一覧

Eclipse セットアップ

  1. Java Install Eclipse〜開発ツールのインストール〜
  2. TensorFlow C++環境〜EclipseCDTをインストール〜
  3. Setup OpenGL with JavaJOGLを使う準備 for Eclipse
  4. Eclipse Meven 開発手順〜プロジェクトの作成〜
  5. Java OpenCV 環境セットアップ(on Mac)
  6. Eclipse SceneBuilderを追加する
  7. JavaFX SceneBuilder EclipseSceneBuilder連携~

Java Basic一覧

  1. Java Basic Level 1 〜Hello Java〜
  2. Java Basic Level2 〜Arithmetic Calculate〜
  3. Java Basic Level3 〜About String class〜
  4. Java Basic Level 4〜Boolean〜
  5. Java Basic Level 5〜If Statement〜
  6. Java Basic Summary from Level1 to 5
  7. Java Basic Level 6 〜Traning of If statement〜
  8. Java Basic Level8 〜How to use for statement〜
  9. Java Basic Level 8.5 〜Array〜
  10. Java Basic Level 9〜Training of for statement〜
  11. Java Basic Level 10 〜While statement 〜
  12. Java Basic Swing〜オブジェクト指向〜
  13. Java Basic Swing Level 2〜オブジェクト指向2〜
  14. サンプル実装〜コンソールゲーム〜
  15. Java Basic インターフェース・抽象クラスの作り方
  16. Java Basic クラスとは〜Step2_1〜
  17. Java Basic JUnit 〜テストスイートの作り方〜

Git関連

  1. Java Git clone in Eclipse 〜サンプルの取得〜
  2. Eclipse Gitリポジトリの取得 GitからソースをPullしよう〜
  3. IntelliJ IDEA GitGitリポジトリからクローン〜

JavaFX関連ページ

  1. Eclipse SceneBuilderを追加する
  2. JavaFX SceneBuilder 〜EclipseとSceneBuilder連携~
  3. JavaFX SceneBuilder〜ボタンにメソッドを割り当てるワンポイント〜
  4. Java プロコンゲーム 〜見た目の作成(SceneBuilderの使用)〜

ステップアップ関連ページ一覧

  1. Java 初めてでも大丈夫〜ステップアッププログラミングのススメ〜
  2. ステップアッププログラミング〜Java FxでHelloWorld解説〜
  3. Java StepUpPrograming〜JavaFX で四則計算〜
  4. Java StepUpPrograming〜JavaFXで画面切り替えを作る1〜
  5. Java StepUpPrograming〜JavaFXで画面切り替え2ボタン作成〜
  6. Java StepUpPrograming〜JavaFXで画面切り替え3アクション〜
  7. Java StepUpPrograming〜JavaFXで画面切り替え4Pane切り替え〜
  8. Java StepUpPrograming〜JavaFXで画面切り替え5WebEngine

JavaFX + ND4Jで機械学習準備

  1. JavaFX + ND4J〜数学への挑戦1:ND4Jのインストール〜
  2. JavaFX + ND4J〜数学への挑戦2: 行列の計算〜
  3. Java + ND4J 〜数学への挑戦3: ベクトル(配列)の作成方法〜

オブジェクト指向関連ページ

  1. [オブジェクト指向の概念1〜OracleDocのチュートリアル1〜](https://zenryokuservice.com/wp/2019/10/301. /%e3%82%aa%e3%83%96%e3%82%b8%e3%82%a7%e3%82%af%e3%83%88%e6%8c%87%e5%90%91%e3%81%ae%e6%a6%82%e5%bf%b5-%e3%80%9coracledoc%e3%81%ae%e3%83%81%e3%83%a5%e3%83%bc%e3%83%88%e3%83%aa%e3%82%a2%e3%83%ab%ef%bc%91/)
  2. オブジェクト指向の概念2〜クラスとは〜

Java ミニゲーム ソース付き 〜RPGの戦闘シーンを作るin Console〜

イントロダクション

RPGゲームの戦闘シーンを作成したいと思います。
イメージは、ファミコンのドラ◯エのように、「〜があらわれた!」で始まり、最後は「〜をたいじした。」と表示して終わる。そんなコンソールゲームを作成したいと思います。

テキストを主軸にした描画方法でのゲームです。下のようなイメージです。

戦闘シーンを作る理由

今回作成する「戦闘シーン」に関して、はじめに着手する理由を記載しておきます。

  1. 作ってしまえば、あとで使い回しが可能な部品(クラス)を作り、改修(カスタム)がしやすいように作る
  2. テキストのみのゲームをテスト的に実行してみる
  3. テキストベースなので、細かい描画処理がいらない
  4. オブジェクト指向プログラミングの練習になる ※1の内容がこれに当たります。

上記のような理由(と自分の趣味の関係)でテキストRPGゲーム風なプログラムを作成してみようと思います。

今までの流れ

以前、「じゃんけんゲーム」を作成しました。
Java ミニゲーム ソース 〜じゃんけんゲーム in Console 〜
Java ミニゲーム ソース 〜じゃんけんゲーム in Console 完成〜

ここまでで、「単純にクラスを作ってプログラムを起動する」ということを実践してみました。

次は、「クラスとクラスを組み合わせて何かを作る」という部分に着手します。
つまりは、作成するクラスにそれぞれの役割を与え、その役割を順番に呼び出して一つのプログラムを作成するというところです。

じゃんけんゲームで考えるならば。。。

下のような、大まかな役割分担を行います。

  1. プログラムを実行するクラス、JankenMainクラスを作成
  2. コンソール表示するクラス、ConsoleUtilクラスを作成
  3. じゃんけんの勝敗判定を行うクラス、JankenUtilクラスを作成

このように役割分担を行っておけば、JankenMainクラス(のメインメソッド)で下のような処理をすればじゃんけんゲームが作成できる。というわけです。しかし、これはサンプルなので、どのようなクラス分けが良いかは自分で考えてみてください。

処理の順番

  1. メインメソッドを起動する(JankenMain)
  2. ユーザーの入力(標準入力)を受け付ける(ConsoleUtil)
  3. CPUの手を取得する(乱数を使用して取得する)(JankenUtil)
  4. 勝敗判定を行う(JankenUtil)
  5. 結果を表示する(ConsoleUtil)

ここまで作成すれば、あとはじゃんけんゲームとして動かすことができます。
しかし、次のような疑問が出てきます。

  • 想定外の入力があった場合どのように処理をするか?
  • XX回勝負などを指定できるようにできないか?

など、想像力を膨らませただけ「疑問」や「改造したい!」という欲求が出てきます。
そのたびに、プログラムを組みなおしているのでは、手間が多すぎます。

そこで、「役割分担」の出番です。一番わかりやすい例として「入力チェック」を追加で実装する場合を考えてみます。

入力チェックを追加する

これは、簡単です。結論から行くと「チェック処理を作成し、JankenMainに3, 4行追加するだけです。
具体的には、下のような形になります。

public static void main(String[] args) {
    Scanner scan = new Scanner(System.in);
    String input = scan.nextLine();
    // この部分を追加
    if (JankenUtil.checkInput(input)) {
        System.out.println("想定外の入力です:" + input);
        // プログラムの強制終了
        System.exit(-1);
    }
}

役割分担を行っていれば、「その役割のあるクラスに対象になる処理を作成し、あとは呼び出すだけでよい」という形に持っていくプログラムの作り方です。

クラスに役割を与える

例えですが、グループでカレーを作るとかの作業を行うとき。。。
以下のような役割分担をすると思います。

  1. 火を起こす人
  2. 食材を切る人
  3. カレーの具を煮る人
  4. その他。。。

このように、クラスにも役割を与えます。

処理の流れ(簡単設計)

今回作成するRPGゲーム(戦闘シーンのみ)は勇者(プレーヤー)とモンスター(たくのじ)が登場します。

そして、戦闘を行い、最後に勝者がわかるよう「〜をやっつけた」もしくは、「〜は倒れた」のような文言を表示する。

登場するクラスを考える

すぐに思いつくのは「プレーヤー」と「モンスター」です。
これらは、クラスにするとして、その他は何が必要でしょうか?

ますは、プログラムを起動するための「メインメソッド」

そして、ゲームとして動かすためのクラス、
今回は以前自分が学習したLWJGLのプログラムの組み方を参考にして作ります。

大まかに、ゲームを作るときの処理は以下の1〜4の処理をループしてゲームとしての動きを実現します。

  1. 初期処理(画像や、データの読み込みなど)
  2. 入力受付
  3. 画像やデータの更新
  4. 画面の再描画

よくよく考えてみると、ほとんどのゲームが「初期表示(再表示)」→「入力」→「再描画」となっていると思います。

プレーヤー側からしたら「データ更新」の部分は見えませんがね(笑)

作成するクラス一覧

上記の内容を踏まえ、以下のクラスを作成しました。
初期表示のみの実装ですが、Githubにアップロードしています。

  1. GameMain: ゲームを動かす、メインメソッドのクラスです
  2. TextRpgGame: メインメソッドから、呼ばれる、ゲームの内容を実装するクラスです。
  3. Player, Monster: プレーヤーとモンスターを表現するクラスです。主にデータを保持するクラスです。
  4. CheckerUtils: 入力チェックなどのチェック処理をまとめたクラスです。

上のようなクラスを作成しました。動作は下のような感じです。
コンソール表示なので。。。

作成したクラス一覧
GameMain
TextRpgGame
Monster
Player
CheckeerUtils

余談:ソースの管理について

Githubを使うとソースのバージョン管理、つまりは、コミットした順序で、ソースの修正部分を管理できる代物です。
接続方法は下の動画で紹介しています。



関連ページ一覧

Eclipse セットアップ

  1. Java Install Eclipse〜開発ツールのインストール〜
  2. TensorFlow C++環境〜EclipseCDTをインストール〜
  3. Setup OpenGL with JavaJOGLを使う準備 for Eclipse
  4. Eclipse Meven 開発手順〜プロジェクトの作成〜
  5. Java OpenCV 環境セットアップ(on Mac)
  6. Eclipse SceneBuilderを追加する
  7. JavaFX SceneBuilder EclipseSceneBuilder連携~

Java Basic一覧

  1. Java Basic Level 1 〜Hello Java〜
  2. Java Basic Level2 〜Arithmetic Calculate〜
  3. Java Basic Level3 〜About String class〜
  4. Java Basic Level 4〜Boolean〜
  5. Java Basic Level 5〜If Statement〜
  6. Java Basic Summary from Level1 to 5
  7. Java Basic Level 6 〜Traning of If statement〜
  8. Java Basic Level8 〜How to use for statement〜
  9. Java Basic Level 8.5 〜Array〜
  10. Java Basic Level 9〜Training of for statement〜
  11. Java Basic Level 10 〜While statement 〜
  12. Java Basic Swing〜オブジェクト指向〜
  13. Java Basic Swing Level 2〜オブジェクト指向2〜
  14. サンプル実装〜コンソールゲーム〜
  15. Java Basic インターフェース・抽象クラスの作り方
  16. Java Basic クラスとは〜Step2_1〜
  17. Java Basic JUnit 〜テストスイートの作り方〜

Git関連

  1. Java Git clone in Eclipse 〜サンプルの取得〜
  2. Eclipse Gitリポジトリの取得 GitからソースをPullしよう〜
  3. IntelliJ IDEA GitGitリポジトリからクローン〜

JavaFX関連ページ

  1. Eclipse SceneBuilderを追加する
  2. JavaFX SceneBuilder 〜EclipseとSceneBuilder連携~
  3. JavaFX SceneBuilder〜ボタンにメソッドを割り当てるワンポイント〜
  4. Java プロコンゲーム 〜見た目の作成(SceneBuilderの使用)〜

Java ミニゲーム ソース 〜じゃんけんゲーム in Console 完成〜

コンソール版のじゃんけんゲームを作成しました。
しかし、とりあえず動く状況なので。。。

これに、細かい部分を作ってしまおうと思います。
まずは、バグ退治です。。。がしかしその前に処理の概要をいかに記載します。

  1. プログラムを起動する(Mainクラスのメインメソッド)
  2. コマンドで「exe」を入力してエンターキー押下
  3. じゃんけんゲームの起動(FirstCls#execute())
  4. じゃんけんゲームの入力を待つ
  5. 「1〜3」の入力かチェック
  6. 乱数を生成し CPUの手とする
  7. 両者の勝敗判定を行う

そして、修正した結果(差分)はこちらのリンクで確認できます。

バグのないようですが、じゃんけんゲームの入力時に「1〜3以外の値」が入力された時にMapから値が取得できず。。。
playerの手がnullになります。そして、処理は次へ行ってしまうので、「???」となります。

具体的なコードは下の部分です。
メインメソッドは下の部分で、FirstCls#handleInput()を呼び出しています。
Mainクラス

public class Main {
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        String input = scan.next();

        FirstCls first = new FirstCls();
        if ("exe".equals(input)) {
            first.execute(scan);
        }
        boolean isNumber = first.isNumberString(input);
        if (isNumber) {
            System.out.println(input + "は数字です。");
        } else {
            System.out.println(input + "は数字ではありません。");
        }
    }
}

FirstCls#execute()でじゃんけんゲームが開始されます。

FirstClsクラス

public void handleInput(String input) {
    System.out.println("入力値: " + input);
    if (isNumberString(input)) {
        System.out.println(input + "は、数字です");
    } else {
        System.out.println(input + "は、数字ではありません");
    }
}

クラス名がリンクになっていますが、これはGithubへのリンクになります。

修正する(修正内容)

修正方法としては、チェック処理を入れてやります。
そして「クラスの使い方」という観点から、チェッククラスを作成します。

余計な音が履いていますが、これを作成した時の動画です。

ここで追加した実装はCheckUtilクラスです。
このクラスは、実装の過程で、メソッドが増えていきましたが、まぁそんなもんでしょう。

ちなみに、このクラスのメソッドは、全て「静的メソッド」と呼ばれるメソッドです。
呼び出す時にクラス名.メソッド名という形で、呼び出します。

チェック処理

このチェック処理のポイントはズバリ「正規表現」です。
使用している以下の正規表現は0〜9の文字にマッチするのであればTRUEを変えす(そうでなければFALSEを返す)メソッドを使用しています。
そして、同じ名前のメソッドがあります。並べてみると違いが一目瞭然です。

public static boolean isNumber(String numberStr) {};
public static boolean isNumber(String numberStr, String range) {};

そして、Stringクラスにあるメソッドを使用しています。この引数に渡す文字列が「正規表現」であり、このメソッドの返り値が判定結果になります。

numberStr.matches(range)

オーバーロード

上のような実装のことを「メソッドのオーバーロード」と言います。親クラスのメソッドを上書きする「オーバーライド」とこんがらないように気をつけてください。

処理の内容に関してですが
・引数が1つのメソッドは単純に「数字の入力かチェック」
・引数が2つのメソッドは、数字の範囲を指定してチェック」
というように、処理の内容が若干違います。

初めに「0-9の入力(数値入力)チェック」を作成したのですが、じゃんけんで使用するのは1〜3までだけではないか。。。と気がついたので、数字入力チェックに「範囲」を追加しました。

public class CheckUtil {
    /** 0-9(数字)判定をする時の正規表現 */
    public static final String REGREX = "[0-9]";

    /** 1-3までの判定に使用する正規表現 */
    public static final String REG_1_TO_3 = "[1-3]";

    /**
     * 必須入力チェック、第二引数にあう正規表現でのチェックを行う
     * 
     * @param numberStr 検証する文字列
     * @param range 判定用の正規表現
     * @return true: 正規表現にマッチ false: マッチしない
     */
    public static boolean isNumber(String numberStr, String range) {
        // 正規表現で判定します。数字のrangeに当てはまる時にtrue
        if (isEmpty(numberStr) && numberStr.length() != 1) {
            return false;
        }
        if (numberStr.matches(range)) {
            return true;
        }
        return false;   }
    /**
     * 引数の1文字が数字かどうかの判定をする。。
     * 
     * @param numberStr
     * @return true: 引数が0-9 false: 0-9ではない
     */
    public static boolean isNumber(String numberStr) {
        // 正規表現で判定します。数字の0-9に当てはまる時にtrue
        if (isEmpty(numberStr) && numberStr.length() != 1) {
            return false;
        }
        if (numberStr.matches("[0-9]")) {
            return true;
        }
        return false;
    }

    /**
     * 引数に渡した文字列が、Null、またはから文字("")
     * @param str 判定する文字列
     * @return ture; 
     */
    public static boolean isEmpty(String str) {
        if (str == null || "".equals(str)) {
            return true;
        }
        return false;
    }
}

ちなみに、静的メソッドは、static修飾子をつけて実装します。インスタンスを生成しないので、メモリの節約になりますが、作りすぎると余計な負担(メモリ使用)になるので注意です。

まとめ

今までに作成したクラスFirstClsでの処理を修正しました。
くどいようですが、Mainメソッドは修正していません。

そして、追加したCheckUtilクラスはチェック担当のクラスです。

なので、このクラスにはチェック処理しか追加しません。



関連ページ一覧

Eclipse セットアップ

  1. Java Install Eclipse〜開発ツールのインストール〜
  2. TensorFlow C++環境〜EclipseCDTをインストール〜
  3. Setup OpenGL with JavaJOGLを使う準備 for Eclipse
  4. Eclipse Meven 開発手順〜プロジェクトの作成〜
  5. Java OpenCV 環境セットアップ(on Mac)
  6. Eclipse SceneBuilderを追加する
  7. JavaFX SceneBuilder EclipseSceneBuilder連携~

Java Basic一覧

  1. Java Basic Level 1 〜Hello Java〜
  2. Java Basic Level2 〜Arithmetic Calculate〜
  3. Java Basic Level3 〜About String class〜
  4. Java Basic Level 4〜Boolean〜
  5. Java Basic Level 5〜If Statement〜
  6. Java Basic Summary from Level1 to 5
  7. Java Basic Level 6 〜Traning of If statement〜
  8. Java Basic Level8 〜How to use for statement〜
  9. Java Basic Level 8.5 〜Array〜
  10. Java Basic Level 9〜Training of for statement〜
  11. Java Basic Level 10 〜While statement 〜
  12. Java Basic Swing〜オブジェクト指向〜
  13. Java Basic Swing Level 2〜オブジェクト指向2〜
  14. サンプル実装〜コンソールゲーム〜
  15. Java Basic インターフェース・抽象クラスの作り方
  16. Java Basic クラスとは〜Step2_1〜
  17. Java Basic JUnit 〜テストスイートの作り方〜

Git関連

  1. Java Git clone in Eclipse 〜サンプルの取得〜
  2. Eclipse Gitリポジトリの取得 GitからソースをPullしよう〜
  3. IntelliJ IDEA GitGitリポジトリからクローン〜

JavaFX関連ページ

  1. Eclipse SceneBuilderを追加する
  2. JavaFX SceneBuilder 〜EclipseとSceneBuilder連携~
  3. JavaFX SceneBuilder〜ボタンにメソッドを割り当てるワンポイント〜
  4. Java プロコンゲーム 〜見た目の作成(SceneBuilderの使用)〜

ステップアップ関連ページ一覧

  1. Java 初めてでも大丈夫〜ステップアッププログラミングのススメ〜
  2. ステップアッププログラミング〜Java FxでHelloWorld解説〜
  3. Java StepUpPrograming〜JavaFX で四則計算〜
  4. Java StepUpPrograming〜JavaFXで画面切り替えを作る1〜
  5. Java StepUpPrograming〜JavaFXで画面切り替え2ボタン作成〜
  6. Java StepUpPrograming〜JavaFXで画面切り替え3アクション〜
  7. Java StepUpPrograming〜JavaFXで画面切り替え4Pane切り替え〜
  8. Java StepUpPrograming〜JavaFXで画面切り替え5WebEngine

JavaFX + ND4Jで機械学習準備

  1. JavaFX + ND4J〜数学への挑戦1:ND4Jのインストール〜
  2. JavaFX + ND4J〜数学への挑戦2: 行列の計算〜
  3. Java + ND4J 〜数学への挑戦3: ベクトル(配列)の作成方法〜

Java ミニゲーム ソース 〜じゃんけんゲーム in Console 〜

今回は、Javaで作成するミニゲームと題して下のゲームを作成したいと思います。

じゃんけんゲーム

毎度おなじみ「じゃんけんゲーム」シンプルに、楽しめるゲームとして最もポピュラーなものだと思います。
それをJava言語を使ってコンソールゲームにしました。
しかし、バグもあります。。。

Mainメソッド

メインメソッドは変更しません。前回のコードはこちらから見れます。※前回の記事です。

public class Main {
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        String input = scan.next();

        FirstCls first = new FirstCls();
        if ("exe".equals(input)) {
            first.execute(scan);
        }
        boolean isNumber = first.isNumberString(input);
        if (isNumber) {
            System.out.println(input + "は数字です。");
        } else {
            System.out.println(input + "は数字ではありません。");
        }
    }
}

今回の実装はFirstCls#executeから始めます。。。

実際に作ってみた

ここで、Mainメソッド変更しません。とはじめに記載したのではじめが分かりづらいです。起動したら「exe」と入力する必要がありました(笑)
そして、実装したコード(FirstCls)は下のようなコードです。
※使用していないゴミコードは削除しています。全体はこちらのGithubで見ることができます。

public class FirstCls {
    /** システム(OS)で使用する改行コード */
    private static final String SEPARATOR = System.getProperty("line.separator");
    /** プレーヤの勝利フラグ */
    private static final Integer WIN = 1;
    /** プレーヤの敗北フラグ */
    private static final Integer LOOSE = 2;
    /** プレーヤの引き分けフラグ */
    private static final Integer DRAW = 3;

    public void execute(Scanner scan) {
        System.out.println("*** EXECUTEを起動します ***");
        // じゃんけんの手のマップ
        Map<String, String> map = createJankenTe();
        // じゃんけんの勝敗マップ
        Map<String, Integer> judgeMap = createJudgement();
        Random rnd = new Random();
        while(true) {
            System.out.print("じゃんけん。。。");
            String player = scan.next();
            int cpu = rnd.nextInt();
            System.out.println("あなた:" + map.get(player) + " CPU:" + map.get(String.valueOf(cpu)));
            if (judgeMap.get(player + cpu) == WIN) {
                System.out.println("You win!");
            } else if (judgeMap.get(player + cpu) == LOOSE) {
                System.out.println("You loose!");
            } else if (judgeMap.get(player + cpu) == DRAW) {
                System.out.println("Draw! one more time ...");
                continue;
            }
            System.out.println(SEPARATOR + "もう一度やる?" + SEPARATOR + "y: もう一度 n: やめる");

            String more = scan.next();
            if ("n".equals(more)) {
                break;
            } 
        }
    }

    /**
     * じゃんけんの手を設定したMapを返却する
     * @return Map
     */
    private Map<String, String> createJankenTe() {
        Map<String, String> map = new HashMap<>();
        map.put("1", "グー");
        map.put("2", "チョキ");
        map.put("3", "パー");
        return map;
    }

    /**
     * じゃんけんの勝敗パターンをMapに設定
     * @return Map
     */
    private Map<String, Integer> createJudgement() {
        Map<String, Integer> map = new HashMap<>();
        map.put("12", WIN);
        map.put("23", WIN);
        map.put("31", WIN);
        map.put("21", LOOSE);
        map.put("32", LOOSE);
        map.put("13", LOOSE);
        map.put("11", DRAW);
        map.put("22", DRAW);
        map.put("33", DRAW);
        return map;
    }
}

こんな感じです。

処理内容

Mainメソッドは。。。割愛します。
FirstCls#execute()では、ジャンケンで取りうる手(グー・チョキ・パー)をMapに設定しておき、1~3の入力に対応してそれぞれの手を表示、じゃんけんの判定にしようします。

勝敗の判定には、全てのパターンをMapに記憶してプレーヤーの手とCPUの手を連結→プレーヤー:グー、CPU: チョキであれば"12"で勝敗マップからは「1」が取得できます。

1は勝利判定のフラグです。
詳細は上のコードに書いてありますので。。。

近くに、これの解説動画も作成いたします。

問題

バグがあるのですが、それはどこでしょうか?
<ヒント>
動かしてみるとわかります。

でわでわ。。。

関連ページ一覧

Eclipse セットアップ

  1. Java Install Eclipse〜開発ツールのインストール〜
  2. TensorFlow C++環境〜EclipseCDTをインストール〜
  3. Setup OpenGL with JavaJOGLを使う準備 for Eclipse
  4. Eclipse Meven 開発手順〜プロジェクトの作成〜
  5. Java OpenCV 環境セットアップ(on Mac)
  6. Eclipse SceneBuilderを追加する
  7. JavaFX SceneBuilder EclipseSceneBuilder連携~

Java Basic一覧

  1. Java Basic Level 1 〜Hello Java〜
  2. Java Basic Level2 〜Arithmetic Calculate〜
  3. Java Basic Level3 〜About String class〜
  4. Java Basic Level 4〜Boolean〜
  5. Java Basic Level 5〜If Statement〜
  6. Java Basic Summary from Level1 to 5
  7. Java Basic Level 6 〜Traning of If statement〜
  8. Java Basic Level8 〜How to use for statement〜
  9. Java Basic Level 8.5 〜Array〜
  10. Java Basic Level 9〜Training of for statement〜
  11. Java Basic Level 10 〜While statement 〜
  12. Java Basic Swing〜オブジェクト指向〜
  13. Java Basic Swing Level 2〜オブジェクト指向2〜
  14. サンプル実装〜コンソールゲーム〜
  15. Java Basic インターフェース・抽象クラスの作り方
  16. Java Basic クラスとは〜Step2_1〜
  17. Java Basic JUnit 〜テストスイートの作り方〜

Git関連

  1. Java Git clone in Eclipse 〜サンプルの取得〜
  2. Eclipse Gitリポジトリの取得 GitからソースをPullしよう〜
  3. IntelliJ IDEA GitGitリポジトリからクローン〜

Java OpenCV 〜輪郭:輪郭検出処理の順序〜

OpenCVでの輪郭抽出の処理手順を確認しようと思います。

今までに、OpenCV(JavaCV)での、学習準備と基本的な処理方法の学習を学習しました。

輪郭抽出のことを調べるとPythonでの処理とかアルゴリズムの理論とか、肝心要の部分が見つからず。。。

ようやく。。。

輪郭抽出の処理順序

  1. 画像を読み込む
  2. グレースケール(白黒画像)に変更する
  3. グレースケール画像から輪郭を抽出

大まかに、上のような手順で処理を行うと表示できる。
ただし、グレースケースの画像から輪郭を取得するのでわりかしリアルな白黒だと、外側の枠しか輪郭が取得できない。

ちょっとわかりづらいけど、緑色の線が輪郭です。

そして、これをわかりやすくするには
Imgproc.threshold()を使用する必要がある。

動かしてみると下のようなイメージです。

ここまできたら、あとはトライアンドエラーで星輪郭が得られるように、下の値を調整してやります。

ちょと画像は違いますが、下のような感じで試しました。

しかし、これは、写真により値を変更しないと欲しい輪郭が取れない。。。

よく見かけるサンプルでは、輪郭がくっきりしているので、問題ないだろうが、ちょっと考え直す必要があると思いました。

→輪郭の取得方法に関して、考え直すと言う意味です。