авыаывавы

← разместить еще код

Расшаренный код:

#define _WIN32_WINNT 0x0500
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <process.h>
#include <mem.h>
#include <locale.h>


HANDLE hstdout;					//хэндл вывода
HANDLE sem_in[5];				//семафор на вход в лодку на планете
HANDLE sem_out[5];				//аналогичный семафор на выход
HANDLE mutex;					//мьютекс для корректного изменения данных
HANDLE thread_update;			//хендл нити обновления
HANDLE thread_people[40];		//хендлы нитией, имитирующих поведение людей
HANDLE thread_boat[5];			//хендлы нитией, имитирующих поведение лодок
HANDLE mut;

int height;						//высота окна
int width;						//ширина окна

int city_wait[4];				//кол-во ожидающих
int city_walk[4];				//кол-во отдыхающих
int boat_pos[5];				//номер позиции каждой лодки
int boat_in[5];					//кол-во людей в лодке
int boat_offset[5];				//смещенные лодки относительно главной дороги
int mult = 50;
int people_kol; //количество людей
int shat=5; //количество шатлов
int t=0;

COLORREF clr_water = RGB(155, 190, 245);
COLORREF clr_city = RGB(35, 69, 86);
COLORREF clr_zem = RGB(55, 99, 30);
COLORREF clr_mars = RGB(100, 69, 30);
COLORREF clr_titan = RGB(55, 99, 30);
COLORREF clr_evropa = RGB(100, 100, 30);
COLORREF clr_city_text = RGB(255, 100, 100);
COLORREF clr_boat = RGB(116, 99, 65);
COLORREF clr_boat_text = RGB(255, 255, 255);

//нарисовать квадрат в точке Х,У с размерами в масштабе 1 к 50
void DrawRect(HDC hdc, int x, int y, int dx, int dy) {
	Rectangle(hdc, x * mult, y * mult, (x + dx) * mult, (y + dy) * mult);
}
//нарисовать эллипс в точке Х,У с размерами в масштабе 1 к 50
void DrawEllipse(HDC hdc, int x, int y, int dx, int dy) {
	Ellipse(hdc, x * mult, y * mult, (x + dx) * mult, (y + dy) * mult);
}
//залить фон градиентом
void DrawGradient(HDC hdc) {

	SelectObject(hdc, GetStockObject(DC_PEN));
	SelectObject(hdc, GetStockObject(DC_BRUSH));


	for (int i = 0; i < 100; i++) {
		SetDCBrushColor(hdc, RGB( 95+i, 69+i, 86+i));
		SetDCPenColor(hdc, RGB(95 + i, 69 + i, 86 + i));
		Rectangle(hdc, -200 + i *5, -200 + i * 5, width + 200 - i * 5, height + 200 - i * 5);
	}
}
//вычислить координаты экрана по номеру позиции
COORD Position(int index) {
	COORD c;
	c.X = index+1;
	c.Y = index;
	return c;
	}
