Help us understand the problem. What is going on with this article?

オブジェクト指向が5000%理解できる記事(実践編)

More than 1 year has passed since last update.

実践編

最近、こんな問題がTwitterで話題になってました。

というわけで、この問題をオブジェクト指向でコーディングするとどんな感じになるのか。やってみたいと思います。

理論編から読みたいかたはコチラ

(1)オブジェクトを洗い出す

問題文を見ると、「人(プレイヤーと呼びましょう)」と「カード」が登場していますね。これが今回のオブジェクトたちです。

class Player {

}

class Card {

}

(2)各オブジェクトのプロパティを洗い出す

プレイヤー

プレイヤーのプロパティは、「プレイヤーの名前(A,B,C)」「額にかざしているカード(ランダムで1枚引いたやつ)」ですね。

class Player {
  name;
  card;
}

カード

カードのプロパティは、「数字(1~5のどれか)」ですね。

class Card {
  number;
}

(3)各オブジェクトのメソッドを洗い出す

プレイヤー

プレイヤーのメソッドは、「ランダムにカードを1枚のカードを引いて額にかざす」と「MAX, MID, MIN, ?のいずれかを回答する」ですね。

class Player {
  name;
  card;

  draw(cards) { }
  answer(cards) { }
}
カード

カードにメソッドは、ありません!だって現実世界のカード、自分から動いたりしないですもの。

class Card {
  number;

  //メソッドはなし!
}

(4)オブジェクト間のメッセージを洗い出す

今回のメッセージは「プレイヤーが相手のカードを見る」と「プレイヤーがカードの数字を見る」ですね。

class Player {
  name;
  card;

  draw(cards) { }
  answer(cards) {
   //カードオブジェクトの数字を確認する。
  }
}

以上が、オブジェクト指向をコードに落とし込むまでの手順になります。慣れてしまえばとても便利なので、是非マスターしてくださいね!

後書き

C#を例にコード全体の全体像を書いてみました。参考までに読んでみてください。

Hello.cs
using System;
using System.Collections.Generic;

class Hello {
    public static void Main(){ //つまるところ、メイン関数はフローチャートなのだ。
        //カードを用意
        int num_cards = 5;
        List<Card> cards = new List<Card>();
        for(int i = 0; i < num_cards; i++) {
            int number = i + 1;
            cards.Add(new Card(number));
        }

        //プレイヤーを用意
        int num_players = 3;
        List<Player> players = new List<Player>();
        for(int i = 0; i < num_players; i++) {
            string name = ToAlphabet(i);
            players.Add(new Player(name));
        }

        if(num_cards < num_players) {
            Console.WriteLine("エラーだよ!");
            return;
        }

        //各プレイヤーがカードを引く
        foreach(Player p in players) {
            p.Draw(cards); //カードを引くのでカードを引数で渡す
        }

        //プレイヤーが順番に回答してゆく
        foreach(Player p in players) {
            string answer = p.Answer(players); //他のプレイヤーの様子を見るのでプレイヤーを引数で渡す
            Console.Write("{0}=>{1}", p.name, answer);
            if(answer == "?" && players[players.Count-1] != p) { //次の回答者がいたらカンマを出力して続行
                Console.Write(", ");
            }
            else { //次の回答者がいなかったらおしまい。
                Console.WriteLine();
                break;
            }
        }
    }

    //数字をアルファベットに変換!
    static string ToAlphabet(int number) {
        string alphabet = "";
        do {
            alphabet = Convert.ToChar(number % 26 + 0x41) + alphabet;
        } while((number=number/26-1) != -1);

        return alphabet;
    }
}

class Card {
    private int _number;
    public int number {
        get { return this._number; }
    }

    public Card(int number) {
        this._number = number;
    }

    //現実世界のカードは自分から動かないのでメソッドを持たない!
}

class Player {
    private Card _card;
    public Card card {
        get { return this._card; }
    }

    private string _name;
    public string name {
        get { return this._name; }
    }

    public Player(string name) {
        this._name = name;
    }

    //カードを一枚引いて額にかざす
    public void Draw(List<Card> cards) {
        Random random = new Random(Environment.TickCount);
        int index = random.Next(cards.Count);
        this._card = cards[index];
        cards.RemoveAt(index);
    }

    //MAX, MID, MIN, ?
    public string Answer(List<Player> players) {
        //ここがこの問題の肝となるアルゴリズムです!
        //是非チャレンジしてみてくださいね!
        return "?";
    }
}

以上です!

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away