2012年2月20日 星期一

Polymorphism


The dictionary defines polymorphism as the ability to take on different forms. In C++ polymorphism means multiple definitions for the same function. We have already studied a form of polymorphism in function overloading. This is referred to as ad hoc polymorphism or functional polymorphism.

Polymorphism is implemented when you have (a) derived class(es) containing a member function with the same signature as a base class. A function invoked through a pointer to the base class, will execute the correct implementation regardless of whether the pointer is pointing at a base class object or a derived class object. Functions that behave in this way are called virtual functions. The determination of which function to call is not known at compile-time, so the correct function is selected during execution. This process is called late binding, or dynamic binding. The usual call of a function through an object, is known to the compiler, hence, early binding or static binding.

Non-virtual vs. Virtual Functions

Example 7-9 - Non virtual Functions

This example and the next one demonstrate the difference between a virtual and a non-virtual function.

1      // File: ex7-9.cpp – Inheritance with a non-virtual function
2     
3      #include <iostream>
4      using namespace std;
5     
6      class B
7      {
8      public:
9          B()     { cout << "B ctor called for " << this << endl;}
10          void funk1()
11               { cout << "B::funk1() called for " << this << endl; }
12          void funk2()
13               { cout << "B::funk2() called for " << this << endl; }
14      };
15     
16     
17      class D : public B
18      {
19      public:
20          D()     { cout << "D ctor called for " << this << endl; }
21          void funk1()                // Override funk1()
22               { cout << "D::funk1() called for " << this << endl; }
23      };
24      int main(void)
25      {
26          B b;
27          D d;
28          cout << endl;
29         
30          b.funk1();
31          d.funk1();
32          cout << endl;
33         
34          b.funk2();
35          d.funk2();
36          cout << endl;
37         
38          B* pB;
39          pB = &b;
40          pB->funk1();
41          cout << endl;
42         
43          pB = &d;
44          pB->funk1();
45          cout << endl;
46         
47          cout << "size of b = " << sizeof b << endl;
48          cout << "size of d = " << sizeof d << endl;
49         
50          return 0;
51      }


******  Output  ******

B ctor called for 0012FF7C                <- Output from line 26
B ctor called for 0012FF78                <- Output from line 27
D ctor called for 0012FF78                <- Output from line 27

B::funk1() called for 0012FF7C                <- Output from line 30
D::funk1() called for 0012FF78                <- Output from line 31

B::funk2() called for 0012FF7C                <- Output from line 34
B::funk2() called for 0012FF78                <- Output from line 35

B::funk1() called for 0012FF7C                <- Output from line 40

B::funk1() called for 0012FF78                <- Output from line 44

size of b = 1                    <- Output from line 47
size of d = 1                    <- Output from line 48

Why does a B and a D object have a size of 1?

Example 7-10 - Virtual Functions

This example is the same as the last one, except that funk1() is declared a virtual function. Hence, this program implements polymorphism.

1      // File: ex7-10.cpp – Inheritance with a virtual function
2     
3      #include <iostream>
4      using namespace std;
5     
6      class B
7      {
8      public:
9          B()     { cout << "B ctor called for " << this << endl;}
10          void funk1()
11               { cout << "B::funk1() called for " << this << endl; }
12          virtual void funk2()
13               { cout << "B::funk2() called for " << this << endl; }
14      };
15     
16     
17      class D : public B
18      {
19      public:
20          D()     { cout << "D ctor called for " << this << endl;}
21          void funk1()                        // Override funk1()
22               { cout << "D::funk1() called for " << this << endl; }
23          virtual void funk2()                    // Override funk2()
24           { cout << "D::funk2() called for " << this << endl; }
25         
26      };
27      int main(void)
28      {
29          B b;
30          D d;
31          cout << endl;
32         
33          b.funk1();
34          d.funk1();
35          cout << endl;
36         
37          b.funk2();
38          d.funk2();
39          cout << endl;
40         
41          B* pB;
42          pB = &b;
43          pB->funk1();
44          pB->funk2();
45          cout << endl;
46         
47          pB = &d;
48          pB->funk1();
49          pB->funk2();
50         
51          cout << endl;
52         
53          cout << "size of b = " << sizeof b << endl;
54          cout << "size of d = " << sizeof d << endl;
55         
56          return 0;
57      }


******  Output  ******

B ctor called for 0012FF7C                <- Output from line 29
B ctor called for 0012FF78                <- Output from line 30
D ctor called for 0012FF78                <- Output from line 30