//получить индекс города в радиусе 1
int GetIndexNear(int index_pos) {
	switch (index_pos)
	{
	case 0:
		return 0;
	case 3:
		return 1;
	case 6:
		return 2;
	case 9:
		return 3;
	default:
		return -1;
	}
}
//нарисовать город
void DrawCity(HDC hdc, int index) {

	SelectObject(hdc, GetStockObject(DC_PEN));
	SelectObject(hdc, GetStockObject(DC_BRUSH));



	SetDCBrushColor(hdc, clr_city);		//цвет заливки
	SetDCPenColor(hdc, clr_city);			//цвет обводки




	switch (index)
	{
	case 0:
	    SetDCBrushColor(hdc, clr_zem);
		DrawEllipse(hdc, 4, 0, 3, 2);
		//DrawRect(hdc, 3, 0, 5, 2);
		break;
	case 1:
	    SetDCBrushColor(hdc, clr_mars);
		DrawEllipse(hdc, 7, 3, 3, 2);
		//DrawRect(hdc, 6, 3, 5, 2);
		break;
	case 2:
		DrawEllipse(hdc, 10, 6, 3, 2);
		//DrawRect(hdc, 9, 6, 5, 2);
		break;
	case 3:
	    SetDCBrushColor(hdc, clr_evropa);
		DrawEllipse(hdc, 6, 9, 3, 2);
		//DrawRect(hdc, 5, 9, 5, 2);
		break;

	}






}
//нарисовать данные в городе
void UpdateCity(HDC hdc, int index, int countWait, int countIn) {
	TCHAR buf[10];							//буфер текста
	SelectObject(hdc, GetStockObject(DC_PEN));
	SelectObject(hdc, GetStockObject(DC_BRUSH));
	SetBkColor(hdc, clr_city);			//цвет фона
	SetTextColor(hdc, clr_city_text);		//цвет текста
	setlocale(LC_ALL,"Russian");
	SetDCBrushColor(hdc, clr_city);		//цвет заливки
	SetDCPenColor(hdc, clr_city);
	/*if (index < 3)Rectangle(hdc, (index * 3 + 1)*mult  , (index * 3 )*mult + 20, (index * 3 + 3)*mult + 20, (index * 3 )*mult + 30);
	else
		Rectangle(hdc, (index * 3 - 3)*mult, (index * 3 )*mult +20, (index * 3)*mult , (index * 3 )*mult + 30);*/

	switch (index)
	{
	case 0:
	    SetBkColor(hdc, clr_zem);
		sprintf(buf,  "Ждет:%d", countWait);
		TextOut(hdc, (5.5) * mult, (1) * mult - 20, buf, 6);

		sprintf(buf, "Внутри:%d", countIn);
		TextOut(hdc, (5.5) * mult, (1) * mult + 10, buf, 9);
		sprintf(buf, "Земля");
		TextOut(hdc, (4) * mult + 10, (1) * mult - 10, buf, 6);

        SetBkColor(hdc, RGB(95 , 69 , 86 ));
		sprintf(buf, "Людей всего");
		TextOut(hdc, (10.5) * mult, (2) * mult - 10, buf, 12);
		sprintf(buf, "%d", people_kol);
		TextOut(hdc, (11) * mult, (2) * mult + 10, buf, 2);

		break;
	case 1:
	    SetBkColor(hdc, clr_mars);
		sprintf(buf,"Ждет:%d", countWait);
		TextOut(hdc, (8.5) * mult, (4) * mult - 20, buf, 7);
		sprintf(buf,"Внутри:%d", countIn);
		TextOut(hdc, (8.5) * mult, (4) * mult + 10, buf, 9);
		sprintf(buf, "Марс");
		TextOut(hdc, (7) * mult + 10, (4) * mult - 10, buf, 5);
		break;
	case 2:
		sprintf(buf,"Ждет:%d", countWait);
		TextOut(hdc, (11.5) * mult, (7) * mult - 20, buf, 7);
		sprintf(buf,"Внутри:%d", countIn);
		TextOut(hdc, (11.5) * mult, (7) * mult + 10, buf, 9);
		sprintf(buf,"Титан");
		TextOut(hdc, (10) * mult + 10, (7) * mult - 10, buf, 6);
		break;
	case 3:
	    SetBkColor(hdc, clr_evropa);
		sprintf(buf,"Ждет:%d", countWait);
		TextOut(hdc, (6.5) * mult, (10) * mult - 20, buf, 7);
		sprintf(buf, "Внутри:%d", countIn);
		TextOut(hdc, (6.5) * mult, (10) * mult + 10, buf, 9);
		sprintf(buf, "Европа");
		TextOut(hdc, (7.5) * mult + 10, (10) * mult - 10, buf, 7);
		break;

	}


}
//нарисовать лодку
void DrawBoat(HDC hdc, int index_pos, int count_in,int offset) {
	COORD c = Position(index_pos);
	c.X+=offset;
	TCHAR buf[10];
	SelectObject(hdc, GetStockObject(DC_PEN));
	SelectObject(hdc, GetStockObject(DC_BRUSH));

	SetTextColor(hdc, clr_boat_text);		//цвет текста
	SetBkColor(hdc, clr_boat);			//цвет фона

	SetDCBrushColor(hdc, clr_boat);
	SetDCPenColor(hdc, clr_boat);

	DrawEllipse(hdc, c.X, c.Y, 1, 1);

	sprintf(buf, "%d", count_in);
	TextOut(hdc, c.X * mult + 20, c.Y * mult + 15, buf, 2);
}
//очистить дорогу
void RedrawRoad(HDC hdc) {
	SelectObject(hdc, GetStockObject(DC_PEN));
	SelectObject(hdc, GetStockObject(DC_BRUSH));
	SetDCBrushColor(hdc, clr_water);
	SetDCPenColor(hdc, clr_water);
	for (int i = 0; i < 10; i++) {
		DrawEllipse(hdc, Position(i).X-1, Position(i).Y, 1, 1);
		DrawEllipse(hdc, Position(i).X, Position(i).Y, 1, 1);
		DrawEllipse(hdc, Position(i).X+1, Position(i).Y, 1, 1);
	}
}
//нарисовать карту
void DrawMap(HDC hdc) {

	for (int i = 0; i < 4; i++) {
		DrawCity(hdc, i);
	}
	SelectObject(hdc, GetStockObject(DC_PEN));
	SelectObject(hdc, GetStockObject(DC_BRUSH));
	SetDCBrushColor(hdc, clr_water);
	SetDCPenColor(hdc, clr_water);
	for (int i = -125; i < 15 * mult; i++) {
		Rectangle(hdc, i+1.3 * mult, i, i + 2.7 * mult, i + 2 * mult);
	}
	//SetDCBrushColor(hdc, clr_city);		//цвет заливки
	//SetDCPenColor(hdc, clr_city);
	/*for (int i = 0; i < 4; i++) {
		if (i < 3)Rectangle(hdc, (i * 3 + 1)*mult-25, (i * 3)*mult , (i * 3 + 3 + 1)*mult + 20, (i * 3+1)*mult);
		else
			Rectangle(hdc, (i * 3 - 3 + 1)*mult, (i * 3)*mult, (i * 3+1 + 1)*mult+25, (i * 3+1)*mult );
	}*/
}


