どうも! 職業訓練生のがっちゃんです!
50歳にして、長期人材育成「情報セキュリティ管理者資格」2年コースを絶賛受講中です!
今回は、「Javaでモンスターとプレイヤーがバトルする」プログラムを作成する:その1」の続きの授業を書いていきたいと思います。いきなりここからですと、チンプンカンプンになっちゃうかもですので、「その1」の方もご覧いただければと思います!
6:モンスターを個別に設定
今回は、「Battle.java」のモンスターの召喚方法を変更、モンスターがやられたときのコメントをモンスターごとに違うようにします。この間の続きのプログラムを触っていきますが「Character.java」「Player.java」に変更はありません。「Battle.java」は、モンスターを個別で設定していたところを、それぞれのクラスから召喚するように変更しただけです。「Monster.java」は、モンスターがやっつけられたときの文字出力箇所をコメントアウトし、「各モンスター.java」で設定するようにしました。
各モンスタークラスの新規作成方法
「Bat.java」「Wolf.java」「Franken.java」「Kaibutsukun.java」「Dorakyura.java」5種類のモンスタークラスを新規作成しますが、以下の方法を使えば、ほぼ自動的に骨子を作成してくれます。いつものように、「battle6」パッケージをクリックし右クリックで「新規」→「クラス」を選択します。以下の「新規Javaクラス」ウインドウが表示されますので「スーパークラス」蘭の右側にある「参照」ボタンを押し「スーパークラスの選択」で「Monster-battle6-OOP/src」を選択し「OK」ボタンをクリックします。
以下のように「スーパークラス」欄が「battle6.Monster」に変わっています。あとは「名前」欄にモンスターの名称を入力、「どのメソッドスタブを作成しますか?」欄では「スーパークラスからのコンストラクター」と「継承された抽象メソッド」を選択し「完了」ボタンをクリックします。
すると、以下のように「Bat.java」の骨子がほとんど出来上がっており、簡単にプログラミングすることができます。これを使って各モンスタークラスを作成していきましょう。
以下が、それぞれのプログラムになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 |
package battle6; import java.util.InputMismatchException; import java.util.Random; import java.util.Scanner; /** * モンスター集団とプレイヤーがバトルするプログラム * カプセル化による情報公開レベルの調整 * @author がっちゃん * */ public class Battle { //ユーザーの入力装置の作成、どれくらいの力が入っているのかも加味できるようにする。 private Scanner input = new Scanner(System.in); private Random rand = new Random(); //モンスター集団の準備 //private Character[] ms = new Character[] { //一匹ずつモンスター情報を登録 // new Monster("ドラキュラ", 100), // new Monster("オオカミ男", 200), // new Monster("フランケン", 300), //各クラスからモンスターを召喚する private Monster[] ms = new Monster[] { new Bat(), new Wolf(), new Franken(), new Kaibutsukun(), new Dorakyura(), }; //プレイヤーの準備(ソロプレイヤーとする) //プレイヤーインスタンスの作成 private Character p = new Player(800); /** * バトルの開始と終了 * @param args 起動時引数 */ public static void main(String[] args) { //Battle b = new Battle(); //b.run(); //上の2行は下のようにまとめることができる。 new Battle().run(); //ハBattleが生まれ、その出来上がったものをrunする。 } /** * バトルが動作します */ private void run() { //privateをつけたrunというメソッドを作成(battleでしか、使えないメソッドを作成)。 this.showStartMessage(); //下方で作ったShowStartMessageを動かしますよ、という意味。 //thisは、上のnew Battle().run();をさします。 do { this.ShowPrompt(); this.beat(); if( !this.isAlive() ) { break; //ゲーム終了へ } }while(true); //}while( isAlive() );上のif文を使わない場合は、このように書けばOK this.showEndMessage(); } /** * 戦います!の部分をメソッド化します。 */ private void beat() { do { // TODO 自動生成されたメソッド・スタブ // ユーザ入力情報の取得(ユーザのやりたいことを取得)。変数入力で記憶する。 int selection = 0; //本当は、try下で、一行で済ませたいが、以降も使用するため、初期化だけ{}の外で行う。 try { selection = input.nextInt(); }catch( InputMismatchException e ) {//変な情報を入れられたら最初に戻るシステムを作成 input.nextLine(); //誤入力の時に、読み取った情報は使用済みなので不要、捨てる。 System.out.println("数値で入力してちょうだいね!"); continue; } // 選ばれたモンスターが殴られる try { ms[selection].damage( rand.nextInt(40) + 10); //ms配列から選ばれた、mというモンスターが殴られる //最低40、最大49の力で殴られて、hpが減ることをあらわします。 } catch (IndexOutOfBoundsException e) { //変な変数(はみ出た変数)が入力されると、最初に戻るシステムを作成 System.out.println("存在しないモンスターやで!番号間違ってない!?"); continue; } //プレイヤーがモンスターから反撃を受ける(攻撃したモンスターから殴り返されることにする) //モンスターが倒れ切ったときのみ反撃がない。モンスターの体力値があるときは反撃される。 if( ms[selection].isAlive()) { p.damage(rand.nextInt(40)+10); } break; //無事処理が済んだ場合は、繰り返しを中断する。 }while(true); } /** * バトル開始のメッセージの表示 */ private void showStartMessage() { System.out.println("モンスターバトル始まるよ!"); System.out.println("モンスターがたくさんあらわれた!"); System.out.println("モンスターをやっつけるのだ!"); System.out.println("攻撃するモンスターの番号を入力するんだ!"); System.out.println(); } /** * モンスター一覧を表示して、どれを攻撃するか */ private void ShowPrompt() { //やっつけるモンスターの名前を入力しなさい //プレイヤーの現在の状態を表示 System.out.println(p.getProfile()); System.out.println("-------------"); // 相手となるモンスターの一覧を表示(事前に変数設定していれば、下のように全部入力されて出てきます) for (int i = 0; i < ms.length; i++) { System.out.println( i + ":" + ms[i].getProfile() ); //長文の後半はgetProfileによってCharacterクラスに書き込みました。 } } /** * まだ戦えるやつが残っているかを調べます * @return まだ生存者がいればtrue */ private boolean isAlive() { //プレイヤーの体力値がなくなったら負け if( !p.isAlive() ) { System.out.println("あなたの負け!!"); return false; } // 全滅させたらクリア(何か数字がなくなったら全滅とする) for (int i = 0; i < ms.length; i++) { // if( ms[i].isAlive() ) { //体力まだあるか(生きているか)どうかをisAliveでCharacterクラスに移行。 //↑こうすることによって、ここがより分かりやすくなった。 return true; } } System.out.println("モンスターを全滅させました!"); System.out.println("あなたの勝利です! おめでとう!"); return false; } /** * バトル終了のメッセージの表示 */ private void showEndMessage() { System.out.println("モンスターバトル終了~♪"); System.out.println("また遊びにきてねぇ〜!"); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
package battle6; /** * キャラクターを表す抽象 基底クラス * @author がっちゃん * */ //abstract=未完成品 public abstract class Character { /** * モンスターの名前 */ private String name; /** * モンスターの体力を数字であらわす。 */ private int hp; /** * コンストラクタ構文で以下を設定 * @param name モンスターの名前 * @param hp モンスターの初期体力 */ public Character( String name , int hp ) { this.name = name; this.hp = hp; } /** * モンスターの名前を取得するメソッド * @return モンスター名 */ public String getName() { //モンスターの名前を見てもいいよ、というメソッドの作成。 //getがあるのに値を設定するための機能がないのは、名前を書き換えさせず、見せる気しかないからです。 //これで誤って変な情報に書き換えられないように守られることになります。「これをカプセル化」と言います。 return this.name; //これにより、プログラムのミスを事前に防げることができます。 } /** * 打撃を受けて体力が減ります。ついでに、ダメージごとのメッセージも追加してみる。 * @param amount 打撃の強さ */ public void damage( int amount ) { if( amount < 0 ) { //マイナスの力では殴られない return; } if( this.hp == 0) { System.out.println("モンスターはすでに倒れている・・・"); return; } System.out.println( this.name + "は" + amount + "のダメージ!"); if( amount < this.hp) { this.hp -= amount; this.cry(); } else { this.hp = 0; this.dyingMessage(); } } /** * ダメージを受けた時のメッセージを表示します */ protected abstract void cry(); /** * 倒れた時のメッセージを表示するメソッドを作成します。 */ protected abstract void dyingMessage() ; //System.out.println("倒された!"); //メッセージを未定(保留)にしました。 //具体的に実行するのは、違うところ(モンスター、プレイヤーが倒されるところ)で決めてくださいね、となった。 //オーバーライド時に、部品を供給してくれる。 /** * モンスターの現在の状態を文字列として返します。 * @return 状態をあらわす文字列 */ public String getProfile() { return this.name + "の体力は" + this.hp + "ポイント"; } /** * モンスターが生きているかを返します * @return 生きていれば true */ public boolean isAlive() { return this.hp > 0; } /** * 指定された体力を設定します * @param hp 新しい体力値 */ public void setHp(int hp) { // if( this.hp == 0 ) { System.out.println("体力値ゼロのため動けません"); //動けない状態になった場合、記録することを阻止します。 return; } if( hp < 0) { //ゼロより小さい数値になったらゼロに修正するよ。 this.hp = 0; } else { //ゼロ以上やったら教えてもらった変数に変更するよ。 this.hp = hp; //ここからしか変更できないようにする。教えてもらった変数に変更します(上書きするよ)。 } } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
package battle6; /** * プレイヤーの状態を保持するクラス * @author がっちゃん * */ //モンスタークラスの能力を継承したプレイヤークラスを作成 public class Player extends Character { /** *プレイヤーの体力の増減 */ //private int hp; //体力値は不正に情報を改ざんできないようにprivateで設定 //Monsterクラスでダメージ計算できるのでカットする。 /** * コンストラクタ * @param hp プレイヤーの初期体力 */ public Player( int hp ) { super("プレイヤー",hp); //this.hp = hp; これもMonsterクラスで計算できるのでカットする。 } @Override protected void dyingMessage() { // TODO 自動生成されたメソッド・スタブ //super.dyingMessage(); System.out.println("あなたは倒されました!"); } @Override protected void cry() { System.out.println("この俺にダメージを与えるだと!?"); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
package battle6; /** * バトルに登場する抽象モンスタークラス * @author がっちゃん * */ public abstract class Monster extends Character { /** * モンスターのコンストラクタ * @param name モンスターの名前 * @param hp モンスターの初期体力値 */ public Monster(String name, int hp) { super(name, hp); } //モンスターのやられるサマをそれぞれ作成するため、以下はコメントアウト // @Override // protected void dyingMessage() { // System.out.println("このモンスターを倒しました!"); // //super dyingMessage(); ここは不要になりました。 // } // @Override // protected void cry() { // System.out.println("ぎゃぁぁ〜!"); // } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
package battle6; /** * コウモリ男 * @author がっちゃん */ public class Bat extends Monster { public Bat() { //以下のようにモンスターの名前と体力値を設定する super("コウモリ男",100); } @Override protected void cry() { // コウモリ男がプレイヤーに攻撃されたときの声 System.out.println("キキィーーー"); } @Override protected void dyingMessage() { // コウモリ男が死んだときのメッセージ System.out.println("ぎゃるるる!"); System.out.println("コウモリ男を倒しました!"); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
package battle6; /** * オオカミ男 * @author がっちゃん */ public class Wolf extends Monster { public Wolf() { super("オオカミ男", 100); // TODO 自動生成されたコンストラクター・スタブ } @Override protected void cry() { //オオカミ男がプレイヤーに攻撃されたときの声 System.out.println("わおおぉおん!!"); } @Override protected void dyingMessage() { // オオカミ男が死んだときのメッセージ System.out.println("キャイ〜ン!"); System.out.println("オオカミ男を倒しました!"); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
package battle6; /** * フランケンシュタイン * @author がっちゃん */ public class Franken extends Monster { public Franken() { //以下のようにモンスターの名前と体力値を設定する super("フランケンシュタイン", 150); } @Override protected void cry() { // フランケンシュタインがプレイヤーに攻撃されたときの声 System.out.println("フンガァ、フンガァ!"); } @Override protected void dyingMessage() { // フランケンシュタインが死んだときのメッセージ System.out.println("フンガフッフ!"); System.out.println("フランケンシュタインを倒しました!"); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
package battle6; /** * 怪物くん * @author がっちゃん */ public class Kaibutsukun extends Monster { public Kaibutsukun() { //以下のようにモンスターの名前と体力値を設定する super("怪物くん", 300); } @Override protected void cry() { // 怪物くんがプレイヤーに攻撃されたときの声 System.out.println("おめぇ、いってぇなぁ!!"); } @Override protected void dyingMessage() { // 怪物くんが死んだときのメッセージ System.out.println("おら、死ぬのかぁ!?"); System.out.println("怪物くんを倒しました!"); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
package battle6; /** * ドラキュラ伯爵 * @author がっちゃん */ public class Dorakyura extends Monster { public Dorakyura() { //以下のようにモンスターの名前と体力値を設定する super("ドラキュラ伯爵", 80 ); } @Override protected void cry() { // ドラキュラ伯爵がプレイヤーに攻撃されたときの声 System.out.println("いたいザマスねぇ!"); } @Override protected void dyingMessage() { // ドラキュラ伯爵が死んだときのメッセージ System.out.println("やられたザマス!!"); System.out.println("ドラキュラ伯爵を倒しました!"); } } |
ファイルが9つに増えましたね。それぞれエラーメッセージがなければ実行してみましょう。実行結果のサンプルは以下の通りです。
今回は、プレイヤーの体力値を800にしたので勝利になりましたね。700くらいなら接戦になりそうかな!?皆さんも色々と数値を調整して遊んでみてくださいね。
7:特定のモンスターをダメージ値により急激に弱くする
これで、最後のプログラム修正になります。有名なモンスターである「オオカミ男」「フランケンシュタイン」「ドラキュラ」を、ダメージが30点以上たまると、急激に弱くなり、以降の攻撃は2倍のダメージを与えることができるようにします。
というわけで、「有名なモンスターなので通常は強いけど、30点以上ダメージをため込むとすんごく弱くなる」のような設定でプログラムしていきます。まずは、「FamousMonster.java」クラスを抽象型(未完成型)で追加。最初から抽象型でプログラムする場合は、以下のように「abstract」をチェックしておけば自動的に作成されます。
次に、メソッドのオーバーライド。下図のように「dam」と入力して入力支援機能「ctrl」+「SPACE」キーを押すと、入力支援候補が出てきます。「damage(int amount)」を選択すれば、オーバーライドしてくれます。
また、各「Bat.java」「Wolf.java」「Franken.java」「Kaibutsukun.java」「Dorakyura.java」で、以下のようにエラーがでいてる箇所があると思いますが、エラー箇所にマウスを持っていけば、支援機能が発動しますで、「実装されていないメソッドの追加」を選択すると不足分をオーバーライドしてくれます。
以下、最後のプログラムになります。
「Battle.java」は、プレイヤーやモンスターが攻撃されたときの体力値の減少を40という数値から「p.getPower()」「ms[selection].getPower」に修正しただけです。
「Character.java」も「public abstract int getPower();」を追加しただけです。
「monster.java」は全く変更していません。
「Player.java」「Kaibutsukun.java」「Bat.java」は、「getPower」のオーバーライドだけ。
「Wolf.java」「Franken.java」「Dorakyura.java」はFamousMonsterに変更し、「getPower」をオーバーライドしただけです。
それぞれ、大きな変更はありません。以下、最終プログラムです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 |
package battle7; import java.util.InputMismatchException; import java.util.Random; import java.util.Scanner; /** * モンスター集団とプレイヤーがバトルするプログラム * カプセル化による情報公開レベルの調整 * @author がっちゃん * */ public class Battle { //ユーザーの入力装置の作成、どれくらいの力が入っているのかも加味できるようにする。 private Scanner input = new Scanner(System.in); private Random rand = new Random(); //モンスター集団の準備 //各クラスからモンスターを召喚する private Monster[] ms = new Monster[] { new Bat(), new Wolf(), new Franken(), new Kaibutsukun(), new Dorakyura(), }; //プレイヤーの準備(ソロプレイヤーとする) //プレイヤーインスタンスの作成 private Character p = new Player(800); /** * バトルの開始と終了 * @param args 起動時引数 */ public static void main(String[] args) { new Battle().run(); //ハBattleが生まれ、その出来上がったものをrunする。 } /** * バトルが動作します */ private void run() { //privateをつけたrunというメソッドを作成(battleでしか、使えないメソッドを作成)。 this.showStartMessage(); //下方で作ったShowStartMessageを動かしますよ、という意味。 //thisは、上のnew Battle().run();をさします。 do { this.ShowPrompt(); this.beat(); if( !this.isAlive() ) { break; //ゲーム終了へ } }while(true); //}while( isAlive() );上のif文を使わない場合は、このように書けばOK this.showEndMessage(); } /** * 戦います!の部分をメソッド化します。 */ private void beat() { do { // ユーザ入力情報の取得(ユーザのやりたいことを取得)。変数入力で記憶する。 int selection = 0; //本当は、try下で、一行で済ませたいが、以降も使用するため、初期化だけ{}の外で行う。 try { selection = input.nextInt(); }catch( InputMismatchException e ) {//変な情報を入れられたら最初に戻るシステムを作成 input.nextLine(); //誤入力の時に、読み取った情報は使用済みなので不要、捨てる。 System.out.println("数値で入力してちょうだいね!"); continue; } // 選ばれたモンスターが殴られる try { ms[selection].damage( rand.nextInt(p.getPower() )+ 10); //ms配列から選ばれた、mというモンスターが殴られる //最低40、最大49の力で殴られて、hpが減ることをあらわします。 } catch (IndexOutOfBoundsException e) { //変な変数(はみ出た変数)が入力されると、最初に戻るシステムを作成 System.out.println("存在しないモンスターやで!番号間違ってない!?"); continue; } //プレイヤーがモンスターから反撃を受ける(攻撃したモンスターから殴り返されることにする) //モンスターが倒れ切ったときのみ反撃がない。モンスターの体力値があるときは反撃される。 if( ms[selection].isAlive()) { p.damage(rand.nextInt(ms[selection].getPower())+10); } break; //無事処理が済んだ場合は、繰り返しを中断する。 }while(true); } /** * バトル開始のメッセージの表示 */ private void showStartMessage() { System.out.println("モンスターバトル始まるよ!"); System.out.println("モンスターがたくさんあらわれた!"); System.out.println("モンスターをやっつけるのだ!"); System.out.println("攻撃するモンスターの番号を入力するんだ!"); System.out.println(); } /** * モンスター一覧を表示して、どれを攻撃するか */ private void ShowPrompt() { //やっつけるモンスターの名前を入力しなさい //プレイヤーの現在の状態を表示 System.out.println(p.getProfile()); System.out.println("-------------"); // 相手となるモンスターの一覧を表示(事前に変数設定していれば、下のように全部入力されて出てきます) for (int i = 0; i < ms.length; i++) { System.out.println( i + ":" + ms[i].getProfile() ); //長文の後半はgetProfileによってCharacterクラスに書き込みました。 } } /** * まだ戦えるやつが残っているかを調べます * @return まだ生存者がいればtrue */ private boolean isAlive() { //プレイヤーの体力値がなくなったら負け if( !p.isAlive() ) { System.out.println("あなたの負け!!"); return false; } // 全滅させたらクリア(何か数字がなくなったら全滅とする) for (int i = 0; i < ms.length; i++) { // if( ms[i].isAlive() ) { //体力まだあるか(生きているか)どうかをisAliveでCharacterクラスに移行。 //↑こうすることによって、ここがより分かりやすくなった。 return true; } } System.out.println("モンスターを全滅させました!"); System.out.println("あなたの勝利です! おめでとう!"); return false; } /** * バトル終了のメッセージの表示 */ private void showEndMessage() { System.out.println("モンスターバトル終了~♪"); System.out.println("また遊びにきてねぇ〜!"); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 |
package battle7; /** * キャラクターを表す抽象 基底クラス * @author がっちゃん */ //abstract=未完成品 public abstract class Character { /** * モンスターの名前 */ private String name; /** * モンスターの体力を数字であらわす。 */ private int hp; /** * コンストラクタ構文で以下を設定 * @param name モンスターの名前 * @param hp モンスターの初期体力 */ public Character( String name , int hp ) { this.name = name; this.hp = hp; } /** * モンスターの名前を取得するメソッド * @return モンスター名 */ public String getName() { //モンスターの名前を見てもいいよ、というメソッドの作成。 //getがあるのに値を設定するための機能がないのは、名前を書き換えさせず、見せる気しかないからです。 //これで誤って変な情報に書き換えられないように守られることになります。「これをカプセル化」と言います。 return this.name; //これにより、プログラムのミスを事前に防げることができます。 } /** * 打撃を受けて体力が減ります。ついでに、ダメージごとのメッセージも追加してみる。 * @param amount 打撃の強さ */ public void damage( int amount ) { if( amount < 0 ) { //マイナスの力では殴られない return; } if( this.hp == 0) { System.out.println("モンスターはすでに倒れている・・・"); return; } System.out.println( this.name + "は" + amount + "のダメージ!"); if( amount < this.hp) { this.hp -= amount; this.cry(); } else { this.hp = 0; this.dyingMessage(); } } /** * ダメージを受けた時のメッセージを表示します */ protected abstract void cry(); /** * 倒れた時のメッセージを表示するメソッドを作成します。 */ protected abstract void dyingMessage() ; //System.out.println("倒された!"); //メッセージを未定(保留)にしました。 //具体的に実行するのは、違うところ(モンスター、プレイヤーが倒されるところ)で決めてくださいね、となった。 //オーバーライド時に、部品を供給してくれる。 /** * モンスターの現在の状態を文字列として返します。 * @return 状態をあらわす文字列 */ public String getProfile() { return this.name + "の体力は" + this.hp + "ポイント"; } /** * モンスターが生きているかを返します * @return 生きていれば true */ public boolean isAlive() { return this.hp > 0; } /** * * @return */ public abstract int getPower(); /** * 指定された体力を設定します * @param hp 新しい体力値 */ public void setHp(int hp) { // if( this.hp == 0 ) { System.out.println("体力値ゼロのため動けません"); //動けない状態になった場合、記録することを阻止します。 return; } if( hp < 0) { //ゼロより小さい数値になったらゼロに修正するよ。 this.hp = 0; } else { //ゼロ以上やったら教えてもらった変数に変更するよ。 this.hp = hp; //ここからしか変更できないようにする。教えてもらった変数に変更します(上書きするよ)。 } } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
package battle7; /** * プレイヤーの状態を保持するクラス * @author がっちゃん */ //モンスタークラスの能力を継承したプレイヤークラスを作成 public class Player extends Character { /** *プレイヤーの体力の増減 */ //private int hp; //体力値は不正に情報を改ざんできないようにprivateで設定 //Monsterクラスでダメージ計算できるのでカットする。 /** * コンストラクタ * @param hp プレイヤーの初期体力 */ public Player( int hp ) { super("プレイヤー",hp); //this.hp = hp; これもMonsterクラスで計算できるのでカットする。 } @Override protected void dyingMessage() { // TODO 自動生成されたメソッド・スタブ //super.dyingMessage(); System.out.println("あなたは倒されました!"); } @Override protected void cry() { System.out.println("この俺にダメージを与えるだと!?"); } @Override public int getPower() { // 攻撃力を返します return 30; } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
package battle7; /** * バトルに登場する抽象モンスタークラス * @author がっちゃん */ public abstract class Monster extends Character { /** * モンスターのコンストラクタ * @param name モンスターの名前 * @param hp モンスターの初期体力値 */ public Monster(String name, int hp) { super(name, hp); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
package battle7; /** * 有名なモンスター抽象 基底クラス * @author がっちゃん *有名なので通常は強いが30点以上のダメージをくらうとすんごく弱くなる */ public abstract class FamouosMonster extends Monster { /* * 有名かどうかの確認 */ public boolean famous = true; public FamouosMonster(String name, int hp) { super(name, hp); // TODO 自動生成されたコンストラクター・スタブ } /** * 有名なモンスター固有のダメージ処理メソッドを作成 * 有名なモンスターで強いので通常はダメージは半分 * 今回はダメージが30点以上たまるとすんごく弱くなる * 弱くなったら会心の一撃でダメージ2倍 */ @Override public void damage(int amount) { if ( this.famous ) { if( amount >=30 ) { this.famous = false; System.out.println("30P以上ダメージが加算されたのでモンスターがすんごく弱くなったぞ!"); } //FamounMonsterの場合、攻撃力は1/2に減 amount /=2; }else { //FamousMonsterでかつ30P以上ダメージがたまったらダメージ2倍 amount *=2; } super.damage(amount); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
package battle7; /** * コウモリ男 * @author がっちゃん */ public class Bat extends Monster { public Bat() { //以下のようにモンスターの名前と体力値を設定する super("コウモリ男",100); } @Override protected void cry() { // コウモリ男がプレイヤーに攻撃されたときの声 System.out.println("キキィーーー"); } @Override protected void dyingMessage() { // コウモリ男が死んだときのメッセージ System.out.println("ぎゃるるる!"); System.out.println("コウモリ男を倒しました!"); } @Override public int getPower() { return 10; } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
package battle7; /** * オオカミ男 * @author がっちゃん */ public class Wolf extends FamouosMonster { public Wolf() { super("オオカミ男", 100); // TODO 自動生成されたコンストラクター・スタブ } @Override protected void cry() { //オオカミ男がプレイヤーに攻撃されたときの声 System.out.println("わおおぉおん!!"); } @Override protected void dyingMessage() { // オオカミ男が死んだときのメッセージ System.out.println("キャイ〜ン!"); System.out.println("オオカミ男を倒しました!"); } @Override public int getPower() { return 15; } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
package battle7; /** * フランケンシュタイン * @author がっちゃん */ public class Franken extends FamouosMonster { public Franken() { //以下のようにモンスターの名前と体力値を設定する super("フランケンシュタイン", 150); } @Override protected void cry() { // フランケンシュタインがプレイヤーに攻撃されたときの声 System.out.println("フンガァ、フンガァ!"); } @Override protected void dyingMessage() { // フランケンシュタインが死んだときのメッセージ System.out.println("フンガフッフ!"); System.out.println("フランケンシュタインを倒しました!"); } @Override public int getPower() { return 30; } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
package battle7; /** * 怪物くん * @author がっちゃん */ public class Kaibutsukun extends Monster { public Kaibutsukun() { //以下のようにモンスターの名前と体力値を設定する super("怪物くん", 300); } @Override protected void cry() { // 怪物くんがプレイヤーに攻撃されたときの声 System.out.println("おめぇ、いってぇなぁ!!"); } @Override protected void dyingMessage() { // 怪物くんが死んだときのメッセージ System.out.println("おら、死ぬのかぁ!?"); System.out.println("怪物くんを倒しました!"); } @Override public int getPower() { return 40; } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
package battle7; /** * ドラキュラ伯爵 * @author がっちゃん */ public class Dorakyura extends FamouosMonster { public Dorakyura() { //以下のようにモンスターの名前と体力値を設定する super("ドラキュラ伯爵", 80 ); } @Override protected void cry() { // ドラキュラ伯爵がプレイヤーに攻撃されたときの声 System.out.println("いたいザマスねぇ!"); } @Override protected void dyingMessage() { // ドラキュラ伯爵が死んだときのメッセージ System.out.println("やられたザマス!!"); System.out.println("ドラキュラ伯爵を倒しました!"); } @Override public int getPower() { return 30; } } |
まとめ
これで、「モンスターとプレイヤーがバトルするプログラム」の作成は完成を迎えました。いろいろな機能が少しずつ実装されていく形で授業を進めてくれたので分かりやすかったです。段階的にプログラムを作るたびに評価していく「スパイラル開発」とかいう手法で進めてくださったそうです。素人には分かりやすいプログラム方法でした。
あとはあの授業スピードについていけるくらいの基礎スキルを身に付けていくようにすれば、理解度はもっと向上するんだけどなぁ。
いろいろなプログラムを入力して身体で覚えるようにしないと、ですね。
それでは本日も最後までお付き合いいただき、ありがとうございました!