برنامج تمثيلي لمصعد في ++C
برنامج تمثيلي لمصعد
ملحوظة : لا يستخدم لهذا البرنامج البرنامج EasyWin .
هل تساءلت مرة كيف يمكن للمصاعد في الأبنية الحديثة أن تعرف وجهتها ؟ كان ذلك ينفذ عن طريق عامل المصعد ولكن مباني اليوم قد زودت بإمكانيات للذكاء تغنينا عن الوسائل الأدمية .
تري ما هي عناصر نظام كهذا ؟ في مبني نمطي حديث يوجد عدة مصاعد , ومجموعة من الضواغط تشير لأعلي ولأسفل . من الممكن أن يكون لكل طابق ضاغطان فقط , فلا تعلم أي مصعد سوف يخدمك , وبداخل المصعد مجموعة من الضواغط بقدر عدد الطوابق , ويقوم المستخدمون بالضرب علي الضاغط المطلوب لهم , سوف يقوم برنامجنا التمثيلي بتشخيص كل هذه الأوضاع .
تشغيل البرنامج :
عندما يبدأ تشغيل البرنامج , تري علي الشاشة قائمة بعشرين طابقا وأربعة مصاعد في الطابق الأرضي المرقم 1 (أنظر الشكل )
شكل الشاشة الإفتتاحية لبرنامج elev.cpp .
طلب طابق معين
عند ضربك علي أي مفتاح تري الرسالة التالية التي تطلب منك إدخال الطابق الذي أنت به :
Enter the floor you're on :
ثم رسالة بالإتجاه الذي تريده (صعود أم هبوط) :
Enter direction you want to go (u or d):
وعند الاستجابة لهاتين الرسالتين , تري مثلتا بجوار الطابق الذي اخترته , يشير إما لأعلي أو لأسفل . وكلما حدث طلب جديد , ظهرت مثلثات بهذه الطريقة بجوار الطوابق المطلوبة .
إذا كان هناك مصعد موجود بالفعل أمام الطابق المختار , يفتح الباب علي التو , في ذلك تري وجها سعيدا خارج المصعد , ثم يدخل من خلال الباب المفتوح . وإذا لم يكن هناك مصعد عند ذلك الطابق , تحرك إليه أحد المصاعد إما صعودا أو هبوطا .
تحديد الوجهة
بمجرد وصول المصعد للطابق المحدد , ودخول الراكب الوجه السعيد فيه , تظهر الرسائل الحوارية التي تحدد موقع توقف المصعد , وتستحث المستخدم
ان يدخل الطابق الذي يريده , مثلا :
Car 1 has stopped at floor 1
Enter destination floors (0 when finished)
Destination 1 : 13
و بإمكانك هنا أن تدخل أي عدد من الطريق , علي أساس أنه يوجد أكثر من راكب , علي ألا تريد عن 20 ) . بعد الإنتهاء , تضرب علي الرقم 0 . تميز الطوابق المطلوبة بمستطيل إلي يسار المصعد . ويخزن النظام كافة الطوابق المطلوبة , ويحاول خدمتها جميعا (أنظر الشكل) .
شكل المصاعد تتحرك
تصميم النظام
المصاعد جميعها متماثلة , فمن المنطقي أن نجعل لها فئة تضم البيانات المطلوبة لأي مصعد : الوضع الحالي , الطوابق المطلوبة له , الاتجاه , وهكذا .
كما أن لدينا بيانات للمبني ككل , وكما رأينا في البرنامج horse.cpp فإن هذه البيانات مشتركة لكافة الكائنات , ومن ثم يجب أن تعرف كبيانات استاتيكية . وفي مثالنا هذا لدينا ثلاثة من هذه البيانات : مصفوفة بالطوابق المطلوب من المصاعد التوقف عندها . هذه المصفوفة علي الصورة ثنائية , وتضم في بعد بيانا بوليا لحالتي الصعود والهبوط .
كما يجب أن يعرف أي مصعد بأماكن تواجد المصاعد الأخري , فلو أن مصعدا في الطابق الأول , فليس له أن يصعد لتلبيه نداء من الطابق الثالث عشر إذا كان هناك مصعد أخر في الطابق العاشر . ولتحقيق ذلك وضعت مصفوفة مؤشرات لأماكن المصاعد , يخزن فيها كل مصعد عنوانه بمجرد إنشائه .
أما البيان الاستاتيكي الثالث فهو رقم المصعد الذي ينشأ , وبهذه الطريقة يتاح لكل مصعد أن يرقم نفسه بمجرد إنشائه .
التحكم في الزمن
كما فعلنا في البرنامج horse.cpp , فإن الدالة الأصلية main() تستدعي دالة تسمي master_tick عند فترات منتظمة , تتحكم في كافة عناصر تشغيل البرنامج . تستدعي تلك الدالة دالة أخري car_tick1() تقوم بالإضافة لأشياء أخري , بإظهار المصعد علي الشاشة ثم تستدعي دالة أخري لتقرير ما يحدث بعد ذلك . والخيارات هنا هي : الصعود , الهبوط , التوقف , دخول مستخدم , خروج مستخدم .
وقبل تحريك مصعد لمكان ما يجب عليه أن يأخذ تصورا لأماكن بقية المصاعد ولتحقيق ذلك تدخل كافة المصاعد في عملية تقرير قبل أن يتحرك أي منها . نستخدم لهذا الغرض دالتين زمنيتين لكل مصعد . فبعد استدعاء car_tick1() لتقرر إلي أين يجب أن يتجه المصعد , تستدعي دالة أخري car_tick1() لتقرر إلي أن يجب أن يتجه المصعد , تستدعي دالة أخري car_tick2() تقوم بتحريك المصعد , وهي تجعل المصاعد تتحرك بواسطة تغيير المتغير current_floor .
وتتبع عملية إدخال المستخدمين تتابعا ثابتا , يكون المصعد خلاله متوقفا عند الطابق المطلوب , فيرسم البرنامج :
1- مصعدا ذا باب مغلق , دون وجه باسم .
2- مصعدا ذا باب مفتوح , ووجه باسم لليسار .
3- مصعدا ذا باب مفتوح ووجه باسم , ثم يؤخذ طلب المستخدم .
4- مصعدا ذا باب مغلق , دون وجه باسم .
ويطبق توال مشابه في حالة خروج المستخدم . هذه التتابعات تستخدم لها مؤقتا timer (متغير من نوع عدد صحيح ) يتناقص من 3 إلي 0 . و تستخدم دوارة case للتحكم في خطوات الرسم المشار إليها .
تنظيم البرنامج :
قسمنا البرنامج إلي أربعة ملفات , اثنان منهما يمكن أن يضعهما منتج هذا النوع من البرامج التطبيقية , وهما elev.h, elev.cpp . هذان البرنامجان يمكن لشركة مصاعد أن تشتريهما , لتطبيقهما علي أي مبني تتعاقد عليه (هذا البرنامج غير معتمد من هيئة المصاعد القومية , فلا تحاول أن تجربه حقيقة) . يقوم مبرمجو الشركة بكتابة ملفين أخرين : الملف elev_app.h
elev_app.h
elev_app.h
// elev_app.h// provides constants to specify building characteristicsconst int NUM_FLOORS = 20; // number of floors
const int NUM_CARS = 4; // number of elevator cars
ويوجد به توصيف المبني , والمفروض أن يكون ملفا منفصلا لأن هذه المواصفات يجب أن تكون معلومة للدوال المنتمية لفئة المصعد , وأفضل طريقة لذلك هو أن يضمن هذا الملف في الملف elev.h , والملف elev_app.cpp الذي يستهل المصاعد في يستدعي دوال المصعد علي فترات محددة ليمثل مرور الوقت .
توصيف الفئة
يضم الملف elev.h توصيفا للفئة elevator , وتلعب بعض عناصرها مثل num_cars, car_numbers نفس دور المتغيرات في برنامج الأحصنة الذي قدمناه في الفصل 13 . وتفيد مصفوفة المؤشرات إلي المصاعد car_list[] في أن يوالي كل مصعد الاستعلام عن أوضاع واتجاهات المصاعد الأخري .
Elev.h
elev.h
// elev.h// header file for elevators -- contains class declarations// UCS Laboratories#include "elev_app.h" // provided by client
#include <iostream.h>
#include <iomanip.h> // for setw()#include <dos.h> // for delay()#include <conio.h> // for screen output#include <stdlib.h> // for itoa()#include <process.h> // for exit()enum direction { UP, DN, STOP };enum boolean { FALSE, TRUE };const int LOAD_TIME = 3; // loading/unloading time (ticks)
const int SPACING = 7; // visual spacing between cars
const int BUF_LENGTH = 80; // length of utility string buffer
////////////////////////////////////////////////////////////////class elevator { private: // data shared by all elevator carsstatic elevator* car_list[NUM_CARS]; // ptrs to cars
static int num_cars; // cars created so far
// array of up/down buttons static boolean floor_request[2][NUM_FLOORS]; // data specific to each carint car_number; // our number (0 to n-1)
int current_floor; // where are we? (0 to n-1)
int old_floor; // where were we? (0 to n-1)
direction current_dir; // which way are we going? boolean destination[NUM_FLOORS]; // selected by occupantsint loading_timer; // non-zero if loading
int unloading_timer; // non-zero if unloading
// functions for specific carsvoid car_tick1(); // time tick 1 for each car
void car_tick2(); // time tick 2 for each car
void car_display(); // display elevator
void dests_display(); // display elevator requests
void decide(); // decide what to do
void move(); // move the car
void get_destinations(); // get destinations
// functions for data shared by all carsstatic void show_floor_reqs(); // show floor requests
public: // functions for data of specific cars elevator(); // constructor // functions for data shared by all carsstatic void init(); // initialize static data
static void master_tick(); // send ticks to all cars
static void get_floor_reqs(); // get floor requests
};
elev_app.h
// elev_app.h// provides constants to specify building characteristicsconst int NUM_FLOORS = 20; // number of floors
const int NUM_CARS = 4; // number of elevator cars
الدوال المنتمية
يضم الملف elev.cpp الدوال المنتمية للفئة , والبيانات الاستاتيكية . وتقوم الدوال الاستاتيكية باستهلاك النظام , وتقدم التوقيت الأساسي , وتظهر طلبات الطوابق , وتتقبل طلبات الطوابق من المستخدمين . و تقوم الدوال المعتادة (غير الاستاتيكية) باستهلاك المصاعد (عن طريق البادئة) , وتقدم توقيتين لكل مصعد , وتظهره , وتظهر وجهته , وتقرر ما يحدث , وتحرك المصعد للمكان الجديد , ثم تحصل علي طلب المستخدم .
Elev.cpp
Elev.cpp
// elev.cpp// contains class data and member function definitions// UCS Laboratories#include "elev.h" // include class declarations
/////////////////////////////////////////////////////////////////// static data definitions/////////////////////////////////////////////////////////////////elevator* elevator::car_list[NUM_CARS]; // list of ptrs to carsint elevator::num_cars = 0; // elevs created to date
// array of up/down buttonsboolean elevator::floor_request[2][NUM_FLOORS]; // [0]=UP, [1]=DN/////////////////////////////////////////////////////////////////// static function definitions/////////////////////////////////////////////////////////////////void elevator::init() // initialize static data
{char ustring[BUF_LENGTH]; // string for floor numbers
// clrscr(); // clear screenfor(int j=0; j<NUM_FLOORS; j++) // for each floor
{// gotoxy(3, NUM_FLOORS-j); // put floor number itoa(j+1, ustring, 10); // on screencout << setw(3) << ustring;
floor_request[UP][j] = FALSE; // no floor requests yetfloor_request[DN][j] = FALSE;
}
}
void elevator::master_tick(void) // master time tick
{ show_floor_reqs(); // display floor requestsfor(int j=0; j<NUM_CARS; j++) // for each elevator
car_list[j]->car_tick1(); // send it time tick 1for(j=0; j<NUM_CARS; j++) // for each elevator
car_list[j]->car_tick2(); // send it time tick 2}
void elevator::show_floor_reqs() // display floor requests
{for(int j=0; j<NUM_FLOORS; j++)
{// gotoxy(SPACING, NUM_FLOORS-j); if(floor_request[UP][j]==TRUE)cout << '\x1E'; // up arrow
else cout << ' '; // gotoxy(SPACING+3, NUM_FLOORS-j); if(floor_request[DN][j]==TRUE)cout << '\x1F'; // down arrow
else cout << ' ';}
}
// get_floor_reqs() -- get floor requests from user outside carvoid elevator::get_floor_reqs() {char ch; // utility char for input
char ustring[BUF_LENGTH]; // utility string for input **************
int iFloor; // floor from which request made
char chDirection; // 'u' or 'd' for up or down
if( !kbhit() ) // wait for keypress
return;ch = getch();
if(ch=='\x1B') // if escape key, end program
exit(0);
// gotoxy(1,22); // bottom of screen cout << "Enter the floor you're on: "; cin.get(ustring, BUF_LENGTH); // get floorcin.ignore(10, '\n'); // eat chars, including newline
iFloor = atoi(ustring); // convert to integer cout << "Enter direction you want to go (u or d): "; cin.get(chDirection); // (avoid multiple linefeeds)cin.ignore(10, '\n'); // eat chars, including newline
if(chDirection=='u' || chDirection=='U')
floor_request[UP][iFloor-1] = TRUE; // up floor requestif(chDirection=='d' || chDirection=='D')
floor_request[DN][iFloor-1] = TRUE; // down floor request // gotoxy(1,22); clreol(); // clear old text //gotoxy(1,23); clreol(); //gotoxy(1,24); clreol();}
/////////////////////////////////////////////////////////////////// non-static function definitions/////////////////////////////////////////////////////////////////elevator::elevator() // constructor {car_list[num_cars] = this; // put our address on list
car_number = num_cars++; // set our number current_floor = 0; // start at 0 (user's 1) old_floor = 0; // remember previous floor current_dir = STOP; // stationary at startfor(int j=0; j<NUM_FLOORS; j++) // occupants have not pushed
destination[j] = FALSE; // any buttons yet loading_timer = 0; // not loading yet unloading_timer = 0; // not unloading yet}
void elevator::car_tick1() // tick 1 for each car
{ car_display(); // display elevator box dests_display(); // display destinationsif(loading_timer) // count down load time
--loading_timer;
if(unloading_timer) // count down unload time
--unloading_timer;
decide(); // decide what to do}
// all cars must decide before any of them movevoid elevator::car_tick2() // tick 2 for each car
{ move(); // move car if appropriate}
void elevator::car_display() // display elevator image
{// gotoxy(SPACING+(car_number+1)*SPACING, NUM_FLOORS-old_floor);cout << " "; // erase old position
//gotoxy(SPACING-1+(car_number+1)*SPACING,// NUM_FLOORS-current_floor); switch(loading_timer) { case 3:cout << "\x01\xDB \xDB "; // draw car with open door
break; // happy face on left
case 2:cout << " \xDB\x01\xDB "; // happy face in open door
get_destinations(); // get destinations break; case 1:cout << " \xDB\xDB\xDB "; // draw with closed door
break; // no happy face
case 0:cout << " \xDB\xDB\xDB "; // draw with closed door, no
break; // happy face (default)
}
// gotoxy(SPACING+(car_number+1)*SPACING, // NUM_FLOORS-current_floor); switch(unloading_timer) { case 3:cout << "\xDB\x01\xDB "; // draw car with open door
break; // happy face in car
case 2:cout << "\xDB \xDB\x01"; // draw car with open door
break; // happy face on right
case 1:cout << "\xDB\xDB\xDB "; // draw with closed door
break; // no happy face
case 0:cout << "\xDB\xDB\xDB "; // draw with closed door, no
break; // happy face (default)
}
old_floor = current_floor; // remember old floor}
void elevator::dests_display() // display destinations
{ // selected by buttonsfor(int j=0; j<NUM_FLOORS; j++) // inside the car
{// gotoxy(SPACING-2+(car_number+1)*SPACING, NUM_FLOORS-j); if( destination[j] == TRUE )cout << '\xFE'; // small box
elsecout << ' '; // blank
}
}
void elevator::decide() // decide what to do
{ // flags indicate if destinations or requests above/below us boolean destins_above, destins_below; // destinations boolean requests_above, requests_below; // requests // floor number of closest request above us and below us int nearest_higher_req = 0; int nearest_lower_req = 0; // flags indicate if there is another car, going in the same // direction, between us and the nearest floor request (FR)boolean car_between_up, car_between_dn;
// flags indicate if there is another car, going in the // opposite direction, on the opposite side of the nearest FRboolean car_opposite_up, car_opposite_dn;
// floor and direction of other car (not us)int ofloor; // floor
direction odir; // direction // ensure we don't go too high or too low if( (current_floor==NUM_FLOORS-1 && current_dir==UP)|| (current_floor==0 && current_dir==DN) )
current_dir = STOP;
// if there's a destination on this floor, unload passengers if( destination[current_floor]==TRUE ) { destination[current_floor] = FALSE; // erase destinationif( !unloading_timer) // unload
unloading_timer = LOAD_TIME;
return;}
// if there's an UP floor request on this floor, // and if we're going up or stopped, load passengers if( (floor_request[UP][current_floor] && current_dir != DN) ) { current_dir = UP; // (in case it was STOP) // remove floor request for direction we're goingfloor_request[current_dir][current_floor] = FALSE;
if( !loading_timer) // load
loading_timer = LOAD_TIME;
return;}
// if there's a down floor request on this floor, // and if we're going down or stopped, load passengers if( (floor_request[DN][current_floor] && current_dir != UP) ) { current_dir = DN; // (in case it was STOP) // remove floor request for direction we're goingfloor_request[current_dir][current_floor] = FALSE;
if( !loading_timer) // load passengers
loading_timer = LOAD_TIME;
return;}
// check if there are other destinations or requests // record distance to nearest requestdestins_above = destins_below = FALSE;
requests_above = requests_below = FALSE;
for(int j=current_floor+1; j<NUM_FLOORS; j++)
{ // check floors aboveif( destination[j] ) // if destinations
destins_above = TRUE; // set flag if( floor_request[UP][j] || floor_request[DN][j] ) { // if requests requests_above = TRUE; // set flagif( !nearest_higher_req ) // if not set before
nearest_higher_req = j; // set nearest req}
}
for(j=current_floor-1; j>=0; j--) // check floors below
{if(destination[j] ) // if destinations
destins_below = TRUE; // set flag if( floor_request[UP][j] || floor_request[DN][j] ) { // if requests requests_below = TRUE; // set flagif( !nearest_lower_req ) // if not set before
nearest_lower_req = j; // set nearest req}
}
// if no requests or destinations above or below, stop if( !destins_above && !requests_above &&!destins_below && !requests_below)
{current_dir = STOP;
return;}
// if destinations and we're stopped, or already going the // right way, go toward destinations if( destins_above && (current_dir==STOP || current_dir==UP) ) {current_dir = UP;
return;}
if( destins_below && (current_dir==STOP || current_dir==DN) ) {current_dir = DN;
return;}
// find out if there are other cars, (a) going in the same // direction, between us and the nearest floor request; // or (b) going in the opposite direction, on the other // side of the floor requestcar_between_up = car_between_dn = FALSE;
car_opposite_up = car_opposite_dn = FALSE;
for(j=0; j<NUM_CARS; j++) // check each car
{if(j != car_number) // if it's not us
{ // get its floor ofloor = car_list[j]->current_floor; // and odir = car_list[j]->current_dir; // direction // if it's going up and there are requests above us if( (odir==UP || odir==STOP) && requests_above ) // if it's above us and below the nearest request if( (ofloor > current_floor&& ofloor <= nearest_higher_req)
// or on same floor as us but is lower car number|| (ofloor==current_floor && j < car_number) )
car_between_up = TRUE;
// if it's going down and there are requests below us if( (odir==DN || odir==STOP) && requests_below ) // if it's below us and above the nearest request if( (ofloor < current_floor&& ofloor >= nearest_lower_req)
// or on same floor as us but is lower car number|| (ofloor==current_floor && j < car_number) )
car_between_dn = TRUE;
// if it's going up and there are requests below us if( (odir==UP || odir==STOP) && requests_below ) // it's below request and closer to it than we are if(nearest_lower_req >= ofloor&& nearest_lower_req - ofloor
< current_floor - nearest_lower_req)
car_opposite_up = TRUE;
// if it's going down and there are requests above us if( (odir==DN || odir==STOP) && requests_above ) // it's above request and closer to it than we are if(ofloor >= nearest_higher_req&& ofloor - nearest_higher_req
< nearest_higher_req - current_floor)
car_opposite_dn = TRUE;
} // end if(not us) } // end for(each car) // if we're going up or stopped, and there is an FR above us, // and there are no other cars going up between us and the FR, // or above the FR going down and closer than we are, // then go up if( (current_dir==UP || current_dir==STOP)&& requests_above && !car_between_up && !car_opposite_dn )
{current_dir = UP;
return;}
// if we're going down or stopped, and there is an FR below // us, and there are no other cars going down between us and // the FR, or below the FR going up and closer than we are, // then go down if( (current_dir==DN || current_dir==STOP)&& requests_below && !car_between_dn && !car_opposite_up )
{current_dir = DN;
return;}
// if nothing else happening, stopcurrent_dir = STOP;
}
void elevator::move() { // if loading or unloading,if(loading_timer || unloading_timer) // don't move
return;if(current_dir==UP) // if going up, go up
current_floor++;
else if(current_dir==DN) // if going down, go down
current_floor--;
}
void elevator::get_destinations() // stop, get destinations
{char ch; // utility char for input
char ustring[BUF_LENGTH]; // utility buffer for input ********
int dest_floor; // destination floor
// gotoxy(1, 22); cout << "Car " << (car_number+1) << " has stopped at floor " << (current_floor+1) << "\nEnter destination floors (0 when finished)";for(int j=1; j<NUM_FLOORS; j++) // get floor requests
{ // maximum; usually fewer // gotoxy(1, 24);cout << "Destination " << j << ": ";
// cin.unsetf(ios::skipws); // do not skip white space// cin >> dest_floor; // get floor number// cin >> ustring; cin.get(ustring, BUF_LENGTH); // (avoid multiple LFs)cin.ignore(10, '\n'); // eat chars, including newline
// cin.get(ch); // eat the newlinedest_floor = atoi(ustring);
// gotoxy(1,24); clreol(); // clear old input lineif(dest_floor==0) // no more requests
{// gotoxy(1,22); clreol(); // clear bottom three lines // gotoxy(1,23); clreol(); // gotoxy(1,24); clreol(); return;}
--dest_floor; // start at 0, not 1if(dest_floor==current_floor) // chose this very floor
{ --j; continue; } // so forget it // if we're stopped, first choice made sets direction if(j==1 && current_dir==STOP)current_dir = (dest_floor < current_floor) ? DN : UP;
destination[dest_floor] = TRUE; // record selection dests_display(); // display destinations}
}
التطبيق
الملفان التاليان يضعهما شخص يستخدم النظام مطورا لمواصفاته الخاصة , ويتضمن الملف الأول عدد الطوابق وعدد المصاعد .
Elev_app.h
elev_app.h
// elev_app.h// provides constants to specify building characteristicsconst int NUM_FLOORS = 20; // number of floors
const int NUM_CARS = 4; // number of elevator cars
ويقوم برنامج الملف الثاني باستهلاك البيانات الاستاتيكية في الفئة elevator , وينشئ عددا من كائناتها عن طريق المؤثر new , ثم يدخل في دوارة تستدعي الدالتين master_tick(), get_floor_request() . وتقوم الدالة المكتبية delay() بإبطاء التشغيل بما يوائم العين البشرية . كما تقوم الدالة sound() بإعطاء مؤثر صوتي يبين مرور الزمن . وعندما يستجيب إلي استحثاث من البرنامج , فإن زمن البرنامج (في مقابل زمن المستخدم) يتوقف , وذلك باختفاء التأثير الصوتي .
Elev_app.cpp
elev_app.cpp
// elev_app.cpp// client-supplied file#include "elev.h" // for class declarations
void main(void)
{ elevator::init(); // initialize static datanew elevator[NUM_CARS]; // create elevators
while(TRUE) { elevator::master_tick(); // send time tick to all cars sound(200); delay(30); nosound(); // beep delay(1000); // pause elevator::get_floor_reqs(); // get floor requests from user}
}
الاستراتيجية العامة
إن بناء نظام ذكي لإدارة تشغيل المصاعد ليس بالأمر السهل . وفي برنامجنا يتولي ذلك الدالة decide() التي تتضمن بعضا من القواعد مرتبة بحسب أولويتها , فإذا تصادف وجود قاعدة , طبقت , ولا ينظر لما يليها من قواعد . وإليك صورة مبسطة إلي حد ما :
1- إذا كان المصعد علي وشك الارتطام بأرضية البدروم أو بالسقف , توقف .
2- إذا كان هذا هو الطابق المقصود , أنزل المستخدمين .
3- إذا كان هناك طابق علوي مطلوب , وكانت الوجهة لأعلي , أدخل المستخدمين .
4- إذا كان هناك طابق سفلي مطلوب , وكانت الوجهة لأسفل , أدخل المستخدمين .
5- إذا لم توجد وجهة أو طلب من أعلي أو من أسفل , توقف .
6- إذا وجد طلب أعلي منا أتجه لأعلي .
7- إذا وجد طلب أسفل كمنا توجه لأسفل .
8- إذا كنا متوقفين أو متجهين لأعلي , وكان هناك طلب من أعلي , وليس هناك مصاعد متجهة بيننا وبين الطالب , أو أعلاه و متجة لأسفل , أقرب منا , أتجه لأعلي .
9- إذا كنا متوقفين أو متجهين لأسفل , وكان هناك طلب من أسفل , وليس هناك مصاعد متجهة بيننا وبين الطالب , أو أسفله ومتجهة لأعلي , أقرب منا أتجه لأعلي .
10- إذا لم توجد قواعد للتطبيق , توقف .
والقاعدتان 8,9 معقدتان بعض الشئ , تحاولان منع أكثر من مصعد أن يتجه لنفس الاستدعاء . علي أن النتيجة ليست مضمونة تماما , ففي بعض الأحايين تبطئ المصاعد في تلبية الاستدعاء خشية وجود مصاعد أخري بطريقها إليه , بينما قد تكون هذه الأخيرة ملبية لاستدعاءات أخري . ويمكن تحسين أداء البرنامج بأن يسمح للدالة decide() أن تميز بين الاستدعاءات لأعلي ولأسفل , عند اختبارها إذا ما كان هناك استدعاءات من أعلي أو من أسفل . ولكن ذلك سوف يجعل من الدالة أكثر تعقيدا عما هي عليه بالفعل .
ونترك مثل هذه التعديلات للقارئ .
تعليقات
إرسال تعليق