//попытка сесть в лодку в городе. Вернет индекс лодки, иначе -1
int TrySit(int index_city) {
	for (int i = 0; i < shat; i++) {
		if (GetIndexNear(boat_pos[i]) == index_city && boat_in[i] < 5) return i;
	}
	return -1;
}
//рандом индекса города с исключением
int RndIndexCity(int index_current) {
	while (1) {
		int index = rand() % 4;
		if (index != index_current) return index;
	}
}
//имитация поведения человека
unsigned __stdcall People(void* args) {
	srand((int)args * time(0) * 3000);
	int index_cur = rand() % 4;
	int index_boat;

	while (1) {
		WaitForSingleObject(mutex, INFINITE);
		if (city_walk[index_cur] > 0) city_walk[index_cur]--;
		city_wait[index_cur]++;
		ReleaseMutex(mutex);
		if(city_wait[index_cur]>4){
                ReleaseSemaphore(mut, 1, NULL);
        boat_pos[3]=0;
        t=1;
		}
		while (1)
		{
			WaitForSingleObject(sem_in[index_cur], INFINITE); //ждем семафор на вход в нашем городе
			WaitForSingleObject(mutex, INFINITE);		//меняем данные

			index_boat = TrySit(index_cur);
			if (index_boat >= 0 && boat_in[index_boat]<6) {		//если сел, то изменение данных,
															//иначе ждать заново
				boat_in[index_boat]++;
				city_wait[index_cur]--;
				ReleaseMutex(mutex);
				break;
			}
			ReleaseMutex(mutex);
		}

		index_cur = RndIndexCity(index_cur);				//генерация маршрута

		while (1)
		{
			WaitForSingleObject(sem_out[index_cur], INFINITE); //ждем семафор на выход в новом городе
			WaitForSingleObject(mutex, INFINITE);					//меняем данные

			if (GetIndexNear(boat_pos[index_boat]) == index_cur) {	//если в лодка в нужном городе,
																	//то выход,иначе ждать заново
				if (boat_in[index_boat] > 0) boat_in[index_boat]--;
				city_walk[index_cur]++;
				ReleaseMutex(mutex);
				break;
			}
			ReleaseMutex(mutex);
		}
		Sleep(10000 + rand() % 3000);
	}

}
//имитация поведения шатла
unsigned __stdcall Boat(void* args) {
	int index = (int)args;
	int stp=index;
	if((index==3||index==4)&&t==0){
            WaitForSingleObject(mut, INFINITE);
         stp=1;
	}
        											//получили личный номер
	srand(index*time(0) * 1000);

	int step = rand() % 2+1;
	if(step==2)step=1;
	boat_pos[index] = rand() % 2 + 2 * stp;
	int index_near = GetIndexNear(boat_pos[index]);
	while (1) {


		if (index_near == 0 || index_near == 3) step *= -1;
		if(boat_pos[index]<-1)	boat_pos[index]=1;//если на краю маршрута, то изменить направление
		if(boat_pos[index]>10) boat_pos[index]=8;
		boat_pos[index] += step;										//шагнуть

		index_near = GetIndexNear(boat_pos[index]);						//получить остановку рядом
		if (index_near >= 0) {
			for (int i = 0; i < 5; i++) {
				ReleaseSemaphore(sem_out[index_near], 1, NULL);	//сигнал на выход в планете рядом
				Sleep(500);
			}
			for (int i = 0; i < 5; i++) {
				ReleaseSemaphore(sem_in[index_near], 1, NULL);	//сигнал на вход в планете рядом
				Sleep(500);
			}
		}
		Sleep(200);
	}

}
//нить отрисовки в окно по данным
unsigned __stdcall Update(void* args) {
	HDC hdc;
	hdc = GetDC(hstdout);

	while (1) {

		RedrawRoad(hdc);							//очистка дороги


		for (int i = 0; i < shat; i++) {
			DrawBoat(hdc, boat_pos[i], boat_in[i],boat_offset[i]);			//прорисовка лодок

		}


		for (int i = 0; i < 4; i++) {
			UpdateCity(hdc, i, city_wait[i], city_walk[i]); //прорисовка городов
		}
		Sleep(200);
	}
}