B::funk1() called for 0012FF7C                <- Output from line 33
D::funk1() called for 0012FF78                <- Output from line 34

B::funk2() called for 0012FF7C                <- Output from line 37
D::funk2() called for 0012FF78                <- Output from line 38

B::funk1() called for 0012FF7C                <- Output from line 43
B::funk2() called for 0012FF7C                <- Output from line 44

B::funk1() called for 0012FF78                <- Output from line 48
D::funk2() called for 0012FF78                <- Output from line 49

size of b = 4                    <- Output from line 53
size of d = 4                    <- Output from line 54

Example 7-11 - Virtual Functions

This example illustrates that
  1. a virtual function does not have to be overridden in the derived class and
  2. also that you may not execute a derived class function that is not defined in the base class through a base class pointer even if the pointer is pointing at a derived class object.
1      // File: ex7-11.cpp
2      #include <iostream>
3      using namespace std;
4     
5      class B {
6        protected:
7          int b;
8        public:
9          B() { cout << "B ctor called for " << this << endl; b = 0; }
10          virtual void virt()
11            { cout << "B::virt() called for " << this << endl; }
12      };
13     
14      class D : public B {
15        protected:
16          int d;
17        public:
18          D() { cout << "D ctor called for " << this << endl; d = 0;}
19          void non_virt2()
20            { cout << "D::non_virt2() called for " << this << endl; }
21      };
22     
23      int main() {
24        B b;             // declare a base object
25        D d;             // declare a derived object
26     
27        b.virt();         // invoke virt() through a base object
28        d.virt();         // invoke virt() through a derived object
29     
30        B* pb;         // pb is a pointer to a base class object
31        pb = &b;         // pb points to b
32     
33        pb->virt();     // invoke virt() through a base pointer
34                         //   to a base object
35     
36        pb = &d;         // pb points to d
37        pb->virt();     // invoke virt() through a base pointer
38     
39        cout << "size of b = " << sizeof b << endl;
40        cout << "size of d = " << sizeof d << endl;
41        d.non_virt2();     // invoke non_virt2() through derived object
42      //  pb->non_virt2(); Error:  non_virt2() is not a member of B
43        return 0;
44      }


******  Output  ******

B ctor called for 0x2488fff2
B ctor called for 0x2488ffec
D ctor called for 0x2488ffec
B::virt() called for 0x2488fff2
B::virt() called for 0x2488ffec
B::virt() called for 0x2488fff2
B::virt() called for 0x2488ffec
size of b = 8
size of d = 12
D::non_virt2() called for 0x2488ffec

Example 7-12 - Virtual Functions

This example shows that
  1. "virtualness" is passed down to derived classes even if the immediate "parent" class does not name a function as virtual and 
  2. polymorphism may be implemented through references instead of pointers to base objects.
1      // File: ex7-12.cpp
2     
3      #include <iostream>
4      using namespace std;
5     
6      class person
7      {
8        protected:
9          int data;
10        public:
11          virtual char *WhoAmI() { return "person"; }
12          char *nonVirtualWhoAmI() { return "non_virtual person"; }
13      };
14     
15      class child : public person
16      {
17        public:
18          char *WhoAmI() { return "child"; }
19          char *nonVirtualWhoAmI() { return "non_virtual child"; }
20      };
21     
22      class grand_child : public child
23      {
24        public:
25          char *WhoAmI() { return "grand_child"; }
26          char *nonVirtualWhoAmI(){ return "non_virtual rand_child"; }
27      };
28     
29     
30      // non class member function with person& argument
31      void identify_yourself(person& p)
32      {
33        cout << "I am a " << (p.WhoAmI()) << endl;
34        cout << "I am a " << (p.nonVirtualWhoAmI()) << endl;
35      }
36      int main()
37      {
38        person P;
39        child C;
40        grand_child G;
41     
42        person* pp;
43        pp = &P;
44        cout << (pp->WhoAmI()) << endl;
45        cout << (pp->nonVirtualWhoAmI()) << endl;
46     
47        pp = &C;
48        cout << (pp->WhoAmI()) << endl;
49        cout << (pp->nonVirtualWhoAmI()) << endl;
50     
51        pp = &G;
52        cout << (pp->WhoAmI()) << endl;
53        cout << (pp->nonVirtualWhoAmI()) << endl;
54     
55        cout << "sizeof(int) = " << sizeof(int) << endl;
56        cout << "sizeof(person) = " << sizeof(person) << endl;
57        cout << "sizeof(child) = " << sizeof(child) << endl;
58        cout << "sizeof(grand_child) = " << sizeof(grand_child) <<endl;
59     
60        identify_yourself(P);
61        identify_yourself(C);
62        identify_yourself(G);
63     
64        return 0;
65      }


