50歳から自分の好きな職業に簡単に転職できるの? ここは「がっちゃん 」が実際に体験した転職への道を記録するブログである

Javaで「モンスターとプレイヤーがバトルする」プログラムを作成:前編

どうも! 職業訓練生のがっちゃんです!

 50歳にして、長期人材育成「情報セキュリティ管理者資格」2年コースを絶賛受講中です!

 今回は、Java言語の授業で「モンスター集団とプレイヤーがバトルする」プログラムを作成した件について話したいと思います!

 本プログラム作成の前提としての「eclipse」のインストール方法とプログラム作成のための「プロジェクト」「クラスファイル」の作り方についてはこちら「「eclipse」でjavaプログラムの「プロジェクト」と「クラスファイル」を作成」を参考にしていただければと思います。

オブジェクト指向の概念について

 今回、この「モンスターとプレイヤーがバトルする」プログラムを作成する目的は、「オブジェクト指向」(Object Oriented Programing/Design)の概念を勉強するためのものです。

 この「オブジェクト指向」、なかなか理解することが難しくいんです。そこで今回は私もキチンと理解できるように、私が好きな「機動戦士ガンダム」でオブジェクト指向の3大概念「継承」「カプセル化」「多様性(ポリモーフィズム)」を考えることにしました。

継承

 宇宙世紀0077年、地球からもっとも離れたスペースコロニーにある「ジオン公国」は、Ms-06「ザク」の開発に成功した。機体バランスの良い優れたモビルスーツのため、量産化され0079年1月の「ルウム戦役」では実践に投入され、ジオン軍の勝利に多大な貢献をしました。

 しかし、地球連邦軍も遅ればせながら「V作戦」というモビルスーツ開発にて最新型モビルスーツ「ガンダム」の製造に成功しました。そのため、ザクではガンダムに打ち勝つことができません。ザク以上の性能を持ったモビルスーツの開発が急務となりました。

 新たなモビルスーツ開発をとなると、時間もコストもかかってしまいます。ただでさえ、ザクの開発にも多大なコストがかかっています。可能であればザクの設計を応用してザク以上の性能を持つモビルスーツ開発が出来れば、開発時間をかけず、またコストも抑えるこが可能と考えました。

 そこで作られたのがMS-07S「グフ」クラスという「サブクラス」です。ザクの開発会社「ジオニック社」は、こんなこともあろうかと考え、最初から「ザククラス」というスーパークラスを作っていたのです。

 「ザククラス」には、ザクの設計内容、機体の機動力、コックピットの仕様、動力装置の概要、エネルギーの供給方法などが、詳細に書かれています。そのままコピーしただけでは「ザク」しか作れませんが「ザククラス(スーパークラス)」は「継承」により、新しいクラス「グフクラス」という「サブクラス」を作ることができます。

 「グフクラス」(サブクラス)では、ヒートロッドという武器を付けたしたり、機体の機動力もザクの2倍に書き換えることが可能です。こうして、新たに設計することなく、新たなモビルスーツ「グフ」クラスという設計図を作ることができました。

 新規にモビルスーツ開発をするたびに、イチから設計していてはものすごく大変ですが、このように「スーパークラス」と「サブクラス」により、設計図を部分的に変更してモビルスーツ開発ができるようにしておけば、ものすごく楽にモビルスーツ開発が可能となります。これが「継承」です。

 ところで地球連邦軍も、ジオン軍に対抗するためは、モビルスーツの量産化が急務です。ガンダムを設計した「テム・レイ」は、このようになることをあらかじめ想定し「ガンダムクラス」という設計図をオブジェクト指向で作っていました。スーパクラスとなる「ガンダム」クラスをベースに量産化のためコストダウンの書き換えをして継承した「ジム」クラスという「サブクラス」を作成するのであった。(続く、かも)

