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

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

ただいまの
回答率

88.19%

java  参照型変数

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 1,642
コード

public class Player{
    
    
    //定数、変数
    static final int STONE = 0, SCISSORS = 1, PAPER = 2;  //ジャンケンの手を表す定数
    private String name_;                                 //プレイヤーの名前 
    private int winCount_ = 0;                            //プレイヤーの勝った回数


    //nameのコンストラクタ
    public Player(String name){
        this.name_ = name;
    }
    
    
    //ジャンケンの手を出すメソッド
    public int showHand(){
        
        int hand = 0;
        
        Random rnd = new Random();           //ランダムに数字を取り出す公式
        int randomNum = rnd.nextInt(3);      //0から2の数字をランダムに取り出す

        if (randomNum == 0){
            hand = STONE;
        }
        else if (randomNum == 1){
            hand = SCISSORS;
        }
        else if (randomNum == 2){
            hand = PAPER;
        }

        return hand;          //決定した手を戻り値として返す
    }
    
    
    //勝敗を聞くメソッド
    public void notifyResult(boolean result){
        
        if (true == result){        //true勝ち、false負け
            winCount_ ++;         //勝った場合は勝ち数を加算する
        }
    }
    
    
    //自分の勝った回数を答えるメソッド
    public int getWinCount(){
        return winCount_;
    }
    
    
    //自分の名前を答えるメソッド
    public String getName(){
        return name_;
    }
}

コード

public class Judge{
    
    
    //ジャンケンを開始するメソッド
    public void startJanken(Player player1, Player player2){
        
        System.out.println("【ジャンケン開始】\n");

        for (int cnt = 0; cnt < 3; cnt++){                  //ジャンケンを3回行う
            
            System.out.println("【" + (cnt + 1) + "回戦目】");

            Player winner = judgeJanken(player1, player2);  //プレイヤーの手を見て、どちらが勝ちかを判定する
            
            if (winner != null){
                
                System.out.println("\n" + winner.getName() + "が勝ちました!\n");  //勝者を表示する
                winner.notifyResult(true);                                    //勝ったプレイヤーへ結果を伝える
            }
            else{
                System.out.println("\n引き分けです!\n");
            }
        }

        System.out.println("【ジャンケン終了】\n");

        Player finalWinner = judgeFinalWinner(player1, player2);                        //最終的な勝者を判定する

        System.out.print(player1.getWinCount() + " 対 " + player2.getWinCount() + "で"); //結果の表示

        if (finalWinner != null){
            System.out.println(finalWinner.getName() + "の勝ちです!\n");
        }
        else{
            System.out.println("引き分けです!\n");
        }
    }
    
    
    //プレイヤーの手を見て、どちらが勝ちかを判定するメソッド
    private Player judgeJanken(Player player1, Player player2){
        
        Player winner = null;

        int player1hand = player1.showHand();  //プレイヤー1の手を出す

        int player2hand = player2.showHand();  //プレイヤー2の手を出す

        //それぞれの手を表示する
        printHand(player1hand);
        System.out.print(" vs. ");
        printHand(player2hand);
        System.out.print("\n");

        //プレイヤー1が勝つ場合
        if ((player1hand == Player.STONE && player2hand == Player.SCISSORS)
         || (player1hand == Player.SCISSORS && player2hand == Player.PAPER)
         || (player1hand == Player.PAPER && player2hand == Player.STONE)){
            
            winner = player1;
        }
        //プレイヤー2が勝つ場合
        else if ((player1hand == Player.STONE && player2hand == Player.PAPER)
              || (player1hand == Player.SCISSORS && player2hand == Player.STONE)
              || (player1hand == Player.PAPER && player2hand == Player.SCISSORS)){
            
            winner = player2;
        }

        //どちらでもない場合は引き分け(nullを返す)

        return winner;
    }
    
    

