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

#実践編

最近、[こんな問題](https://qiita-image-store.s3.amazonaws.com/0/169376/80ea2cf1-37e7-60b0-3230-c7dc1d2d60cc.jpeg)がTwitterで話題になってました。

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

理論編から読みたいかたは[コチラ](https://qiita.com/gorillab/items/b2f8e39d7cc23ad505f9)。

## (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 "?";
    }
}
```

以上です！