******  Output  ******

person
non_virtual person
child
non_virtual person
grand_child
non_virtual person
sizeof(int) = 4
sizeof(person) = 8
sizeof(child) = 8
sizeof(grand_child) = 8
I am a person
I am a non_virtual person
I am a child
I am a non_virtual person
I am a grand_child
I am a non_virtual person

Why write a Virtual destructor?

Example 7-13
This example illustrates why you might want to write a virtual destructor.

1      // File: ex7-13.cpp - Why a Virtual destructor?
2     
3      #include <iostream>
4      using namespace std;
5     
6      class X
7      {
8        public:
9          X(void) { cout << "X constructor called\n"; }
10          ~X(void) { cout << "X destructor called\n"; }
11      };
12     
13     
14      class A : public X
15      {
16        public:
17          A(void) { cout << "A constructor called\n"; }
18          ~A(void) { cout << "A destructor called\n"; }
19      };
20     
21     
22      int main(void)
23      {
24        X* ptrX;
25     
26        ptrX = new X;
27        delete ptrX;
28     
29        cout << endl;
30     
31        ptrX = new A;
32        delete ptrX;
33        return 0;
34      }


******  Output  ******

X constructor called
X destructor called

X constructor called
A constructor called
X destructor called

What's the problem?

Example 7-14
This example shows how to write a virtual destructor. Compare the output with the last example.

1      // File: ex7-14.cpp - Why a Virtual destructor? Here’s why!
2     
3      #include <iostream>
4      using namespace std;
5     
6      class X
7      {
8        public:
9          X(void) { cout << "X constructor called\n"; }
10          virtual ~X(void) { cout << "X destructor called\n"; }
11      };
12     
13     
14      class A : public X
15      {
16        public:
17          A(void) { cout << "A constructor called\n"; }
18          ~A(void) { cout << "A destructor called\n"; }
19      };
20     
21     
22      int main(void)
23      {
24        X* ptrX;
25     
26        ptrX = new X;
27        delete ptrX;
28     
29        cout << endl;
30     
31        ptrX = new A;
32        delete ptrX;
33        return 0;
34      }


******  Output  ******

X constructor called
X destructor called

X constructor called
A constructor called
A destructor called
X destructor called

Note:  it is not necessary to repeat the virtual for the destructor in the derived class.

Non-Virtual, Virtual, and Pure Virtual Functions

The following notes differentiate these three types of class member functions:

Non-Virtual
  • This is the default type of class member function. The keyword virtual does not appear in the function prototype.
  • Non-virtual functions, as a rule, are not usually overridden in the derived class.

Virtual
  • The keyword virtual appears at the beginning of the function prototype in the base class.  It doesn't have to be used in derived class function prototypes, but it's not a bad idea to use it.
  • Virtual functions, as a rule, are usually overridden in the derived class.
  • Virtual functions make polymorphism possible.

Pure Virtual
  • The keyword virtual appears at the beginning and  = 0  at the end of the function prototype in the base class. The  = 0  is not repeated in derived classes unless that class is intended to serve as a base class for other descendent classes. 
  • Pure virtual functions must be overridden in the derived class, unless, that class is also a base class for other classes.
  • Pure virtual functions are not defined in the class in which they are declared as pure vitual.
  • The presence of a pure virtual function in a class makes it an abstract class.  Abstract classes may not be instantiated.

Abstract Classes and Pure Virtual Functions

The following example is the traditional shape class example, illustrating the abstract base class, shape, with pure vitual functions.

Example 7-15  - Abstract classes and pure virtual functions

