Архив3 / Kursach(33) / 09. ТСПП (дод Г)
.docxДодаток Д
Лістинги
Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using Elevator;
namespace consoleApp
{
class Program // Клас Program
{
static void Main(string[] args)
{
Building theBuilding = new Building(); //Створюємо будинок
Console.SetCursorPosition(1, 24);
Console.WriteLine(); //Переводим на строчку вниз, щоб потім не скакати
while (true)
{
theBuilding.master_tick(); //таймер
theBuilding.record_floor_reqs();
} } }}
ClassLibrary1.dll
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Elevator
{
public enum Direction { UP = 0, DOWN = 1, STOP = 2 }
public class Building
{
public static void clear_line()
{
for (int i = 0; i < 79; i++) Console.Write(" ");
}
private bool[,] floor_request; //Масив запитів поверхів
Elevator[] car_list; //Кабінки - ліфти
//Конструктор
public Building()
{
Console.Clear(); // Очистка екрану
car_list = new Elevator[4]; // Обявлення масиву 4х ліфтів
floor_request = new bool[2, 20]; // 2 направлення 20 поверхів
for (int i = 0; i < 4; i++) створити ліфти
{
car_list[i] = new Elevator(this, i); //Клас Elevator
}
for (int i = 0; i < 20; i++) // Для кожного поверху
{
Console.SetCursorPosition(3, 20 - i); // виводим номер поверху на екран
Console.Write((i + 1));
if (i < 10) Console.Write(" ");
floor_request[(int)Direction.UP, i] = false; // Запитів ще не було
floor_request[(int)Direction.DOWN, i] = false;
}
}
public void master_tick() // Метроном
{
int j;
show_floor_reqs(); // Вивести запити поверхів
for (j = 0; j < 4; j++) // Для кожного ліфта
{
Elevator el = (Elevator)car_list[j];
el.car_tick1(); // Куди поїде кожен ліфт?
}
for (j = 0; j < 4; j++)
{
Elevator el = (Elevator)car_list[j];
el.car_tick2(); Реальний запуск кожного ліфта
}
}
public bool get_floor_req(Direction dir, int floor) // Перевірка того, чи є запити
{
return floor_request[(int)dir, floor];
}
public void set_floor_req(Direction dir, int floor, bool updown) // Встановити запит
{
floor_request[(int)dir, floor] = updown;
}
public int get_cars_floor(int carNo) // Найти кабінку
{
return car_list[carNo].get_floor();
}
public Direction get_cars_dir(int carNo) // Визначення направлення
{
return car_list[carNo].get_direction();
}
public void show_floor_reqs() Вивід запитів
{
for (int j = 0; j < 20; j++)
{
Console.SetCursorPosition(7, 20 - j);
if (floor_request[(int)Direction.UP, j]) Console.Write("^"); // стрілка вверх
else Console.Write(" ");
Console.SetCursorPosition(7 + 3, 20 - j);
if (floor_request[(int)Direction.DOWN, j]) Console.Write("v"); // стрілка вниз
else Console.Write(" ");
}
}
public void record_floor_reqs() // Получення запитів з поверху
{ // так як натиснення кнопок у ліфті на поверсі
char[] ustring = new char[80];
int iFloor;
char chDirection;
Console.SetCursorPosition(1, 22); // низ екрану
Console.Write("Введiть \"!\" для визову лiфта або ENTER для продовження: ");
string en = Console.ReadLine(); //очікування вводу
if (en != "!") return; //якщо не ! то ввод відміняється
Console.SetCursorPosition(1, 22);
Building.clear_line();
Console.SetCursorPosition(1, 22);
Console.Write("На якому ви етажi? ");
iFloor = int.Parse(Console.ReadLine()); //// получити поверх
Console.Write("В якому направленнi будете рухатись(u/d): ");
string dir = Console.ReadLine(); // получити направлення
chDirection = dir[0]; // получити символ
if (chDirection == 'u') floor_request[(int)Direction.UP, iFloor - 1] = true; // запит вверх
if (chDirection == 'd') floor_request[(int)Direction.DOWN, iFloor - 1] = true; // запит вниз
Console.SetCursorPosition(1, 22); // стерти старий текст
Building.clear_line();
Console.SetCursorPosition(1, 23);
Building.clear_line();
Console.SetCursorPosition(1, 24);
Building.clear_line();
}
}
} // Закінчення класу Building
namespace Elevator // функціонал класу Elevator
{
public class Elevator
{
private Building ptrBuilding;
private int car_number;
private int current_floor;
private int old_floor;
private Direction current_dir;
private bool[] destination;
private int loading_timer;
private int unloading_timer;
public Elevator(Building ptrB, int nc) // конструктор
{
ptrBuilding = ptrB;
car_number = nc;
current_floor = 0; // почати з 0
old_floor = 0; // запам’ятати бивший поверх
destination = new bool[20];
current_dir = Direction.STOP; // спочатку стоїть на місці
for (int j = 0; j < 20; j++)
{
destination[j] = false; // пасажири ще не натискали кнопки
}
loading_timer = 0; // ще не почалась посадка
unloading_timer = 0; // ще не почалась висадка
}
public void car_tick1() // метроном 1 для кожного ліфта
{
car_display(); // кабінка
dests_display(); // кінцеві поверхи
if (loading_timer > 0) --loading_timer; //рахунок часу посадки
if (unloading_timer > 0) --unloading_timer; // рахунок часу висадки
decide(); // прийняття рішення
}
private void decide() // прийняття рішення
{
int j;
//флаги показують зверху чи знизу запроси чи назначення
bool destins_above, destins_below; //кінцеві пункти
bool requests_above = false, requests_below = false; // запити
int nearlest_higher_req = 0;
int nearlest_lower_req = 0;
bool car_between_up, car_between_dn;
bool car_opposite_up, car_opposite_dn;
int ofloor; // поверх
Direction odir; // направлення
// впевнитись чи ми не дуже високо чи низько
if ((current_floor == 20 - 1 && current_dir == Direction.UP) ||
(current_floor == 0 && current_dir == Direction.DOWN)) current_dir = Direction.STOP;
//якщо етаж назначення - цей, почати висадку
if (destination[current_floor] == true)
{
destination[current_floor] = false; // удалити це значення
if (unloading_timer == 0) // висадка
unloading_timer = 3;
return;
}
// провести посадку на борт
if (ptrBuilding.get_floor_req(Direction.UP, current_floor) && current_dir != Direction.DOWN)
{
current_dir = Direction.UP; // якщо була зупинка
ptrBuilding.set_floor_req(current_dir, current_floor, false);
if (loading_timer == 0) // посадка
loading_timer = 3;
return;
}
// посадити пасажирів
if (ptrBuilding.get_floor_req(Direction.DOWN, current_floor) && current_dir != Direction.UP)
{
current_dir = Direction.DOWN; // якщо була зупинка
// удалити ЗП в данному направленні
ptrBuilding.set_floor_req(current_dir, current_floor, false);
if (loading_timer == 0) // посадка
loading_timer = 3;
return;
}
// Перевірка інших назначень чи ЗП (запитів поверхів)
destins_above = false;
destins_below = false;
for (j = current_floor + 1; j < 20; j++) // перевірка верхніх поверсів
{
if (destination[j])
destins_above = true;
if (ptrBuilding.get_floor_req(Direction.UP, j) || ptrBuilding.get_floor_req(Direction.DOWN, j))
{
requests_above = true;
if (nearlest_higher_req == 0)
nearlest_higher_req = j;
}
}
for (j = current_floor - 1; j >= 0; j--) // перевірка нижніх поверхів
{
if (destination[j])
destins_below = true;
if (ptrBuilding.get_floor_req(Direction.UP, j) || ptrBuilding.get_floor_req(Direction.DOWN, j))
{
requests_below = true;
if (nearlest_lower_req == 0)11111111111111111111111111111111111111111111111
nearlest_lower_req = j;
} }
// якщо немає запитів - зупитись
if (!destins_above && !requests_above && !destins_below && !requests_below)
{ current_dir = Direction.STOP;
return;
}// Якщо є назначення – почати роботу
if (destins_above && (current_dir == Direction.STOP || current_dir == Direction.UP))
{ current_dir = Direction.UP;
return;
} if (destins_below && (current_dir == Direction.STOP || current_dir == Direction.DOWN))
{
current_dir = Direction.DOWN;
return;
}
// перевірка руху ліфта
car_between_dn = false;
car_between_up = false;
car_opposite_dn = false;
car_opposite_up = false;
for (j = 0; j < 4; j++) // перевіряєм кожний ліфт
{ if (j != car_number) // якщо це не наш ліфт
{ ofloor = ptrBuilding.get_cars_floor(j); // встановити його поверх
odir = ptrBuilding.get_cars_dir(j); // та направлення
// якщо їде вгору та ЗП вгорі
if ((odir == Direction.UP || odir == Direction.STOP) && requests_above)
}
if ((current_dir == Direction.UP || current_dir == Direction.STOP) &&
requests_above && !car_between_up && !car_opposite_dn)
{ current_dir = Direction.UP;
return;
}
if ((current_dir == Direction.DOWN || current_dir == Direction.STOP) &&
requests_below && !car_between_dn && !car_opposite_up)
{ current_dir = Direction.DOWN;
return; // зупинитись
}
current_dir = Direction.STOP;
} // Кінець метода decide
private void dests_display() // вевести кінцеві поверхи
{
for (int j = 0; j < 20; j++)
{
Console.SetCursorPosition(7 - 2 + (car_number + 1) * 7, 20 - j);
if (destination[j])
Console.Write("*"); // Зірочка – позначення поверху
else
Console.Write(" "); // пробіл
} }
private void car_display() // вивід образу ліфта
{
Console.SetCursorPosition(7 + (car_number + 1) * 7, 20 - old_floor);
Console.Write(" "); // стерти зі старої позиції
Console.SetCursorPosition(7 - 1 + (car_number + 1) * 7, 20 - current_floor);
switch (loading_timer) // завантаження ліфта
{ case 3:
Console.Write("\x01W W "); //ліфт з відкритими дверима
break; // мордочка зліва
case 2:
Console.Write(" W\x01W " ); // мордочка в дверях
get_distinations(); получити кінцевий поверх
break;
case 1:
Console.Write(" WWW "); закриті двері без мордочки
break;
case 0:
Console.Write(" WWW "); двері закриті
break;
} Console.SetCursorPosition(7 + (car_number + 1) * 7, 20 - current_floor);
switch (unloading_timer) // вигризка ліфта
{ case 3:
Console.Write("W\x01W "); // двері відкриті, мордочка в дверях
break;
case 2:
Console.Write("W W\x01"); // Двері відкриті мордочка справа
break;
case 1:
Console.Write("WWW "); // двері закриті мордочки немає
break;
case 0:
Console.Write("WWW "); двері закриті
break;
}
old_floor = current_floor; // приїхали
} public void car_tick2() // метроном 2 для кожного ліфта
{ move(); їдемо (якщо потрібно)
} private void move()
{ if (loading_timer > 0 || unloading_timer > 0) // якщо посадка чи висадка
return;
if (current_dir == Direction.UP) // якщо вверх - вверх
current_floor++;
else
if (current_dir == Direction.DOWN) // якщо вниз - вниз
current_floor--;
} public int get_floor() // получення данниго поверху
{ return current_floor;
} public Direction get_direction() // вилучення данного направлдення
{
return current_dir;
}
public void get_distinations() // зупинка
{
int dest_floor; // поверх назначення
Console.SetCursorPosition(1, 22); // получити запроси поверхів
Building.clear_line();
Console.SetCursorPosition(1, 22);
Console.Write("Лiфт " + (car_number + 1) + " зупинився на поверсi " + (current_floor + 1) +
"\n введiть номер поверху для назначення(або 0 для закiнчення вводу)");
for (int j = 1; j < 20; j++)
{
Console.SetCursorPosition(1, 24);
Console.Write("Етаж назначення" + j + ": ");
dest_floor = int.Parse(Console.ReadLine());
Console.SetCursorPosition(1, 24);
Building.clear_line(); // стерти стару стрічку
if (dest_floor == 0) // якщо немає більше запитів
{
//стерти 3 нижніх стрічки
Console.SetCursorPosition(1, 22);
Building.clear_line();
Console.SetCursorPosition(1, 23);
Building.clear_line();
Console.SetCursorPosition(1, 24);
Building.clear_line();
return;
} --dest_floor; // починати з 0 а не з 1
if (dest_floor == current_floor) // вибрати даний поверх
{
j--; // забути його
continue;
}
if (j == 1 && current_dir == Direction.STOP) // записати вибір
current_dir = (dest_floor < current_floor) ? Direction.DOWN : Direction.UP;
destination[dest_floor] = true;
dests_display(); вивести поверхи назначення
}
}
}
}