C#
オブジェクト指向

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

実践編

最近、こんな問題が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 "?";
    }
}

以上です!