カプセル化

 宇宙世紀0079年、地球連邦軍はスペースコロニー「サイド7」にて極秘裏に「V作戦」を始め、連保軍初のモビルスーツ「ガンダム」を作った。しかし、その作戦をかぎつけたジオン軍兵士「シャア・アズナブル」は部下とともに「サイド7」に侵入、連邦軍の秘密兵器ガンダムの情報奪取を試みる。

 ガンダムの開発責任者「テム・レイ」は、こんなこともあろうかと、ガンダムの機密情報を奪取されないよう、「ガンダム」クラスに書いている仕様、「操縦方法」メソッド「攻撃方法」メソッドなど通常「public」にするところを、あらかじめ「private」「protected」に変更し「カプセル化」することによって、「ガンダムクラス」の仕様書である各メソッドを外部から見えなくし、かつ容易に改ざんされないようにしていたのであった。

 このカプセル化が功を奏し、シャアたちはガンダムの機密情報をカメラなどで写して帰艦。データを確認したが「カプセル化」により何も写っておらず、機密情報を奪取することはできなかったのであった。(続く、かもしれない)

多様性(ポリモーフィズム)

 宇宙世紀0079年、一年戦争が始まって以来、ジオン軍は地球連邦軍に対し戦争を優位に運ぶため、様々なモビルスーツを開発した。モビルスーツ開発が進むことにより、現場の整備兵の仕事の負担は大きくなるばかりであった。整備兵はモビルスーツごとに武器の装備内容、弾薬の種類、整備内容などをまとめて記録しているが、モビルスーツが増えるたびに、それらを追加して覚えていくのは大変であった。主なガンダム主な武器を以下に示す。

モビルスーツ名と武器
・「ザク」クラス    「ザクマシンガン」メソッド
・「グフ」 クラス   「ヒートロッド」メソッド
・「ズゴック」クラス  「アイアン・ネイル」メソッド
・「ゴッグ」クラス   「フリージーヤード」メソッド

・「アッガイ」     「フレキシブル・ベロウズ・リム」メソッド
・「ドム」クラス    「ヒートサーベル」メソッド
・「ゲルググ」クラス  「ビーム・ナギナタ」メソッド
・「ジオング」     「オールレンジ攻撃」メソッド
 ジオン軍の整備兵は、各モビルスーツクラス名ごとに、武器メソッドを装備させることを間違えぬように、主な武器だけでなく、様々な装備や詳細な整備内容をメソッドとしてプログラミングしていた。モビルスーツの種類が2種類くらいなら問題はなかったが、これだけモビルスーツクラスが増えてくると各モビルスーツごとに各種装備品や詳細な整備内容をプログラミングしていくとミスが多くなってきた。たとえば、「ドム」クラスにはない武器、「ヒートホーク」メソッドをプログラムしてしまい、パイロットが「ヒートホーク」メソッドを使おうとしたが、当然装備されていない武器のため空振りとなってしまい、連邦軍の量産型モビルスーツ「ジム」に撃破されるケースが相次いだ。
 そこでジオン軍兵器研究所は、この事態を打開するべく「多様性」(ポリモーフィズム)を使って「ヒートロッド」メソッドや「ビーム・ナギナタ」メソッドではなく、「武器」メソッドを発動すれば各モビルスーツクラスの武器が発動するようにプログラムミングを変更した。これにより、各モビルスーツクラスが「グフ」でも「ゲルググ」でも、「武器」メソッドを発動すれば、それぞれの武器を間違えることなく使えるようになった。
 これ以降、整備兵のプログラミングミスはなくなり、パイロットも、どのモビルスーツクラスを操縦するときでも「武器」メソッドを発動すれば攻撃できるようになり、操作性も向上することとなったのだ。(続く、かもね)
 簡単にいえば、「各モビルスーツクラス」間の似たようなメソッド、ここでは「ザクマシンガン」や「ヒートロッド」などのメソッドを「武器メソッド」という名前に統一しただけです。難しい言葉ですが、やっていることは単純明快ですね。
 こんな感じで、オブジェクト指向を「機動戦士ガンダム」ネタで考えれば、少しは分かりやすくなったのではないでしょうか!?というか、そんなに特別なことはしてないんだなぁ、と感じたのではないでしょうか?と思っているのは自分だけかな!?ガンダム知らない人は、あんまり理解が深まらなかったらゴメンねぇ。
 オブジェクト指向をざっくり理解したところで「モンスターとプレイヤーとのバトル」プログラムの作成を始めていくとしましょう。