    //最終的な勝者を判定するメソッド
    private Player judgeFinalWinner(Player player1, Player player2){
        
        Player winner = null;

        int player1WinCount = player1.getWinCount();  //Player1から勝ち数を聞く

        int player2WinCount = player2.getWinCount();  //Player2から勝ち数を聞く

        if (player1WinCount > player2WinCount){
            winner = player1;  //プレイヤー1の勝ち
        }
        else if (player1WinCount < player2WinCount){
            winner = player2;  //プレイヤー2の勝ち
        }

        // どちらでもない場合は引き分け(nullを返す)

        return winner;
    }
    
    

    //ジャンケンの手を表示するメソッド
    private void printHand(int hand){
        
        switch (hand){
        
            case Player.STONE :
                System.out.print("グー");
                break;

            case Player.SCISSORS :
                System.out.print("チョキ");
                break;

            case Player.PAPER :
                System.out.print("パー");
                break;

            default :
                break;
        }
    }
}

コード

public class Main {
    
    /**オブジェクト指向によるジャンケンプログラム*/
    
        public static void main(String[] args)
        {
            // 審判(斎藤さん)のインスタンス生成
            Judge saito = new Judge();

            // プレイヤー1(村田さん)の生成
            Player murata = new Player("村田さん");

            // プレイヤー2(山田さん)の生成
            Player yamada = new Player("山田さん");

            // 村田さんと山田さんをプレイヤーとしてジャンケンを開始する
            saito.startJanken(murata, yamada);
        }
    }

上のコードはじゃんけんのサンプルコードなのですが、PlayerクラスがあるのでPlayer型を作っているのはわかります。
またPlayer型の変数player1,player2を作っているのもわかります。
ですが、プログラム上に何回かでている、
int player1hand = player1.showHand(); や、
(player1hand == Player.STONE && player2hand == Player.SCISSORS)
の、player1.とかPlayer.はなんでしょうか?


たとえば、
public class SimpleClass {
    
    int data;

public class SimpleClassRunner {

    public static void main(String[] args) {
        SimpleClass ref=new SimpleClass();

        ref.data=100;
        
        System.out.println(ref.data);
    }

}
この場合のref.は参照型変数を表しているのはわかります。

じゃんけんのプログラムの方のPlayer.やplayer1.はインスタンスを生成していなませんが、参照型変数なのでしょうか?
Player.にいたってはクラス名ですが、どうなのでしょうか?
よろしくお願いいたします。




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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 2

+1

player1はJudgeクラスにあるメソッドの仮パラメータですよね?
このメソッドはPlayer型のインスタンスを要求しています.
そのインスタンスを使うために,渡されたそのインスタンスを扱う名前として,
player1,player2を使っています.
このコードでいえば,MainクラスでJudgeインスタンスのsaitoのメソッドstartJankenに
Playerインスタンスのmurata,yamadaを渡しています.
            saito.startJanken(murata, yamada);
片や,JudgeクラスでstartJankenはこう宣言しています.
    public void startJanken(Player player1, Player player2)
この場合,起動されたsaito.startJanken(murata, yamada)は,
player1をmurata,player2をyamadaとしてメソッドの処理をします.

一方,Player.の方ですが,Playerクラス内でstaticな変数(finalなので定数だが)を宣言しています.
staticフィールドはインスタンスに依存しないので,アクセスする際インスタンスを経由する必要がありません.
むしろ,インスタンスに紐付かない情報なのにインスタンス経由でアクセスするのは混乱の原因になります.
なので,クラス内のstaticなメンバにアクセスする際は,クラス名.メンバでアクセスする決まりになっているのです.
このため,staticなフィールドおよびメソッドはそれぞれクラス変数,クラスメソッドとも呼ばれます.
試しにEclipseでstaticメンバにインスタンス経由でアクセスしようとすると,エラーにはなりませんが黄線で注意されます.

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2015/07/24 15:41

    回答ありがとうございます^^

    Player.の方は理解できました。

    player1はJudgeクラスにあるメソッドの仮パラメータ、とはどういうことでしょうか?
    player1は参照型変数ではないのでしょうか?

