3 Программный код приложения
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <time.h>
typedef struct Car { // Абстрактная структура, представляющая авто
int x; // Положение автомобиля по x
int y; // Положение автомобиля по y
int color;
} Car;
const int CAR_TRAFFIC = 5; // Кол-во авто, двигающися на одной полосе
const int CAR_DISTANCE = 4; // Дистанция между машинами
const int MIN_SPEED = 10000; // Минимальная скорость
const int MAX_SPEED = 100000; // Максимальная скорость
const int CAR_WIDTH = 4; // Размер машин
const int debug = 0; // Константа для отладки
const int HSTRIPE_RIGHT_Y = 10; // Расположение попутной горизонт. полосы по y
const int HSTRIPE_LEFT_Y = 13; // Расположение встречной горизонт. полосы по y
const int HLINE_Y = 12; // Расположение линий разметки горизонт-x полос
const int VSTRIPE_DOWN_X = 41; // Расположение встречной вертикал. полосы по x
const int VSTRIPE_UP_X = 35; // Расположение попутной вертикал полосы по x
const int VLINE_X = 40; // Расположение линий разметки вертикал-x полос
char grass[] = ",;.',.**"; // Символы, заменяющие траву
pthread_mutex_t hmtx; // Переменная мьютекса
//----------------------------------------------------------
// ГРАФИКА
//----------------------------------------------------------
/*
* Отрисовка фона
*/
void drawBackground()
{
int i, currentChar, flowerColor;
printf("\033[2J"); //Очистка экрана
for ( i = 0; i < 24*80; i++){
currentChar = rand()%8; // Случайный символ травы
if ( grass[currentChar] == '*' ) // Проверка если это цветок
{
switch (currentChar) {
case 6: { printf("\033[0;33;42m"); break; }
case 7: { printf("\033[0;31;42m"); break; }
}
}
else
printf("\033[1;32;42m");
printf("%c", grass[currentChar]);
}
}
/*
* Отрисовка данных работы
*/
void drawCopyright()
{
int i, currentChar, flowerColor;
printf("\033[0;30;42m");
printf("\033[19;47H");
printf("Курсовой проект");
printf("\033[20;47H");
printf("По дисциплине:Операционные системы");
printf("\033[21;47H");
printf("Вариант 25");
printf("\033[22;47H");
printf("Выполнил: Визигин Денис ИВТ-338");
}
/*
* Отрисовка горизонтальных полос дорожного движения т.е. встречной и попутной
* @param offsetY - сдвиг по y, от которого начинается отрисовка
*/
void redrawHStripe(int offsetY)
{
int i, j;
printf("\033[%d;1H\033[1;37;40m", offsetY); // Сдвигаем положение рисования на offsetY
for ( i = 0; i < 2; i++ ){
for ( j = 0; j < 80; j++ )
printf(" ");
printf("\n");
}
}
/*
* Отрисовка горизонтальных разделительных линий
* @param offsetY - сдвиг по y, от которого начинается отрисовка
*/
void redrawHLines(int offsetY)
{
int i, j;
printf("\033[%d;1H\033[1;37;40m", offsetY);
for ( j = 0; j < 80; j++ )
if ( (j%2 != 0) && ((j < 33) || (j > 45)) )
printf("–");
else
printf(" ");
}
/*
* Отрисовка вертикальных полос дорожного движения т.е. встречной и попутной
* @param offsetX - сдвиг по x, от которого начинается отрисовка
*/
void redrawVStripe(int offsetX)
{
int i;
for ( i = 1; i <= 24; i++ ){
printf("\033[%d;%dH\033[1;37;40m", i, offsetX);
printf(" ");
}
}
/*
* Отрисовка горизонтальных разделительных линий
* @param offsetY - сдвиг по y, от которого начинается отрисовка
*/
void redrawVLines(int offsetX)
{
int i;
for ( i = 1; i <= 24; i++ ){
printf("\033[%d;%dH\033[1;37;40m", i, offsetX);
printf("|");
}
}
//----------------------------------------------------------
// ПЕРЕРИСОВКА ДОРОГ
//----------------------------------------------------------
/*
* Отрисовка горизонтальной дороги
*/
void drawHorizontalRoad()
{
redrawHStripe(HSTRIPE_RIGHT_Y);
redrawHStripe(HSTRIPE_LEFT_Y);
redrawHLines(HLINE_Y);
fflush(stdout);
}
/*
* Отрисовка вертикальной дороги
*/
void drawVerticalRoad()
{
redrawVStripe(VSTRIPE_UP_X);
redrawVStripe(VSTRIPE_DOWN_X);
redrawVLines(VLINE_X);
fflush(stdout);
}
//----------------------------------------------------------
// ПЕРЕРИСОВКА МАШИН
//----------------------------------------------------------
/*
* Отрисовка горизонтальной машины
*/
void drawHCar(struct Car car, int road)
{
int i;
printf("\033[%d;1H", car.y);
printf("\033[1;37;%dm", car.color);
if ( road == 0 ){
if ( car.x + CAR_WIDTH <= 80 ){
printf("\033[%dC", car.x);
printf(" | ");
}
}
else{
if ( car.x - CAR_WIDTH >= 0 ){
printf("\033[%dC", (car.x - CAR_WIDTH));
printf(" | ");
}
}
fflush(stdout);
}
/*
* Отрисовка вертикальной машины
*/
void drawVCar(struct Car car, int road)
{
int i;
printf("\033[1;%dH", car.x);
printf("\033[1;37;%dm", car.color);
if (road == 0) {
if ( car.y < 25 ){
printf("\033[%dB", car.y);
for ( i = 0; i < CAR_WIDTH - 1; i++){
if ( i != 1)
printf(" ");
else
printf("––");
printf("\033[2D\033[1B");
}
}
}
else
{
if ( car.y - CAR_WIDTH > 0 ){
printf("\033[%dB", car.y - CAR_WIDTH);
for ( i = 0; i < CAR_WIDTH - 1; i++){
if ( i != 1)
printf(" ");
else
printf("––");
printf("\033[2D\033[1B");
}
}
}
fflush(stdout);
}
//----------------------------------------------------------
// АВТОМОБИЛЬНЫЕ ПОТОКИ
//----------------------------------------------------------
/*
* Нить отвечающая за поток с левой стороны экрана
*/
void* hTrafficLeft(void* arg)
{
int speed, nextCar, i; // Скорость и машина с которой необходимо начинать отрисовку
int onCrossway, crosswayCar; // Логическое значение машины на перекрёстки и числовое
struct Car cars[CAR_TRAFFIC]; // Структура машин
for ( i = 0; i < CAR_TRAFFIC; i++ ){
cars[i].x = 1;
cars[i].y = 13;
cars[i].color = rand()%(47 - 41 + 1) + 41;
}
nextCar = 1; // Следующая машина которая выедет из-за пределов экрана - 1
onCrossway = 0;
crosswayCar = -1;
while (1)
{
speed = rand() % (MAX_SPEED - MIN_SPEED + 1) + MIN_SPEED; //Случ. скорость
redrawHStripe(HSTRIPE_LEFT_Y); //Отрисовка полосы движения
if (!onCrossway) { // Есть ли машина на перекрёстке
for ( i = nextCar - 1; i >= 0; i-- ){
drawHCar(cars[i], 0); // Отрисовка горизонтальной машины
cars[i].x++; // Положение машины
// Определение въехали ли машина на перекрёсток
if ( cars[i].x > (34-CAR_WIDTH) && cars[i].x < (46-CAR_WIDTH) ) {
pthread_mutex_lock(&hmtx);
onCrossway = 1; //true
crosswayCar = i;
}
}
}
else { // Машина на перекрёстке
for ( i = 0; i < nextCar; i++ ) {
drawHCar(cars[i], 0);//Отрисовка машин если они не достигли перекрёстка
if ( (cars[crosswayCar + 1].x < (34 - CAR_WIDTH) && i != crosswayCar) || ( i < crosswayCar ) )
cars[i].x++;
}
cars[crosswayCar].x++; // Движение машины, которая на перекрёстке
// Проверка выхода за пределы экрана
if ( cars[crosswayCar].x >= 80 ) {
pthread_mutex_unlock(&hmtx);
onCrossway = 0;
crosswayCar = -1;
}
}
usleep(speed);
// Машина с которой нужно начинать отсчёт
if ( nextCar < CAR_TRAFFIC )
if ( cars[nextCar-1].x - (CAR_DISTANCE + CAR_WIDTH) >= cars[nextCar].x )
nextCar++;
if (cars[CAR_TRAFFIC-1].x > 80) break;
}
pthread_exit(0);
}
/*
* Нить отвечающая за поток с верхней стороны экрана
*/
void* vTrafficUp(void* arg)
{
int speed, nextCar, i;
int onCrossway, crosswayCar;
struct Car cars[CAR_TRAFFIC];
for ( i = 0; i < CAR_TRAFFIC; i++ ){
cars[i].x = 37;
cars[i].y = 1;
cars[i].color = rand()%(47 - 41 + 1) + 41;
}
nextCar = 1;
onCrossway = 0;
crosswayCar = -1;
while (1)
{
speed = rand() % (MAX_SPEED - MIN_SPEED + 1) + MIN_SPEED;
redrawVStripe(VSTRIPE_UP_X);
if (!onCrossway) {
for ( i = nextCar - 1; i >= 0; i-- ) {
drawVCar(cars[i], 0);
cars[i].y++;
if ( cars[i].y > (10 - CAR_WIDTH) && cars[i].y < (15 - CAR_WIDTH) ) {
if (debug) {
printf("\033[1;1H");
printf("Attempt to lock on traffic up by y = %d", cars[i].y);
}
pthread_mutex_lock(&hmtx);
onCrossway = 1;
crosswayCar = i;
}
}
}
else {
for ( i = 0; i < nextCar; i++ ) {
drawVCar(cars[i], 0);
if ( (cars[crosswayCar + 1].y < (10 - CAR_WIDTH) && i != crosswayCar) || ( i < crosswayCar ) )
cars[i].y++;
}
cars[crosswayCar].y++;
if ( cars[crosswayCar].y > 24 ) {
if (debug){
printf("\033[1;1H");
printf("Attempt to unlock on traffic up by y = %d", cars[crosswayCar].y);
}
pthread_mutex_unlock(&hmtx);
onCrossway = 0;
crosswayCar = -1;
}
}
usleep(speed);
if ( nextCar < CAR_TRAFFIC)
if ( cars[nextCar-1].y - CAR_DISTANCE - CAR_WIDTH >= cars[nextCar].y )
nextCar++;
if (cars[CAR_TRAFFIC-1].y > 25) break;
}
pthread_exit(0);
}
/*
* Нить отвечающая за поток с правой стороны экрана
*/
void* hTrafficRight(void* arg)
{
int speed, nextCar, i;
int onCrossway, crosswayCar;
struct Car cars[CAR_TRAFFIC];
for ( i = 0; i < CAR_TRAFFIC; i++ ){
cars[i].x = 80;
cars[i].y = 11;
cars[i].color = rand()%(47 - 41 + 1) + 41;
}
nextCar = 1;
onCrossway = 0;
crosswayCar = -1;
while (1)
{
speed = rand() % (MAX_SPEED - MIN_SPEED + 1) + MIN_SPEED;
redrawHStripe(HSTRIPE_RIGHT_Y);
if (!onCrossway) {
for ( i = nextCar - 1; i >= 0; i-- ){
drawHCar(cars[i], 1);
cars[i].x--;
if ( cars[i].x > (34+CAR_WIDTH) && cars[i].x <= (46+CAR_WIDTH) ) {
pthread_mutex_lock(&hmtx);
onCrossway = 1;
crosswayCar = i;
}
}
}
else {
for ( i = 0; i < nextCar; i++ ) {
drawHCar(cars[i], 1);
if ( (cars[crosswayCar + 1].x >= (46 + CAR_WIDTH) && i != crosswayCar) || ( i < crosswayCar ) )
cars[i].x--;
}
cars[crosswayCar].x--;
if ( cars[crosswayCar].x <= 0 ) {
pthread_mutex_unlock(&hmtx);
onCrossway = 0;
crosswayCar = -1;
}
}
usleep(speed);
if ( nextCar < CAR_TRAFFIC )
if ( cars[nextCar-1].x + (CAR_DISTANCE + CAR_WIDTH) <= cars[nextCar].x )
nextCar++;
if (cars[CAR_TRAFFIC-1].x < 0) break;
}
pthread_exit(0);
}
/*
* Нить отвечающая за поток с нижней стороны экрана
*/
void* vTrafficDown(void* arg)
{
int speed, nextCar, i;
int onCrossway, crosswayCar;
struct Car cars[CAR_TRAFFIC];
for ( i = 0; i < CAR_TRAFFIC; i++ ){
cars[i].x = 43;
cars[i].y = 24;
cars[i].color = rand()%(47 - 41 + 1) + 41;
}
nextCar = 1;
onCrossway = 0;
crosswayCar = -1;
while (1)
{
speed = rand() % (MAX_SPEED - MIN_SPEED + 1) + MIN_SPEED;
redrawVStripe(VSTRIPE_DOWN_X);
if (!onCrossway) {
for ( i = nextCar - 1; i >= 0; i-- ) {
drawVCar(cars[i], 1);
cars[i].y--;
if ( cars[i].y > (10 + CAR_WIDTH) && cars[i].y < (15 + CAR_WIDTH) ) {
if (debug) {
printf("\033[1;1H");
printf("Attempt to lock on traffic up by y = %d", cars[i].y);
}
pthread_mutex_lock(&hmtx);
onCrossway = 1;
crosswayCar = i;
}
}
}
else {
for ( i = 0; i < nextCar; i++ ) {
drawVCar(cars[i], 1);
if ( (cars[crosswayCar + 1].y >= (15 + CAR_WIDTH) && i != crosswayCar) || ( i < crosswayCar ) )
cars[i].y--;
}
cars[crosswayCar].y--;
if ( cars[crosswayCar].y < 0 ) {
if (debug){
printf("\033[1;1H");
printf("Attempt to unlock on traffic up by y = %d", cars[crosswayCar].y);
}
pthread_mutex_unlock(&hmtx);
onCrossway = 0;
crosswayCar = -1;
}
}
usleep(speed);
if ( nextCar < CAR_TRAFFIC)
if ( cars[nextCar-1].y + (CAR_DISTANCE + CAR_WIDTH) < cars[nextCar].y )
nextCar++;
if (cars[CAR_TRAFFIC-1].y < 0) break;
}
pthread_exit(0);
}
int main(){
srand(time(0));
drawBackground();
drawCopyright();
drawVerticalRoad();
drawHorizontalRoad();
pthread_t ptHL, ptHR, ptVD, ptVU;
pthread_mutex_init(&hmtx, NULL);
pthread_create(&ptHL, NULL, (void*)hTrafficLeft, (void*)0);
pthread_create(&ptVU, NULL, (void*)vTrafficUp, (void*)1);
pthread_create(&ptHR, NULL, (void*)hTrafficRight,(void*)2);
pthread_create(&ptVD, NULL, (void*)vTrafficDown, (void*)3);
getchar();
return(0);
}