1      // File: ex7-15.cpp - Abstract classes
2     
3      #include <iostream>
4      #include <cmath>
5      #include <cstdlib>
6      using namespace std;
7     
8      const double pi = 3.141592654;
9     
10      class shape
11      {
12      protected:
13          double x;
14          double y;
15      public:
16          shape(double,double);
17          void print(void) const;
18          virtual double area(void) const = 0;    // pure virtual function
19          virtual double girth(void) const = 0;    // pure virtual function
20      };
21     
22     
23      shape::shape(double c_x, double c_y) : x(c_x),y(c_y) {}
24     
25      void shape::print(void) const
26      {
27          cout << '(' << x << ',' << y << ')';
28      }
29     
30     
31      class square : public shape
32      {
33      private:
34          double side;
35      public:
36          square(double c_x,double c_y, double s);
37          double get_side(void) { return side; }
38          double area(void) const;
39          double girth(void) const;
40      };
41     
42      square::square(double c_x, double c_y, double s) : shape(c_x,c_y)
43      {
44          side = s;
45      }
46     
47      double square::area(void) const
48      {
49          return side * side;
50      }
51     
52      double square::girth(void) const
53      {
54          return 4.*side;
55      }
56     
57     
58      class triangle : public shape
59      {
60      private:
61          double a,b,c;    // length of 3 sides
62      public:
63          triangle(double X,double Y, double A, double B, double C);
64          void print_sides(void);
65          double area(void) const;
66          double girth(void) const;
67      };
68     
69      triangle::triangle(double X,double Y,double A,double B,double C)
70      : shape(X,Y)
71      {
72          a = A;
73          b = B;
74          c = C;
75      }
76     
77      void triangle::print_sides(void)
78      {
79          cout << a << ' ' << b << ' ' << c;
80          return;
81      }
82     
83      double triangle::area(void) const
84      {
85          double s = (a + b + c) / 2.;            // semiperimeter
86          return sqrt(s*(s-a)*(s-b)*(s-c));
87      }
88     
89      double triangle::girth(void) const
90      {
91          return a+b+c;
92      }
93     
94     
95      class circle : public shape
96      {
97      private:
98          double radius;
99      public:
100          circle(double c_x, double c_y, double r);
101          double get_radius(void) { return radius; }
102          double area(void) const;
103          double girth(void) const;
104      };
105     
106      circle::circle(double c_x, double c_y, double r) : shape(c_x,c_y)
107      {
108          radius = r;
109      }
110     
111      double circle::area(void) const
112      {
113          return pi*radius*radius;
114      }
115     
116      double circle::girth(void) const
117      {
118          return 2.*pi*radius;
119      }
120     
121     
122      int main(void)
123      {
124          //  shape sh(6,7);    can't create instance of abstract class
125          circle c(3,4,5);
126          cout << "circle c - center: ";
127          c.print();
128          cout << "  radius = " << c.get_radius();
129          cout << "  area = " << c.area();
130          cout << "  circumference = " << c.girth() << endl;
131         
132          square s(5.,2.,1.);
133          cout << "square s - center: ";
134          s.print();
135          cout << "  side = " << s.get_side();
136          cout << "  area = " << s.area();
137          cout << "  perimeter = " << s.girth() << endl;
138         
139          triangle t(0,0,3,4,5);
140          cout << "triangle t - center: ";
141          t.print();
142          cout << "  sides = ";
143          t.print_sides();
144          cout << "  area = " << t.area();
145          cout << "  perimeter = " << t.girth() << endl;
146         
147          cout << "sizeof(double)=" << sizeof(double) << endl;
148          cout << "sizeof(shape)=" << sizeof(shape) << endl;
149          cout << "sizeof(square)=" << sizeof(square) << endl;
150          cout << "sizeof(triangle)=" << sizeof(triangle) << endl;
151          cout << "sizeof(circle)=" << sizeof(circle) << endl;
152         
153         
154          return 0;
155      }


******  Output  ******

circle c - center: (3,4)  radius = 5  area = 78.5398  circumference = 31.4159
square s - center: (5,2)  side = 1  area = 1  perimeter = 4
triangle t - center: (0,0)  sides = 3 4 5  area = 6  perimeter = 12
sizeof(double)=8
sizeof(shape)=24
sizeof(square)=32
sizeof(triangle)=48
sizeof(circle)=32

Example 7-16 - Life
The following example is a practical application which make use of polymorphism and an abstract class.

