مصفوفة الكائنات في ++C
مصفوفة الكائنات
رأينا في المثال السابق المصفوفة عنصرا لهيكل , ويمكننا عكس الأية , بأن نخلق مصفوفة من الكائنات , والمثالان التاليان تطبيق لذلك , الأول خاص بالمسافات , والثاني بأوراق اللعب .
مثال المسافات الإنجليزية
صنعنا في مقالات سابقة كائنا يعبر عن المسافات الإنجليزية , وسوف نقدم في المثال التالي مصفوفة مكونة من هذا الكائن .
englaray.cpp
// englaray.cpp
// objects using English measurements
// UCS Laboratories
#include <iostream.h>
#include <conio.h>
const int MAX = 100; // maximum number of elements
class Distance // English Distance class
{
private:
int feet;
float inches;
public:
void getdist() // get length from user
{
cout << "\n Enter feet: "; cin >> feet;
cout << " Enter inches: "; cin >> inches;
}
void showdist() // display distance
{ cout << feet << "\'-" << inches << '\"'; }
};
void main()
{
Distance dist[MAX]; // array of distances
int n=0; // count the entries
char ans; // user response ('y' or 'n')
cout << endl;
do // get distances from user
{
cout << "Enter distance number " << n+1;
dist[n++].getdist(); // store distance in array
cout << "Enter another (y/n)?: ";
cin >> ans;
} // quit if user types 'n'
while( ans != 'n' );
for(int j=0; j<n; j++) // display all distances
{
cout << "\nDistance number " << j+1 << " is ";
dist[j].showdist();
}
getche();
}
وفي هذا المثال يدخل المستخدم ما يشاء من مسافات في حدود حجم المصفوفة , وبعد كل إدخال يسأله البرنامج إن كان يرغب في إضافة المزيد . وعندما يكتفي المستخدم , يظهر البرنامج البيانات المدخلة .
الوصول لكائن في مصفوفة
عرفت المصفوفة dist[MAX] علي أن عناصرها من نوع الهيكل distance , وهي مصورة في الشكل .
ويكون الوصول لكائن في المصفوفة مماثلا للوصول لعنصر من عناصر الهيكل في برنامج partaray.cpp . وإليك كيفية استثارة الدالة showdist() المنتمية للعنصر j من المصفوفة :
Dist[j].showdist();
وقد استخدمنا لذلك مؤثر النقطة المعتاد .
كما أننا استخدمنا مؤثر التزايد لكي يتم الانتقال إلي الموضوع التالي من المصفوفة عند كل إدخال جديد , وذلك في الأمر :
Dist[n++].getdist();
حيث إننا نستخدم الدوارة do , وهي لا تتزايد تلقائيا كما تفعل الدوارة for .
شكل مصفوفة كائنات
تجاوز حجم المصفوفة
ماذا لو أدخلت عناصر أكثر من الحجم المحدد للمصفوفة ؟ للأسف , ليس هناك من وسيلة لمنع ذلك , ويترتب علي ذلك أن البيانات المخلة قد تكتب فوق بيانات أخري لبرنامج أخر , ويزداد الأمر سوءا لو كان البرنامج الأخر هو نظام التشغيل نفسه , فيعلم الله لتلاقي هذا الاحتمال , فيمكن مثلا إصدار رسالة تحذير عند امتلاء المصفوفة , تكون أوامرها في بداية الدوارة do , ومضاعفة علي النحو التالي :
If(n>MAX)
{
Cout << ''\nThe array is full!'';
Break;
}
ويكون الأمر break هو صمام الأمن ضد تجاوز حجم المصفوفة , حيث يأخذ البرنامج خارج الدوارة .
مثال ورق اللعب
سوف نستعير الفئة card من الفصل السابع ونصنع مصفوفة من 52 من كائناتها , وبذلك يكون لدينا مجموعة كاملة من ورق اللعب . وحيث إن هذا البرنامج سيستخدم المحارف الرسومية التي في الدوس لصور المجموعة , وذلك لتوفير المساحة المستغلة من الذاكرة , فإن هذا البرنامج يجب أن يشغل تحت الدوس مباشرة , وليس EasyWin .
cardaray.cpp
// cardaray.cpp
// cards as objects
// for IBM character set, build DOS target, not EasyWin
// UCS Laboratories
#include <iostream.h>
#include <stdlib.h> // for randomize(), rand
#include <time.h> // for randomize()
#include <conio.h> // for getche()
enum Suit { clubs, diamonds, hearts, spades };
const int jack = 11; // from 2 to 10 are
const int queen = 12; // integers without names
const int king = 13;
const int ace = 14;
class card
{
private:
int number; // 2 to 10, jack, queen, king, ace
Suit suit; // clubs, diamonds, hearts, spades
public:
card() // constructor
{ }
void init(int n, Suit s) // initialize card
{ suit = s; number = n; }
void display(); // display card
};
void card::display() // display the card
{
if( number >= 2 && number <= 10 )
cout << number;
else
switch(number)
{
case jack: cout << "J"; break;
case queen: cout << "Q"; break;
case king: cout << "K"; break;
case ace: cout << "A"; break;
}
switch(suit)
{
case clubs: cout << char(5); break;
case diamonds: cout << char(4); break;
case hearts: cout << char(3); break;
case spades: cout << char(6); break;
}
}
void main()
{
card deck[52];
cout << endl;
for(int j=0; j<52; j++)
{
int num = (j % 13) + 2; // cycles through 2 to 14, 4 times
Suit su = Suit(j / 13); // cycles through 0 to 3, 13 times
deck[j].init(num, su); // set card
}
cout << "\nOrdered deck:\n";
for(j=0; j<52; j++) // display ordered deck
{
deck[j].display();
cout << " ";
if( !( (j+1) % 13) ) // newline every 13 cards
cout << endl;
}
randomize(); // seed random number generator
for(j=0; j<52; j++) // for each card in the deck,
{
int k = random(52); // pick another card at random
card temp = deck[j]; // and swap them
deck[j] = deck[k];
deck[k] = temp;
}
cout << "\nShuffled deck:\n";
for(j=0; j<52; j++) // display shuffled deck
{
deck[j].display();
cout << ", ";
if( !( (j+1) % 13) ) // newline every 13 cards
cout << endl;
}
getch(); // wait for keypress
} // end main
بمجرد أن أنشأنا مجموعة الورق , لن نقاوم الرغبة في خلطها , ثم إظهرها بعد ذلك .
ويبين الشكل المجموعة قبل وبعد الخلط .
شكل مجموعة ورق اللعب
وقد استخدمت المحارف الرسومية في جدول الاسكي لصور المجموعة , فالأمر :
Chart(5)
مثلا يظهر المحرف المقابل في الجدول لعدد 5 , بدلا من إظهار العدد نفسه , حيث تحويل نوع العدد قسريا إلي النوع char .
إنتاج مجموعة أعداد عشوائية
أما عملية خلط الأوراق فتجري علي خطوتين , استدعاء الدالة المكتبية randomize() , وهي دالة تعتبر مولدا للأرقام العشوائية random-number generator . ويلزم لذلك تضمين الملف stdlib.h في البرنامج , وهو المحتوي علي الدوال المكتبية . وهذه الدالة تستخدم توقيت النظام , ومن ثم يلزم تضمين الملف time.h أيضا.
أما إنتاج المجموعة العشوائية فيكون عن طريق دالة تقوم بذلك , وهي دالة مكتبية تسمي random() فتكون الخطوة الثانية هي استدعاء هذه الدالة , وهي تأخذ معاملا واحدا , هو أكبر عدد لمجموعة الأرقام المطلوب خلطها , زائدا 1 , ففي حالتنا , نريد خلط أعداد بين 0 و 50 , فيكون المعامل 52 , والذي ظهر في البرنامج كالتالي :
Random(52);
وينتج عن هذه الدالة مجموعة أعداد عشوائية من 0 إلي 51 , يمثلها المتغير k , والذي يستخدم لتبديل أوضاع العناصر في المصفوفة .
ويمكن للقارئ استخدام هذا البرنامج في ألعاب أكثر تطورا .
تعليقات
إرسال تعليق