🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

解決済

2回答

1874閲覧

javaで作成したプログラムコードを短くしたい

D-coder

総合スコア9

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

0グッド

0クリップ

投稿2021/01/12 07:06

編集2021/01/14 06:51

先日は無礼な質問の投稿を失礼いたしました。

自分なりに改善を重ねた結果分からない点が出ましたので質問致します。

javaで作成したジャンケンプログラムのコードを短くしたいと考えています。

※作っているゲームの仕様や機能は以下の通り
■キーボードから入力して敵と主人公に名前を付ける
■敵と主人公でじゃんけんをする、(主人公の手はコマンド入力、敵の手は自動)
■じゃんけんで勝った方が負けた方にダメージを与える(主人公と敵のHPは20)
■ダメージは1~3のランダム
■10分の1の確立でクリティカルヒット、上記のダメージの5倍のダメージ
(1ダメージがクリティカルだと5ダメージになる)
■主人公のHPが0になったらyou-Rosstと表示しゲーム終了
■敵のhpが0になるとyou-Winと表示してゲーム終了

短くしたいと考えているコード

「ジャンケンに主人公が勝利した場合のダメージ処理メソッド」と「ジャンケンに敵が勝利した場合のダメージ処理メソッド」があるクラスです。

自分なりに変数などのを使って戦闘時のクリティカル分岐のコードを短くしました。

ですがSystem.out.println();を使った同じような内容の文章を下記のコードで四回繰り返してしまっているのですが、更に短くすることはできるのでしょうか?

****主人公が勝利した場合のメソッドも敵が勝利した場合のメソッドも似たような処理なので、何かすれば更に短く出来そうなのですがその何かが分かりません。


ヒントをいただけますでしょうか?

public class BattleSystem{ /*フィールド値*/ public int playrHp = 20;//主人公のHP public int enemiHp = 20;//敵のHP /*主人公が勝利した場合の戦闘処理メソッド*/ void ataltuku(){ this.playrHp = playrHp; this.enemiHp=enemiHp; java.util.Random rand = new java.util.Random(); java.util.Random rand2 = new java.util.Random(); int damag = rand.nextInt(3)+1;//ダメージのランダム数字1~3を取得 int criticalCheck = rand2.nextInt(10);//クリティカル判定 9の時にクリティカル int criticalDamage = damag * 5;//クリティカル判定時のダメージ【com*5倍のダメージ】 /*戦闘時のダメージ分岐*/ if(criticalCheck < 8 ) { System.out.println(Main.nameInfo.inputName+"の勝ち"); System.out.println(Main.nameInfo.inputEnemi+"は"+damag+"のダメージを受けた"); this.enemiHp= enemiHp-damag; System.out.println(Main.nameInfo.inputEnemi+"HP:"+this.enemiHp+"/20"); System.out.println(Main.nameInfo.inputName+"HP:"+this.playrHp+"/20"); System.out.println("-----------------------------------------"); } if(criticalCheck == 9 ) { System.out.println(Main.nameInfo.inputName+"の勝ち"); System.out.println(Main.nameInfo.inputEnemi+"は"+criticalDamage+"のダメージを受けた"); this.enemiHp= enemiHp-criticalDamage; System.out.println(Main.nameInfo.inputEnemi+"HP:"+this.enemiHp+"/20"); System.out.println(Main.nameInfo.inputName+"HP:"+this.playrHp+"/20"); System.out.println("-----------------------------------------"); } }//ataltuku() /*敵が処理した場合の戦闘処理メソッド*/ void dameizi(){ this.playrHp = playrHp; this.enemiHp=enemiHp; java.util.Random rand = new java.util.Random(); java.util.Random rand2 = new java.util.Random(); int damag = rand.nextInt(3)+1;//ダメージのランダム数字1~3を取得 int criticalCheck = rand2.nextInt(10);//クリティカルのランダムな数値 9でクリティカル int cd = damag * 5;//クリティカル判定時のダメージ【com*5倍のダメージ】 if( criticalCheck < 8 ) { System.out.println(Main.nameInfo.inputEnemi+"の勝ち"); System.out.println(Main.nameInfo.inputName+"は"+damag+"のダメージを受けた"); this.playrHp=playrHp-damag; System.out.println(Main.nameInfo.inputName+"HP:"+this.playrHp+"/20"); System.out.println(Main.nameInfo.inputEnemi+"HP:"+this.enemiHp+"/20"); System.out.println("-----------------------------------------"); } if( criticalCheck == 9 ) { System.out.println(Main.nameInfo.inputEnemi+"の勝ち"); System.out.println(Main.nameInfo.inputName+"は"+cd+"のダメージを受けた"); this.playrHp=playrHp-cd; System.out.println(Main.nameInfo.inputName+"HP:"+this.playrHp+"/20"); System.out.println(Main.nameInfo.inputEnemi+"HP:"+this.enemiHp+"/20"); System.out.println("-----------------------------------------"); } }//dameizi() }

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

今のコードを最大限尊重すると、こんな感じでしょうか。