1      // File: ex7-16.cpp - Life and polymorphism
2     
3      #include <iostream>
4      #include <cstdlib>
5      using namespace std;
6     
7      enum LifeForm {VACANT, WEED, RABBIT, HAWK};
8     
9      const int GridSize = 10;
10      const int Cycles = 10;
11      const int NumberLifeForms = 4;
12      const int HawkLifeExpectancy = 8;
13      const int HawkOvercrowdingLimit = 3;
14      const int RabbitLifeExpectancy = 3;
15     
16      class Grid;
17     
18      class LivingThing {
19        protected:
20          int x,y;
21          void AssessNeighborhood(const Grid& G, int sm[]);
22        public:
23          LivingThing(int _x, int _y): x(_x), y(_y) {}
24          virtual LifeForm WhoAmI() = 0;
25          virtual LivingThing* next(const Grid& G) = 0;
26      };
27     
28      class Grid {
29        friend void LivingThing::AssessNeighborhood(const Grid& G,
30                                                    int sm[]);
31        private:
32          LivingThing* cell[GridSize][GridSize];
33        public:
34          Grid();
35          ~Grid() { if (cell[1][1]) release();}
36          void update(Grid&);
37          void release();
38          void print() const;
39      };
40     
41      /* This function counts the number of each LivingThing thing in
42       the neighborhood.  A neighborhood is a square and the 8
43       adjacent squares on each side of it */
44      void LivingThing::AssessNeighborhood(const Grid& G, int count[]){
45        int i, j;
46        count[VACANT] = count[WEED] = count[RABBIT] = count[HAWK] = 0;
47        for (i = -1; i <= 1; ++i)
48        for (j = -1; j <= 1; ++j)
49        count[G.cell[x+i][y+j] -> WhoAmI()]++;
50      }
51      class Vacant:public LivingThing
52      {
53        public:
54          Vacant(int _x, int _y):LivingThing(_x,_y) {}
55          LifeForm WhoAmI() {return (VACANT);}
56          LivingThing* next(const Grid& G);
57      };
58     
59      class Weed : public LivingThing
60      {
61        public:
62          Weed(int _x, int _y): LivingThing(_x,_y){}
63          LifeForm WhoAmI() {return (WEED);}
64          LivingThing* next(const Grid& G);
65      };
66     
67      class Rabbit : public LivingThing
68      {
69        protected:
70          int age;
71        public:
72          Rabbit(int x, int y, int a = 0) : LivingThing(x,y), age(a) {}
73          LifeForm WhoAmI() { return (RABBIT); }
74          LivingThing* next(const Grid& G);
75      };
76     
77      class Hawk : public LivingThing
78      {
79        protected:
80          int age;
81        public:
82          Hawk(int x, int y, int a = 0): LivingThing(x,y), age(a){}
83          LifeForm WhoAmI() {return (HAWK);}
84          LivingThing* next(const Grid& G);
85      };
86      // This function determines what will be in an Vacant square in
87      // the next cycle
88      LivingThing* Vacant::next(const Grid& G)
89      {
90        int count[NumberLifeForms];
91        AssessNeighborhood(G,count);
92     
93      // If there is more than one Rabbit in the neighborhood, a new
94      // Rabbit is born.
95        if (count[RABBIT] > 1)   return (new Rabbit(x,y));
96     
97      // otherwise, if there is more than one Hawk, a Hawk will be born
98        else if (count[HAWK] > 1) return (new Hawk(x, y));
99     
100      // else, if there is a Weed in the neighborhood, a Weed will grow
101        else if (count[WEED])   return (new Weed(x, y));
102     
103      // otherwise the square will remain Vacant
104        else return (new Vacant(x, y));
105      }
106     
107     
108      // If there is more Weeds than Rabbits, then new Weed will grow,
109      // otherwise Vacant
110      LivingThing* Weed::next(const Grid& G)
111      {
112        int count[NumberLifeForms];
113        AssessNeighborhood(G, count);
114        if (count[WEED] > count[RABBIT]) return (new Weed(x, y));
115        else return (new Vacant(x, y));
116      }
117     
118     
119      /* The Rabbit dies if:
120       there's more Hawks in the neighborhood than Rabbits
121       not enough to eat
122       or if it's too old
123       otherwise the Rabbit ages */
124      LivingThing* Rabbit::next(const Grid& G)
125      {
126        int count[NumberLifeForms];
127        AssessNeighborhood(G, count);
128        if (count[HAWK] >= count[RABBIT] ) return (new Vacant(x, y));
129        else if (count[RABBIT] >count[WEED]) return (new Vacant(x, y));
130        else if (age > RabbitLifeExpectancy) return (new Vacant(x, y));
131        else return (new Rabbit(x,y, age + 1));
132      }
133       // Hawk die of overcrowding, starvation, or old age
134      LivingThing* Hawk::next(const Grid& G)
135      {
136        int count[NumberLifeForms];
137        AssessNeighborhood(G, count);
138        if (count[HAWK]>HawkOvercrowdingLimit)
139          return (new Vacant(x,y));
140        else if (count[RABBIT] < 1) return (new Vacant(x,y));
141        else if (age > HawkLifeExpectancy) return (new Vacant (x, y));
142        else return (new Hawk(x, y, age + 1));
143      }
144     
145      Grid::Grid()
146      {
147        LifeForm creature;
148        int i, j;
149        for (i = 0; i < GridSize; i++)
150          for (j = 0; j < GridSize; j++)
151          {
152          if (i==0 || i==GridSize-1 || j==0 || j==GridSize-1)
153            creature = VACANT;
154          else
155            creature = LifeForm(rand() % NumberLifeForms);
156          switch (creature)
157          {
158            case HAWK:cell[i][j] = new Hawk(i,j);  break;
159            case RABBIT:  cell[i][j] = new Rabbit(i,j);   break;
160            case WEED:cell[i][j] = new Weed(i,j);break;
161            case VACANT:  cell[i][j] = new Vacant(i,j);
162          }
163        }
164      }
165     
166      void Grid::release()
167      {
168        int i, j;
169        for (i = 1; i < GridSize - 1; ++i)
170          for (j = 1; j < GridSize - 1; ++j) delete cell[i][j];
171        cell[1][1] = 0;
172      }
173     
174      void Grid::update(Grid& old)
175      {
176        int i, j;
177        for (i = 1; i < GridSize - 1; ++i)
178        for (j = 1; j < GridSize - 1; ++j)
179        cell[i][j] = old.cell[i][j] -> next(old);
180      }
181      void Grid::print() const
182      {
183        LifeForm creature;
184        int i, j;
185        for (i = 1; i < GridSize - 1; i++)
186        {
187          for (j = 1; j < GridSize - 1; j++)
188          {
189            creature = cell[i][j]->WhoAmI();
190            switch (creature)
191            {
192              case HAWK:  cout << "H"; break;
193              case RABBIT:   cout << "R"; break;
194              case WEED:cout << "W"; break;
195              case VACANT:cout << "0";
196            }
197          }
198          cout << endl;
199        }
200        cout << endl;
201        return;
202      }
203     
204     
205      int main(void)
206      {
207        Grid G1, G2;
208        G1.print();
209     
210        for (int i = 1; i <= Cycles; i++)
211        {
212          cout << "Cycle " << i << endl;
213          if (i % 2)
214          {
215            G2.update(G1);
216            G2.print();
217            G1.release();
218          }
219          else
220          {
221            G1.update(G2);
222            G1.print();
223            G2.release();
224          }
225        }
226        return 0;
227      }