プログラム作成の前に「パッケージ」の作成

 パッケージとは、Javaプログラムのクラスファイルをまとめてくれる仕組みです。クラスファイルがたくさんあるとき、それらを機能ごとに分類してまとめておくとクラスファイルの管理が容易になります。

 普通にプログラムを作ると、下図のように「デフォルトパッケージ」っていうところでクラスファイルがまとめられています。今回はそれに名前を付けてクラスファイルを管理していこう、っていうことです。

 まずは「OOPD」プロジェクトを作成します。下図のように「OOPD」プロジェクト直下にかる「src」フォルダを選択し右クリック「新規」→「パッケージ」を選択します。

 すると、以下の「Javaパッケージ」ウインドウが出現します。「名前」欄に「battle」と入力し、「完了」ボタンをクリックします。

 画面左側「OOPD」プロジェクト直下の「src」フォルダ直下に「battle」という白いパッケージが出来上がったと思います。これでパッケージの出来上がりです。ここで「モンスターとプレイヤーがバトルする」プログラムを管理していきます。

プログラム作成のためのクラスを作成

 その白い「battle」パッケージを選択しマウスを右クリックし「新規」→「クラス」を選択します。

 いつもの「Javaクラス」作成ウインドウが出てきますが、「パッケージ」欄のところに注目して下さい。いつもここは「デフォルトパッケージ」と表示されていたと思いますが、今回は「battle」パッケージに変わっています。

 今回、クラス名は「Battle」としました。メソッドスタブは「public static void」を選択しています。確認出来たら「完了」ボタンをクリックしましょう。

 以下のように「Battle」クラスが出来ていればOKです。1行目に「package battle;」と書かれていることが分かりますね。

1.まずは基本的なプログラム作り

 最初はオブジェクト指向を使わず、基本となる「Battle.java」(ゲームの基本構造)と「Monster.java」(モンスターの状態をあらわすクラス)プログラムを作成していきます。

 「Battle.java」プログラムの内容は以下の通りです。

 次は「Monster.java」のプログラムです。

 これで、基本となるプログラムが完成しました。まずはこれで、キチンと動作するか実行してみましょう。実行画面の例は以下の通りです。

 モンスターをやっつけることができましたが、モンスターのHp体力値がマイナスになっても攻撃可能になってますね。このあたり、改良の余地がありますね。

 次は、「カプセル化」によるプログラムミスの低減を考えてみます。

2.プログラムをカプセル化する

 今までは「public」という「誰が見てもいいし、書き換えてもいいよ」というプログラムにしていましたが「private」にすることにより、「勝手に変更したらあきまへんで!」というプログラムに変更し、情報の公開レベルを調整していきます。また、モンスターの体力値(HP)がマイナスになっても攻撃できる件についても修正します。これらについては「Monster.java」クラスで改良していきます。

 「Battle.java」での修正箇所は、二つだけです。「Monster.java」クラスの「name」と「hp」変数のカプセル化にともない、「name→getName」「hp→getHp」に変更しただけです。これに変更したことについては下の「Monster.java」クラス作成時の説明を確認してくださいね。

 次は「Monster.java」のプログラムです。ここではモンスターの「名前」と「体力値」を「private」にして、外部から変更できないようにします。これにより、「name」と「hp」という変数はprivateなメンバになったので、他のクラスからアクセスできなくなりました。

 ここで問題発生です。「Battle.java」クラスでは、モンスターの「name」と「hp」の値を借りてきて出力する処理がありました。これではそれぞれの値を取得することができません。

 そこで登場するのが「ゲッター」と呼ばれるメソッドです。これはprivateなフィールドにある値をゲットするメソッドです。ゲッターメソッドを作成することによりゲットしたい値、ここではモンスターの「name」(名前)と「hp」(体力値)を取得することができます。

 ゲッターにはpublicを付けますから「どこからでも自由にお使いください」ということになります。これで「Battle.java」クラスから「Monster.java」クラスの「name」と「hp」の値が使えるようになります。

 最後に、モンスターの体力値(HP)がマイナスになっても攻撃できてしまう件も、プログラムで修正しました。プログラムにすると、以下のようになります。

 プログラムが書けたら実行してみましょう。HPはちゃんとマイナスにならないでしょうか?

 ちゃんとマイナスにならないようになりましたね。