  • 中途半端な命名見直し
    すいませんguとか使って^^;
  • Main.nameInfoへの依存解消
    結局BattleSystemでしか使っていないうえ、長くて冗長。
  • 変わらない変数はfinal
    意図せず変更されないように。
  • 表示順をあなた敵に固定
    おそらくわざとやっているのでしょうが、共通化しにくいのと入れ替わると意外と見にくい。

Java

1import java.util.Random; 2import java.util.Scanner; 3 4public class Main { 5 public static void main(String[] args) { 6 final Scanner scanner = new Scanner(System.in); 7 final Random rand = new Random(); 8 9 // NamedはBattleSystemでしか使ってないのであげちゃう ついでにRandomも 10 final BattleSystem status = new BattleSystem(new Named(scanner), rand); 11 12 // 数字だとわかりにくいので 13 final int gu = 0; 14 final int tyoki = 1; 15 final int pa = 2; 16 17 while (0 < status.playerHp && 0 < status.enemyHp) { 18 System.out.println("-----------------------------------------"); 19 System.out.println("コマンド? 0:グー 1:チョキ 2:パー"); 20 int hand = scanner.nextInt(); 21 22 if (hand == 9) { 23 System.out.println("コマンド9検出:強制終了しました"); 24 return; // 勝ち負け判定に入らないように抜ける 25 } 26 27 int com = rand.nextInt(3); 28 29 if (hand == com) { 30 System.out.println("引き分け"); 31 } 32 // かっこや改行があれば長い条件も結構わかりやすくないですか 33 else if ((com == gu && hand == pa) || 34 (com == tyoki && hand == gu) || 35 (com == pa && hand == tyoki)) { 36 status.attack(); 37 } else { 38 status.damage(); 39 } 40 } 41 42 System.out.println("-----------------------------------------"); 43 if (status.enemyHp <= 0) { 44 System.out.println("☆YOU WIN☆"); 45 } else { 46 System.out.println("✖YOU LOSE✖"); 47 } 48 } 49} 50 51class Named { 52 final String playerName; 53 final String enemyName; 54 55 // どうせinput_youname するならコンストラクタでいいでしょう メンバ変数もfinalにできる 56 Named(Scanner scanner) { 57 System.out.print("あなたの名前を入力してください ▼ "); 58 playerName = scanner.nextLine(); 59 System.out.println(playerName + "が入力されました"); 60 61 System.out.print("敵の名前を入力してください ▼ "); 62 enemyName = scanner.nextLine(); 63 System.out.println(enemyName + "が入力されました"); 64 65 System.out.println(); 66 System.out.println("あなたの名前は" + playerName + "です"); 67 System.out.println("敵の名前は" + enemyName + "です"); 68 } 69} 70 71class BattleSystem { 72 private final Named nameInfo; 73 private final Random rand; 74 75 int playerHp = 20; 76 int enemyHp = 20; 77 78 BattleSystem(Named named, Random random) { 79 nameInfo = named; 80 rand = random; 81 } 82 83 void attack() { 84 int damag = getDamagePoint(); 85 enemyHp -= damag; // enemiHp = enemiHp - damag; 同じ意味 86 print(nameInfo.playerName, nameInfo.enemyName, damag); 87 } 88 89 void damage() { 90 int damag = getDamagePoint(); 91 playerHp -= damag; 92 print(nameInfo.enemyName, nameInfo.playerName, damag); 93 } 94 95 private int getDamagePoint() { 96 int damag = rand.nextInt(3) + 1; 97 if (rand.nextInt(10) == 9) { // クリティカル時 5倍 98 damag *= 5; // damag = damag * 5; 同じ意味 99 } 100 return damag; 101 } 102 103 private void print(String winner, String loser, int damage) { 104 System.out.println(winner + "の勝ち"); 105 System.out.println(loser + "は" + damage + "のダメージを受けた"); 106 107 System.out.println(); 108 System.out.println(nameInfo.playerName + " HP:" + playerHp + "/20"); 109 System.out.println(nameInfo.enemyName + " HP:" + enemyHp + "/20"); 110 } 111}

ゲームの修正点1 継承・抽象メソッドを使用したゲームにする
具体的にはCpuとHuman(人間)をそれぞれ別のクラスとして作り、共通の親クラスPlayerを継承するようにしたいです。

もともとの内容にもついでに一例を出しておきます(あんまりイケてないですw
9割方できているのでclass Humanclass Cpuを作ってみてください^^(int getHand()を実装するだけです)

Java

1import java.util.Random; 2import java.util.Scanner; 3 4public class Main { 5 public static void main(String[] args) { 6 // 人間を表すHumanクラスからインスタンスを一つ生成します 7 // ゲームに参加する人間は一人なので、new Humanするのはここでの1回限り 8 // ほかでnew Humanしてしまうと別の人間が新たに参加することになってしまう! 9 Player player = new Human("あなた", 20); 10 11 // CPUを表すHumanクラスからインスタンスを一つ生成します 12 // ゲームに参加するCPUは一個なので、...以下同文 13 Player cpu = new Cpu("敵", 20); 14 15 System.out.println(); 16 System.out.println("あなたの名前は" + player.getName() + "です"); 17 System.out.println("敵の名前は" + cpu.getName() + "です"); 18 19 final int gu = 0; 20 final int tyoki = 1; 21 final int pa = 2; 22 23 // どちらとも生きている(0 < Hp)間はループ 24 while (player.isAlive() && cpu.isAlive()) { 25 int hand = player.getHand(); // playerの手を取得 26 if (hand == 9) { 27 System.out.println("コマンド9検出:強制終了しました"); 28 return; // 勝ち負け判定に入らないように抜ける 29 } else if (2 < hand) { 30 System.out.println("数値は0・1・2から選んで入力して下さい"); 31 continue; // ループ先頭に戻り手の再入力 32 } 33 34 int com = cpu.getHand(); // cpuの手を取得 35 36 if (hand == com) { 37 System.out.println("引き分け"); 38 continue; 39 } else if ((com == gu && hand == pa) || 40 (com == tyoki && hand == gu) || 41 (com == pa && hand == tyoki)) { 42 player.attack(cpu); // playerの勝ち playerがcpuに攻撃 43 } else { 44 cpu.attack(player); // cpuの勝ち cpuがplayerに攻撃 45 } 46 47 System.out.println(); 48 System.out.println(player); // toString()をオーバ-ライド 名前 HP:現在値/Max値 49 System.out.println(cpu); // 同上 50 } 51 52 System.out.println("-----------------------------------------"); 53 if (player.isAlive()) { 54 System.out.println("☆YOU WIN☆"); 55 } else { 56 System.out.println("✖YOU LOSE✖"); 57 } 58 } 59} 60 61abstract class Player { 62 // あまりstaticは使いたくないが、まあprotected finalならいいでしょう^^; 63 // Scannerに依存するのもどうなの?感ありw 64 protected static final Scanner scanner = new Scanner(System.in); 65 protected static final Random rand = new Random(); 66 67 private final String name; 68 private final int maxHp; 69 70 private int hp; 71 72 73 Player(String tmpName, int hp) { // 呼びかけ用の仮名、初期hp 74 this.hp = maxHp = hp; 75 76 System.out.print(tmpName + "の名前を入力してください ▼ "); 77 name = scanner.nextLine(); 78 System.out.println(name + "が入力されました"); 79 } 80 81 String getName() { return name; } // 名前の取得 82 83 boolean isAlive() { return 0 < hp; } // 生きているかどうか 84 85 abstract int getHand(); // 手の番号取得 0:グー 1:チョキ 2:パー 86 87 // 相手に攻撃 88 // なぜ引数で相手を与えるかというと、両方のnameが欲しいから 89 void attack(Player other) { 90 int damage = rand.nextInt(3) + 1; 91 if (rand.nextInt(10) == 9) { 92 damage *= 5; 93 } 94 other.hp -= damage; // 相手のHpを減らす 95 96 System.out.println(name + "の勝ち"); 97 System.out.println(other.name + "は" + damage + "のダメージを受けた"); 98 } 99 100 @Override public String toString() { return name + " HP:" + hp + "/" + maxHp; } 101} 102 103class Human extends Player { 104 Human(String tmpName, int hp) { 105 super(tmpName, hp); 106 } 107 108 @Override int getHand() { 109 System.out.println("-----------------------------------------"); 110 System.out.println("コマンド? 0:グー 1:チョキ 2:パー"); 111 return scanner.nextInt(); 112 } 113} 114 115class Cpu extends Player { 116 Cpu(String tmpName, int hp) { 117 super(tmpName, hp); 118 } 119 120 @Override int getHand() { return rand.nextInt(3); } 121}

投稿2021/01/14 14:30

編集2022/09/18 16:37
TN8001

総合スコア9855

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

共通の親クラスPlayerに、CpuとPlayerで共通の変数(hp,name)や処理(ダメージをうける処理)などを定義し、それぞれ異なる処理を抽象メソッドを利用した形に変更するにはどうすればよいでしょうか?

敵味方に共通しているものは、どちらもゲームに登場するキャラクターである事です。
つまり、このキャラクターを親クラスとすれば良いでしょう。
貴方のクラスを尊重するとしたらこんな感じのクラスを親クラスとしておくのが良いでしょう。

public class Character{ private String name; private int hp; Character(String char_name, int char_hp){ hp = char_hp; name = char_name; } //戦闘処理メソッド(継承用) void battle(Character character){} //ダメージ用関数 void damage(int sub){ hp -= sub; } //死亡判定 bool isDead(){ if (hp <= 0) return true; return false; } String getName(){ return name; } }

同じような処理を繰り返すハードコーディングを避けた設計にするにはどうすれば良いでしょうか?

まず、2~3行以上同じだなと思う部分を関数化してしまいましょう。
後は一度関数化したからと言って放置してしまう事をせず、常に頭の中にソースコードをイメージしながら書いていきましょう。

投稿2021/01/12 07:33

編集2021/01/12 07:34
stdio

総合スコア3307

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問