******  Output  ******


RRRR0WHH
0R0RHH00
0WHHHWRW
RW0HH0WH
HWRRHHW0
W0R00HR0
HHH0H00R
HRRWWHRW

Cycle 1
0000RW00
R0R000HH
R0H00W0W
0WR00HWH
H00000WW
WR0RH00R
H0HR0RR0
H00WWH00

Cycle 2
0R0RR0HH
0R0RWW00
0RHRWWHW
W000W0W0
HRRRHHWW
00R0HRRR
HHH0R00R
0HWW0HR0

Cycle 3
R0R00W00
R0R00WHH
R0HRWW0W
0RRRWHWW
H000HH0W
HR0RH000
00HR0RR0
H0WWWH0R

Cycle 4
0R0RWWHH
0R0RWW00
0RH0WWHW
R000W0WW
HRRR00HW
H0R0HRRW
HHH0R00R
0HWW0HR0

Cycle 5
R0RRWW00
R0RRWWHH
R0HWWW0W
0RRRWHWW
H000RRHW
0R0RH000
00HR0RR0
H0WWWH0R

Cycle 6
0R00WWHH
0R0RWW00
0RH0WWHW
R00RWHWW
HRRR00HW
00R0HRRW
0HH0R00R
0HWW0HR0

Cycle 7
R0RWWW00
R0R0WWHH
R0HRWW0W
0RR0W0WW
H000RRHW
HR0RH000
HHHR0RR0
H0WWWH0R

Cycle 8
0R0WWWHH
0R0RWW00
0RHRWWHW
R00R0RWW
HRRR00HW
00R0HRRW
00H0R00R
0HWW0HR0

Cycle 9
R0RWWW00
R0RRWWHH
R0H00WHW
0RR0R0WW
H000RRHW
0R0RH000
0HHR0RR0
00WWWH0R

沒有留言:

張貼留言