//запуск потоков
void Initialize() {
     people_kol = rand() % 30;
	//создание мьютексов и семафоров
	mutex = CreateMutex(NULL, FALSE, NULL);
	for (int i = 0; i < 4; i++) {
		sem_in[i] = CreateSemaphore(NULL, 0, 5, NULL);
		sem_out[i] = CreateSemaphore(NULL, 0, 5, NULL);
	}
	mut= CreateSemaphore(NULL, 0, 2, NULL);
	//создание нитей
	thread_update = (HANDLE)_beginthreadex(NULL, 4096, &Update, NULL, 0, NULL);
	for (int i = 0; i < shat; i++) {
		thread_boat[i] = (HANDLE)_beginthreadex(NULL, 4096, &Boat, (void*)i, 0, NULL);
	}
	for (int i = 0; i < people_kol; i++) {
		thread_people[i] = (HANDLE)_beginthreadex(NULL, 4096, &People, (void*)i, 0, NULL);//здесь создается 25 пассажиров
	}
}
//остановка потоков
void Destruct() {
	for (int i = 0; i < people_kol; i++) {
		CloseHandle(thread_people[i]);
	}
	for (int i = 0; i < shat; i++) {
		CloseHandle(thread_boat[i]);
	}
	for (int i = 0; i < 4; i++) {
		CloseHandle(sem_in[i]);
		CloseHandle(sem_out[i]);
	}
	CloseHandle(thread_update);
	CloseHandle(mutex);
}


//процесс окна
LRESULT WINAPI WinProc(HWND hwnd, UINT tmsg, WPARAM wParam, LPARAM lParam) {
	switch (tmsg)
	{
		//по закрытию окна, закрыть потоки
	case WM_DESTROY:
	{
		Destruct();
		PostQuitMessage(0);
		return 0;
	}
	}
	return DefWindowProc(hwnd, tmsg, wParam, lParam);
}
//создание и запуск окна
int StartWindow() {
	COORD pos; //для установления координат

	WNDCLASS wc; //настройки окна
	STARTUPINFO si; //информация о процедуре
	int nCmdShow;
	LRESULT WINAPI WinProc(HWND, UINT, WPARAM, LPARAM); //запускаем процедуру окна
	GetStartupInfo(&si); //получаем информацию

	if (si.dwFlags & STARTF_USESHOWWINDOW)
	{
		nCmdShow = si.wShowWindow;
	}
	else { nCmdShow = SW_SHOWDEFAULT; }
	//подготавливаемся к выводу окна...
	HINSTANCE hInstance = GetModuleHandle(NULL);
	memset(&wc, 0, sizeof(wc));
	wc.lpszClassName = "Boats"; //задаём все параметры окна...
	wc.lpfnWndProc = WinProc;
	wc.hCursor = LoadCursor(NULL, IDC_ARROW);
	wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
	wc.hInstance = hInstance;

	if (!RegisterClass(&wc)) return -1; //проверяем готовность окна
	hstdout = CreateWindow("Boats", "Boats", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,
		CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, hInstance, NULL); //назначаем хэндл
	if (!hstdout) return -2; //проверяем на то, что окно создано
	SetWindowPos(hstdout, HWND_BOTTOM, 0, 0, width, height, SWP_NOMOVE); //задаём размер окна
	ShowWindow(hstdout, nCmdShow); //показываем на экран окно
	return 0;
}
//точка входа
void main() {
	MSG msg; //сообщение от окна
	width = 800; //задаем размеры
	height = 800;
	srand(time(0)); //обновляем рандом

	for (int i = 0; i < 3; i++) {
		boat_pos[i] = 0; //инициализации первоначальных позиций людей
		boat_in[i] = 0;
	}
    boat_pos[3] =-10; //инициализации первоначальных позиций людей
    boat_in[3] = 0;
    boat_pos[4] =-10; //инициализации первоначальных позиций людей
    boat_in[4] = 0;
	boat_offset[0]=-1;
	boat_offset[1]=0;
	boat_offset[2]=1;
	boat_offset[3]=0;
	boat_offset[4]=1;

	//запуск окна, если ошибок нет (==0), то продолжаем
	if (StartWindow() == 0) {

		HDC hdc = GetDC(hstdout);

		DrawGradient(hdc);

		DrawMap(hdc);


		Initialize();//запускаем потоки
		while (GetMessage(&msg, 0, 0, 0)) //крутимся
		{
			DispatchMessage(&msg); //обработка ошибок
		}
	}
}