//: C09:PaperScissorsRock.cpp // From Thinking in C++, 2nd Edition // Available at http://www.BruceEckel.com // (c) Bruce Eckel 2000 // Copyright notice in Copyright.txt // Demonstration of multiple dispatching #include "../purge.h" #include #include #include #include #include using namespace std; class Paper; class Scissors; class Rock; enum Outcome { win, lose, draw }; ostream& operator<<(ostream& os, const Outcome out) { switch(out) { default: case win: return os << "win"; case lose: return os << "lose"; case draw: return os << "draw"; } } class Item { public: virtual Outcome compete(const Item*) = 0; virtual Outcome eval(const Paper*) const = 0; virtual Outcome eval(const Scissors*) const= 0; virtual Outcome eval(const Rock*) const = 0; virtual ostream& print(ostream& os) const = 0; virtual ~Item() {} friend ostream& operator<<(ostream& os, const Item* it) { return it->print(os); } }; class Paper : public Item { public: Outcome compete(const Item* it) { return it->eval(this); } Outcome eval(const Paper*) const { return draw; } Outcome eval(const Scissors*) const { return win; } Outcome eval(const Rock*) const { return lose; } ostream& print(ostream& os) const { return os << "Paper "; } }; class Scissors : public Item { public: Outcome compete(const Item* it) { return it->eval(this); } Outcome eval(const Paper*) const { return lose; } Outcome eval(const Scissors*) const { return draw; } Outcome eval(const Rock*) const { return win; } ostream& print(ostream& os) const { return os << "Scissors"; } }; class Rock : public Item { public: Outcome compete(const Item* it) { return it->eval(this); } Outcome eval(const Paper*) const { return win; } Outcome eval(const Scissors*) const { return lose; } Outcome eval(const Rock*) const { return draw; } ostream& print(ostream& os) const { return os << "Rock "; } }; struct ItemGen { ItemGen() { srand(time(0)); } Item* operator()() { switch(rand() % 3) { default: case 0: return new Scissors; case 1: return new Paper; case 2: return new Rock; } } }; struct Compete { Outcome operator()(Item* a, Item* b) { cout << a << "\t" << b << "\t"; return a->compete(b); } }; int main() { const int sz = 20; vector v(sz*2); generate(v.begin(), v.end(), ItemGen()); transform(v.begin(), v.begin() + sz, v.begin() + sz, ostream_iterator(cout, "\n"), Compete()); purge(v); } ///:~