    キャンセル

  • 2015/07/24 17:16

    参照型変数です.しかし,このメソッドを書いている時点ではこの実体が何かはわかりません.
    この実体は引数を渡してメソッドを起動した時に決まります.

    キャンセル

checkベストアンサー

0

まず int player1hand = player1.showHand(); が出てきているところを考えましょう。
private Player judgeFinalWinner(Player player1, Player player2){...}
というメソッドの中ですね。
このメソッドの引数は2つありますが、いずれもPlayer型です。

次に、このメソッドが呼ばれているところを見ましょう。
public void startJanken(Player player1, Player player2){...}
の中ですね。

さらに、このstartJankenメソッドが呼ばれているところを見ましょう。
saito.startJanken(murata, yamada);
最後に記述されているMainクラスのmainメソッド内ですね。

このmainメソッドでは、先にmurata、yamadaというPlayerオブジェクトが生成されています。
これらを引数としています。

ここで、話を戻します。
int player1hand = player1.showHand();
このplayer1はPlayer型の引数として渡された変数murataです。


質問者さんがこれならわかりますと書いています部分を変更してじゃんけんのサンプルのように書くとこうなります。
public class SimpleClass { 
    int data; 
}

public class RefSimpleClass {
    SimpleClass simple = new SimpleClass();
    public void setData(SimpleClass sc) {
        simple.data = sc.data;
    }
    public int getData() {
        return simple.data;
    } 
}
public class SimpleClassRunner { 
    public static void main(String[] args) { 
        SimpleClass ref=new SimpleClass(); 
        RefSimpleClass rsc = new RefSimpleClass();
        ref.data=100; 
        rsc.setData(ref);
//        System.out.println(ref.data); 
        System.out.println( rsc.getData() );
    } 
}
といった感じになるのでしょうか?(一部修正しました 確認していないのでまだ間違いがあるかもしれません)


結論として、オブジェクトという概念をもう少し勉強されるとよいと思います。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2015/07/24 17:08

    回答ありがとうございます^^
    すごくわかりやすかったです!
    ありがとうございました。

    もう一つお伺いしたいのですが、
    Player winner = judgeJanken(player1, player2);
    のところで、もしプレイヤー1が勝った場合
    Player winner = player1
    となると思うのですが、その次の文の
    System.out.println("\n" + winner.getName() + "が勝ちました!\n");
    でwinner.getNameが村田に変わるということであってますでしょうか?
    そもそも
    public String getName(){
    return name_;
    }
    の役割があよくわかりません。
    よろしければ教えていただきたいです。

    キャンセル

  • 2015/07/24 17:20

    Playerクラスのname_フィールドはprivateで,外部のクラスからアクセスできません.
    (試しにMainクラスのmainメソッドのmurata,yamadaの宣言の後にmurata.name_としてみてください.コンパイルエラーになるはずです.)
    なのでメソッドを通してフィールドの値を取得する仕組みにしているのです.
    「なんでそんな面倒なことを?」と思うでしょうが,こうすることでクラスの安全性を保っているのです.この仕組みがなく,name_がpublicだと,
    例えばmurata.name_ = "中村さん";とすることで名前を変更できてしまいます.

    キャンセル

  • 2015/07/24 17:30

    最初はセッターとゲッターの概念がわからないと思います。
    まずは、そういうものなんだというくらいで使ってみるとよいでしょう。
    セッターとゲッターを使うことによって、privateな変数を外部から見えないようにする効果もありますが、間違った値を入れないようにする仕組みをセッターメソッドに含めることもできます。
    詳しくは、いろんな文献やwebに公開されていますので、「java getter setter」や「java ゲッター セッター」で検索するとよいでしょう。

    キャンセル

  • 2015/07/27 10:08

    swordoneさん、tttsakさん回答ありがとうございました!

    private変数を使っているからなんですね。
    ありがとうございました。

    キャンセル

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

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

関連した質問

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