質問をすることでしか得られない、回答やアドバイスがある。

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

ただいまの
回答率

88.63%

Javaのメソッドの一つをランダムに呼び出す

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 1,880

porpora_0316

score 17

Javaで、複数のメソッドから一つをランダムに呼び出したいです。

slime,Dragon,Devilの中からランダムに取り出して、最終的に『勇者は(10,100,300のどれか)のダメージを受けた!』と表示することは可能ですか?
なお、継承などの練習をしていたので継承していますが、特に意味などはありません。
お願いします。
インデントなど不慣れなので、分かりにくかったら申し訳ありません。

import java.util.*;
class Enemy {
    public static int attack(){
        return 100;
    }
}

class Slime extends Enemy {
    public static int attack() {
        return 10;
    }
}

class Dragon extends Enemy {
    public static int attack() {
        return 100;
    }
}

class Devil extends Enemy {
    public static int attack() {
        return 300;
    }
}

public class Main {
    public static void main(String[] args) {
        Slime slime = new Slime();
        Dragon dragon = new Dragon();
        Devil devil = new Devil();
        ArrayList<String> teki = new ArrayList<String>();
           teki.add("slime");
           teki.add("dragon");
           teki.add("devil");
        int Rand = (int)(Math.random()*3);

    String moji = teki.get(Rand);
    System.out.println("勇者は" + moji.attack() + "のダメージを受けた!");

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+2

意味がないとおっしゃってる継承ですが、それを生かしてください。
ListをEnemy型で宣言して、各敵のオブジェクトを入れます。

public class Main {
    public static void main(String[] args) {
        Slime slime = new Slime();
        Dragon dragon = new Dragon();
        Devil devil = new Devil();
        ArrayList<Enemy> teki = new ArrayList<>();
           teki.add(slime);
           teki.add(dragon);
           teki.add(devil);
        int Rand = (int)(Math.random()*3);

        Enemy selected = teki.get(Rand);
        System.out.println("勇者は" + selected.attack() + "のダメージを受けた!");

    }
}

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/10/18 11:48

    Mainメソッドをこの通りにしてみたのですが、selectedの中身は『Devil@39a054a5』『Slime@39a054a5』『Dragon@39a054a5』と変わっているのにも関わらず表記は『勇者は100のダメージを受けた!』になってしまいます。

    キャンセル

  • 2018/10/18 11:53

    attack()は、staticメソッドなので、オーバーライドされません。

    キャンセル

  • 2018/10/18 11:56 編集

    では、Enemyクラスとその子クラス全てからstaticを消してください。

    キャンセル

  • 2018/10/18 11:59

    ありがとうございます。無事に出来ました。
    まだオブジェクト指向を勉強し始めたばかりなので、staticの意味やオーバーライドについて詳しく知りませんでした。
    もっと勉強します。

    キャンセル

-1

これ、コンパイル通ります?
あまりJavaはやっていないですが、コンパイル通らない気が...
String moji = ...;
... moji.attack() ... 
っておかしくないですか? そのまま読むと
Stringのattackメソッドを呼び出す です。 String::attack() なんてありましたっけ?

また、コンパイルエラーになるかどうかわかりません ( 試したことないから ) が、
なぜ Enemyを継承しているのにそれぞれ attackメソッドをstaticでやっているんでしょうか?
それなら継承しないほうがいいと思いますが。(強みが薄れる。)


私なら Enemyをそれぞれ継承して Enemyの配列かリストを用意する。

その前に、Enemyクラスやそれ周辺を何とかしないと...

今のところインターフェースで良さそうなのでinterface として Enemyを定義。

interface Enemy{
    int attack();
}

で、これを継承(厳密には実装だけど。)してスライムやらのクラスを定義。

public class Slim implements Enemy{
   public Slim( int id ){ id_ = id; }
   public int attack(){ return ap_; }
   private int ap_; // attack point. (攻撃力)
   private int id_; // このオブジェクトの番号?
}

こうすれば、

Slim slim1 = new Slim(1);
int a = slim1.attack();
// a のダメージを受けた!

みたいにできる。

でもこれはあまりよくない。

オブジェクト指向設計 getter, setterを使うなとはどういうことかを読むと、「データはオブジェクトに任せるべき」らしいです。

よって仕様そのものを変更します。

Enemyインターフェースよりも Chara抽象( インターフェースでもいいけど ) にしたほうがいいかな。

参考: アブストラクト

public abstract class Chara{
  abstract boolean attack( Chara c );
  abstract boolean attacked( int n ); // 攻撃されたときの処理 
}

これを継承してSlimやらを定義。

public class Slim implements Enemy{
   public Slim( int id ){ id_ = id; }
   public boolean attack( Chara c ){
           if( c.attacked( ap_ ) ){ // 攻撃して相手が HP = 0 なら
                return true;
           }
   return false;
   }
   public boolean attacked( int n ){
      hp_ -= n; // hp_ = hp_ - n; と同義
      if( hp_ >= 0 ) return true;
   return false;
   }
   private int ap_; // attack point. (攻撃力)
   private int id_; // このオブジェクトの番号?
   private int hp_; // HP
}

のようにHPやらMPやらはオブジェクトが管理するようにする。

で、attackメソッドに攻撃対象のオブジェクトを渡せば攻撃側のap_ ( 攻撃力 ) による攻撃が差し引かれて...っていう風に。

// mainメソッド等の呼び出し元で
Slim slim1 = new Slim(1);
Hero hero = new Hero(1);
slim1.attack( hero ); // 主人公に攻撃
hero.attack( slim1 ); // スライム( スライム1 ) に攻撃

みたいにできる。

即席だからものすごい適当で、本来ならattackedは親であるabstractではprotectedでmainメソッドのような外部からは触れないようにしたり、

コンストラクタをprotectedかなんかにしてデザインパターンのFactoryパターンかなんかで

  1. ファイルから前回の攻撃力やらHPやらのデータを取得
  2. そのデータからオブジェクトを生成して返す

みたいな感じでやったりするはずだけど、あくまで例だから省略。(スルー)

ここまでが準備段階。

で、問題の

slime,Dragon,Devilの中からランダムに取り出して、最終的に『勇者は(10,100,300のどれか)のダメージを受けた!』と表示することは可能ですか?

ですけど、これは私なら先ほどのChara抽象の配列かリスト等を生成。

List<Chara> enemies = new ArrayList<Chara>(); // 敵用arrayリスト

で、オブジェクト指向を取り入れた言語では

子クラスでnewして 親で保持することが可能です。

本来なら ArrayList<Chara> ... = new ArrayList<Chara>(); となっているはずですが、
List<Chara> ... = new ArrayList<Chara>(); としますよね?

それと一緒です。

参考: インターフェース

ということで

// List<Chara> enemies =...;
enemies.add( new Slim1(1) );
enemies.add( new Slim2(2) );
enemies.add( new Dragon(1) );
...

と登録しておき、乱数を発行して

// int r; // すでに乱数は発行されているものとして
enemies[r].attack( hero );

のようにできる。

もちろん、"スライム1によってダメージ10を受けた..." 的な文章も出せるはずだけど、そこは質問者さんが工夫してね。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/10/18 15:39

    細かく教えて下さってありがとうございます。
    ベストアンサーは下の方にしたのですが、参考にさせていただきます。

    キャンセル

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

  • ただいまの回答率 88.63%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る