3.モンスターを攻撃するごとにメッセージが出るようにする

 モンスターの体力値に応じて攻撃したときのメッセージを「モンスターはすでに倒されている・・・」(体力値ゼロの場合)「○○は□□のダメージ!」(体力値がまだプラスの場合)「モンスターは倒された!」(体力値がプラスからゼロになった場合)と変化させるようにプログラムを「Monster.java」クラスに実装します。

 また、体力値の計算を「Monster.java」クラスに移植し、ゲーム進行のメインプログラムである「Battle.java」をシンプルなプログラムにします。

 次に「Monster.java」 クラス。

 書き終わったら実行してみましょう。実行結果は以下のようになります。

 モンスターの体力値(HP)によって、メッセージが変わっていることがわかりますね。

4.プログラムの見た目をわかりやすくする

 ここでは、見た目をわかりやすくするために加工していきます。「Battle.java」だけプログラムを修正しています。「Monster.java」については修正していません。

 また、カプセル化も行っています。

 プログラムの実行結果は、以前と同じです。下の実行結果はイレギュラーな入力に対応できているかを確認してみました。キチンと対応できてますね。

5.継承を使ってプレイヤーも反撃されて負けるかもしれないプログラムにする

 今までは、モンスターをボッコボコにするばかりでしたが、「Player.java」を登場させ、自分もボッコボコにされて負けるかもしれないプログラムに置き換えていきます。

 また、「Monster.java」クラスを「Character.java」クラスに変更し、モンスターとプレイヤー共通で使う部品をここに収納することにします。「Monster.java」「PLayer.java」クラスでは今のところ、それぞれのやられたときのセリフだけを設定しています。

 備考:プレイヤーの体力値の初期設定は500。今回からモンスターの体力値を100ずつ減らしています。この辺りの設定は、あんまり偏らせすぎると、モンスターに勝ってばかりになるので、いまく調整していきましょう。

プログラム入力時、以下の支援機能を使っていこう

 「Battle.java」クラスで、今まで「Monster」という名称だったところを「Character」に変更するのですが、以下の方法を使ってください。

 変更したい名称のところにマウスでクリックし「ctrl」+「F」キーを押すと以下「検索/置換」ウインドウが出現します。「検索」欄に「Monster」と入力し「次で置換」欄に「Character」と入力「すべて置換」ボタンをクリックします。

 すると、以下のように「Monster」が「Character」に変更されていることが分かります。しかし、一部エラー表示が出ている箇所があります。「型Characterのインスタンスを生成できません」と怒られています。これは「Character.java」クラスが「abstract」(未完成)で作成しているためです。「未完成品だから、間違えて使用しないでね」という感じで優しく叱られているので、叱られている所は元の「Monster」に戻しましょう。

 また「Character.java」クラスで「protected abstract void cry();」「protected abstract void dyingMessage() ;」を入力後、各「Player.java」「Monster.java」クラスでは、以下のようにエラーが表示されます。エラー箇所にマウスを持っていくと、エラーを解決する方法が表示されるので、「実装されていないメソッドの追加」の方を選択すれば支援機能により「@Override」が自動的に書かれます。

 以下、それぞれのプログラムになります。

 入力してエラーがないようでしたら実行してみましょう。実行画面のサンプルは以下の通りです。

 今回は、私が負けてしまいました。モンスターの体力値がまだ大幅に残っているので、プレイヤーの体力値をもう少し上げた方がいいかなぁ。

まとめ

 5つの工程に分けて、プログラムを実装させてきました。最初に比べると、ちょっとはゲームっぽくなってきましたね。

 今回はここまでにして、「その2」では、オブジェクト指向をもう少し深掘りしてプログラムを作成していきます。

 それにしても授業の後に、こうやって自分でゆっくり進めていくと、より理解が深まりますね。まぁ、授業のペースがシロウトの私にとってはメチャクチャ早い、っていうのもあるんですが・・・。これからもしっかり復習する意味で、ブログをどんどん更新していきたいですね。

 それでは本日も最後までお付き合いいただき、ありがとうございました!

スポンサーリンク
最新情報をチェックしよう!