Федеральное государственное бюджетное образовательное учреждение высшего образования «Омский государственный технический университет»
ПОЯСНИТЕЛЬНАЯ ЗАПИСКА К КУРСОВОЙ РАБОТЕ
по дисциплине «Операционные системы»
РАЗРАБОТКА ПРОГРАММЫ
«МОДЕЛЬ ЖЕЛЕЗНОДОРОЖНЫХ ПЕРЕВОЗОК»
Вариант 30а
Принял:
Доцент, к.н.
А.Н. Флоренсов
__________________
подпись, дата
Выполнил:
студентка гр. ИСТ-151
___________________
подпись, дата
Омск 2017
-
Постановка задачи
Программная Linux модель железнодорожных перевозок между городами с использованием участков одноколейного движения.
Разработать под Linux программу, которая в текстовом режиме вывода моделирует следующую задачу. Между городами А, В и С имеется две различные железные дороги, центральная часть (треть) которых состоит из одного пути, а остальные части имеют 2 пути. Смоделировать множества процессов движения поездов в обе стороны по этой дороге с учетом ограничения возможностей одного пути (на нем поезда должны двигаться только в одном направлении). Всего на маршрутах и остановках в городах должны функционировать 4 поезда. Отображение на экране осуществляется с помощью управляющих последовательностей в виде условных схем в консольном окне. Изображение с помощью текстовых символов должно занимать большую часть консольного окна размером не менее 25 строк и 80 столбцов.
-
Текст программы.
#include <stdlib.h>
#include <time.h>
#include <ncurses.h> //графическая библиотека, подключается отдельно
#include <unistd.h>
#include <string.h>
struct Train //структура для поездов
{
char* routeForward; //последовательность путей при движении вперед
char* routeBack; //последовательность путей при движении назад
bool direction; //направление, true - вперед, false - назад
char name; //символ отображения поезда на экране, пусть будет *
bool isWaiting; //флаг ожидания освобождения пути
int id;
//Здесь и далее по тексту путь и линия - это одно и то же
char currentLine; //текущий занимаемый путь(линия)
char nextLine; //следущий путь(линия) в маршруте
int X; //координаты движения
int Y;
};
struct Train trains[4]; // а всего 4 поезда
/*
* Расстановка начальных значений для поездов, координаты, имена, маршруты и т.д.
*/
void init()
{
trains[0].X = 1; //первый поезд, поедет из города А
trains[0].Y = 10;
trains[0].currentLine = '2';
trains[0].nextLine = '7';
trains[0].routeForward = "27985";
trains[0].routeBack = "58972";
trains[1].X = 75; //второй поезд, поедет из города В
trains[1].Y = 10;
trains[1].currentLine = '3';
trains[1].nextLine = '7';
trains[1].routeForward = "37986";
trains[1].routeBack = "68973";
trains[2].X = 24; // третий поезд, поедет из города С
trains[2].Y = 1;
trains[2].currentLine = '5';
trains[2].nextLine = '8';
trains[2].routeForward = "58974";
trains[2].routeBack = "47985";
trains[3].X = 45; //четвертый поезд, поедет из города С
trains[3].Y = 1;
trains[3].currentLine = '6';
trains[3].nextLine = '8';
trains[3].routeForward = "68971";
trains[3].routeBack = "17986";
for (int i = 0; i < 4; i++)
{
trains[i].name = '*';
trains[i].isWaiting = false;
trains[i].direction = true;
trains[i].id = i;
mvaddch(trains[i].Y, trains[i].X, trains[i].name);
/*вывод с использованием ncurses, выводит в окно и с переводом координат курсора. Это аналог курсор_позишен на windows*/
}
}
/*
* Установка следующей линии на основе маршрута и направления.
*/
void setNextLine(struct Train* train) {
int pos = 0;
//если направление вперед используем соответствующий маршрут (массив символов)
if (train->direction) {
//находим позицию символа текущей линии в маршруте (их 9).
/*strchr - возвращает указатель на искомый символ в массиве, вычитаем из него адрес указателя массива и получаем позицию символа в массиве */
pos = strchr(train->routeForward, train->currentLine) - train->routeForward;
if (pos == strlen(train->routeForward)) {
//если дошли до последнего пути (позиция равна длине массива)
train->nextLine = ' ';
} else {
train->nextLine = train->routeForward[pos + 1];
}
} else {
pos = strchr(train->routeBack, train->currentLine) - train->routeBack;
if (pos == strlen(train->routeBack)) {
train->nextLine = ' ';
} else {
train->nextLine = train->routeBack[pos + 1];
}
}
}
/*
* Проверка на занятость пути, если путь занят, возвращает true иначе false,
* исключение - если два поезда ждут пока их пути освободятся(8-7 7-8 например), тогда возвращает false и поезда могут продолжить движение
*/
bool isNextLineBusy(struct Train* train) {
bool result = false;
//просматриваем все поезда, кроме самого себя, на каких линия они сидят
for (int i = 0; i< 4; i++) {
if (trains[i].id != train->id && trains[i].currentLine == train->nextLine) {
if (trains[i].isWaiting) {
return false;
}
return true;
}
}
return false;
}
/*
* Окончание движения по линии
*/
void endOfTheLine(struct Train* train) {
train->isWaiting = true;
//проверяем свободна ли следующий путь, если нет - ждем
if (!isNextLineBusy(train)) {
//если свободен переходим на нее и снимаем флаг ожидания
train->currentLine = train->nextLine;
setNextLine(train);
train->isWaiting = false;
}
}
/*
* процедура рисования анимации движения и определения смены пути, обусловлена картой местности
*/
void moveTrain(struct Train* train)
{
//в зависимости от линии на которой находится выбирается алгоритм вычисления следующей координаты
//интересное только по краям линии, там вызывается функция endOfTheLine - переход на след. путь в маршруте
//или происходит разворот поезда в обратном направлении, это может произойти на путях 5,6,1,2,3,4
switch (train->currentLine) {
case '1':
case '2':
/*единственная разница в алгоритмах 1 и 2 линии это их расположение на экране, Y координата*/
if (train->currentLine == '2') {
train->Y = 10;
} else {
train->Y = 8;
}
//закрашиваем наше предыдущее положение
mvaddch(train->Y, train->X, '-');
//если поезд едет в сторону линии 7
if (train->nextLine == '7') {
//значит нам надо наращивать координаты
if (train->X< 25) {
train->X++;
} else {
//доехали до 7 линии, перепрыгиваем на нее
endOfTheLine(train);
}
} else {
//поезд едет в сторону станции А
if (train->X > 1) {
train->X--;
} else {
//разворачиваемся и меняем направление движения
train->direction = !train->direction;
setNextLine(train);
}
}
//все case-ы работают примерно так же
break;
case '7':
mvaddch(train->Y, train->X, '-');
train->Y = 9;
if (train->nextLine == '3' || train->nextLine == '4') {
if (train->X< 44) {
train->X++;
} else {
endOfTheLine(train);
}
}
if (train->nextLine == '1' || train->nextLine == '2') {
if (train->X > 26) {
train->X--;
} else {
endOfTheLine(train);
}
}
if (train->nextLine == '9') {
if (train->X< 34) {
train->X++;
}
if (train->X > 34) {
train->X--;
}
if (train->X == 34) {
endOfTheLine(train);
}
}
break;
case '9':
train->X = 34;
if (train->Y == 9 || train->Y == 6) {
mvaddch(train->Y, train->X, ' ');
} else {
mvaddch(train->Y, train->X, '|');
}
if (train->nextLine == '8') {
if (train->Y > 6) {
train->Y--;
} else {
endOfTheLine(train);
}
} else {
if (train->Y< 9) {
train->Y++;
} else {
endOfTheLine(train);
}
}
break;
case '8':
mvaddch(train->Y, train->X, '-');
train->Y = 6;
if (train->nextLine == '6') {
if (train->X< 45) {
train->X++;
} else {
endOfTheLine(train);
}
}
if (train->nextLine == '5') {
if (train->X > 25) {
train->X--;
} else {
endOfTheLine(train);
}
}
if (train->nextLine == '9') {
if (train->X< 34) {
train->X++;
}
if (train->X > 34) {
train->X--;
}
if (train->X == 34) {
endOfTheLine(train);
}
}
break;
case '5':
case '6':
if (train->currentLine == '5') {
train->X = 25;
} else {
train->X = 45;
}
mvaddch(train->Y, train->X, '|');
if (train->nextLine == '8') {
if (train->Y< 6) {
train->Y++;
} else {
endOfTheLine(train);
}
} else {
if (train->Y > 1) {
train->Y--;
} else {
train->direction = !train->direction;
setNextLine(train);
}
}
break;
case '3':
case '4':
if (train->currentLine == '3') {
train->Y = 10;
} else {
train->Y = 8;
}
mvaddch(train->Y, train->X, '-');
if (train->nextLine == '7') {
if (train->X > 45) {
train->X--;
} else {
endOfTheLine(train);
}
} else {
if (train->X< 75) {
train->X++;
} else {
train->direction = !train->direction;
setNextLine(train);
}
}
break;
default:
break;
}
mvaddch(train->Y, train->X, train->name);
}
void printMap() //псвевдографика
{
printw(" 5 C 6 \n");
printw(" | | \n");
printw(" | | \n");
printw(" | | \n");
printw(" | | \n");
printw(" | 9 | \n");
printw(" 8--------- -----------8 \n");
printw(" | \n");
printw("1------------------------- | -------------------------------4\n");
printw("A 7-------- ----------7 B\n");
printw("2------------------------- 9 -------------------------------3\n");
}
void main()
{
WINDOW* screen;
screen = initscr(); // Переход в curses-режим
wresize(screen, 640, 480); //устанавливаем размер окна
printMap();
init();
refresh(); //эта функция опусташает буфер экрана, печатает все, что накопилось
while (1)
{
clear(); //очищаем экран
printMap(); //рисуем чистую карту
//последовательно рисуем поезда, вся инфа о их положении хранится в структуре
for (int i = 0; i < 4; i++)
{
moveTrain(&(trains[i]));
}
refresh();
usleep(300000); //задержка между движением в микросекундах
}
endwin(); // Выход из curses-режима.
}