⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 maincontrol.cpp

📁 电梯调度模拟,有mfc界面展现5部电梯的相互调度
💻 CPP
字号:
// MainControl.cpp : 实现文件
//

#include "stdafx.h"
#include "MyVariousState.h"
#include "MainControl.h"
#include "MyWaitQueue.h"
#include "ElevatorThread.h"

// CMainControl 对话框

//IMPLEMENT_DYNAMIC(CMainControl, CDialog)

CMainControl::CMainControl(CWnd* pParent /*=NULL*/)
	: CDialog(CMainControl::IDD, pParent)
{
	str_arrElevatorName[0]='1';
	str_arrElevatorName[1]='2';
	str_arrElevatorName[2]='3';
	str_arrElevatorName[3]='4';
	str_arrElevatorName[4]='5';

	iTotalFailTimes = 0;
}

CMainControl::~CMainControl()
{
}

void CMainControl::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
}


BEGIN_MESSAGE_MAP(CMainControl, CDialog)
	ON_BN_CLICKED(IDCCANCEL, &CMainControl::OnBnClickedCcancel)
	ON_BN_CLICKED(IDOK, &CMainControl::OnBnClickedOk)
	ON_WM_DESTROY()
	ON_WM_TIMER()
	ON_COMMAND_RANGE(IDC_FLOORBUTTONS,IDC_FLOORBUTTONS+40,OnFloorBtnClk) 
	ON_MESSAGE(WM_ARRIVE_ONEFLOOR,OnOneFloorArrived)
END_MESSAGE_MAP()


// CMainControl 消息处理程序

BOOL CMainControl::OnInitDialog() 
{
	CDialog::OnInitDialog();

	

	// TODO: Add extra initialization here
	m_myQuit.SubclassDlgItem(IDOK,this);
	m_myAbout.SubclassDlgItem(IDCCANCEL,this);

	//===========创建动态楼层按钮
	CString strCaption;
	int iFloorbtnLeft = 25;
	int iFloorbtnTop = 350;
	int iColWidth = 80;
	int iRowHeight = 65;	

	int iFloorbtnWidth = 55;
	int iFloorbtnHeight = 25;
	int i;

	try{

		for(i=MAX_FLOOR_NUM;i>0;i--)
		{
			strCaption.Format(_T("%d"),i);
			m_pFloorButton[i-1][0]=new MyButton;
			m_pFloorButton[i-1][1]=new MyButton;

			m_pFloorButton[i-1][0]->Create(strCaption+"↑",BS_PUSHBUTTON|WS_CHILD|WS_VISIBLE,\
				CRect(iFloorbtnLeft,iFloorbtnTop+(10-i)*iRowHeight/2,iFloorbtnLeft+iFloorbtnWidth,iFloorbtnTop+(10-i)*iRowHeight/2+iFloorbtnHeight),\
				this,IDC_FLOORBUTTONS+2*(i-1));
			m_pFloorButton[i-1][1]->Create(strCaption+"↓",BS_PUSHBUTTON|WS_CHILD|WS_VISIBLE,\
				CRect(iFloorbtnLeft+iColWidth,iFloorbtnTop+(10-i)*iRowHeight/2,iFloorbtnLeft+iColWidth+iFloorbtnWidth,iFloorbtnTop+(10-i)*iRowHeight/2+iFloorbtnHeight),\
				this,IDC_FLOORBUTTONS+2*(i-1)+1);
		}

	}
	catch(CException* e)
	{
		AfxMessageBox(_T("无法创建楼层按钮,程序不能正常运行。"));
		e->ReportError();
		e->Delete();
		return FALSE;//退出!
	}

	//隐藏掉两个无用的按钮
	m_pFloorButton[19][0]->ShowWindow(FALSE);
	m_pFloorButton[0][1]->ShowWindow(FALSE);



////////////////////////////////创建电梯///////////////////////
	try{

		for(i=0;i<MAX_ELEVATOR_NUM;i++)
		{
			m_elevatorArr[i] = new CMyElevatorThread(i+1,this);
			m_elevatorArr[i]->Create(IDD_MYELEVATOR_DIALOG,this);	
			m_elevatorArr[i]->MoveWindow(CRect(i*205+210,15,(i+1)*205+210,755));
			m_elevatorArr[i]->ShowWindow(SW_SHOW);
		}

	}
	catch(CException* e)
	{
		AfxMessageBox(_T("无法创建电梯,程序不能正常运行。"));
		e->ReportError();
		e->Delete();
		return FALSE;//退出!
	}

	

	return TRUE;  // return TRUE unless you set the focus to a control
	// EXCEPTION: OCX Property Pages should return FALSE
}



void CMainControl::OnBnClickedCcancel()
{
	// TODO: 在此添加控件通知处理程序代码
	//if(IDYES==MessageBox(_T("是否真的结束程序?"),_T("电梯系统"),MB_YESNO))		

	//CDialog::OnOK();
	CAboutDlg dlg;
	dlg.DoModal();
}

void CMainControl::OnBnClickedOk()
{
	// TODO: 在此添加控件通知处理程序代码
	if(IDYES==MessageBox(_T("是否真的结束程序?"),_T("电梯调度系统"),MB_YESNO))		
	OnOK();
}
void CMainControl::OnDestroy() 
{
	CDialog::OnDestroy();

	// TODO: Add your message handler code here
	int i;
	for(i=0;i<MAX_ELEVATOR_NUM;i++)
	{
		delete m_elevatorArr[i];
	}

	for(i=0;i<MAX_FLOOR_NUM;i++)
	{
		delete m_pFloorButton[i][0];
		delete m_pFloorButton[i][1];
	}

	KillTimer(1);
	lWaitQueue.~CMyWaitQueue();

	


}
//主控中心响应外部按钮

void CMainControl::OnFloorBtnClk(UINT curBtn) 
{
	// TODO: Add your control notification handler code here

	int iReqFloor =curBtn-1100+1;
	sOuterRequest tmpOuterRequest = ChangeReqStruct(iReqFloor);

	if((lWaitQueue.searchNode(tmpOuterRequest)) > 0)
	{
		AfxMessageBox(_T("请不要重复请求。"));
		return;
	}

	

	GetDlgItem(curBtn)->EnableWindow(FALSE);

	trytoSchedule(tmpOuterRequest);//立即尝试分派!		

}

//主控中心将外部按钮转换成内部消息传递

sOuterRequest CMainControl::ChangeReqStruct(int iNo)
{
	sOuterRequest tempVal;
	if(iNo%2==0) 
	{
		tempVal.eMyReqDirection =DOWN;
	}
	else
	{
		tempVal.eMyReqDirection =UP;
		iNo++;
	}

	tempVal.iMyReqFloor = iNo/2;
	tempVal.iMyReqTime =0;
	tempVal.bMyReClaimed = FALSE;
	return tempVal;
}


int CMainControl::ChangeReqStruct2(const sOuterRequest& tmpRequest)
{
	return (tmpRequest.eMyReqDirection==UP) ? (2*(tmpRequest.iMyReqFloor-1)) : (2*(tmpRequest.iMyReqFloor-1)+1);

}

int CMainControl::GoodnessEle(const sOuterRequest& tmpOuterRequest)
{
	int returnVal = -1;

	//挨个查看各正常电梯的状态
	int tmpCurFloor;
	int tmpCurWeight;
	int tmpPrioValue;
	bool tmpCanSchedule;
	enum state tmpState;

	int iPrioValue = 10000;//优先数,优先数越小优先级越大
	for(int i=0;i<MAX_ELEVATOR_NUM; i++)
	{
		tmpState = m_elevatorArr[i]->getState();
		tmpCurFloor = m_elevatorArr[i]->getCurFloor();
	    tmpCurWeight=m_elevatorArr[i]->getCurPassengerNum();
		tmpCanSchedule = m_elevatorArr[i]->canSchedule();

		if(tmpState!=MAL_FUNCTION && tmpCanSchedule)
		{
			if(tmpState==Ele_IDLE||(tmpOuterRequest.eMyReqDirection==UP && (tmpState==Ele_UP_RUN || tmpState==Ele_UP_PAUSE)) || \
				(tmpOuterRequest.eMyReqDirection==DOWN && (tmpState==Ele_DOWN_RUN || tmpState==Ele_DOWN_PAUSE)) )
			{
				if(tmpState==Ele_IDLE)
				{
					//计算该电梯的优先数
					tmpPrioValue = DIST_PRIO*abs(tmpOuterRequest.iMyReqFloor-tmpCurFloor)+WEIGHT_PRIO*tmpCurWeight;

					if(tmpPrioValue<iPrioValue)
					{
						iPrioValue = tmpPrioValue;
						returnVal = i;
					}
				}

				if(tmpOuterRequest.eMyReqDirection==UP && tmpOuterRequest.iMyReqFloor>=tmpCurFloor)
				{
					//计算该电梯的优先数
					tmpPrioValue = DIST_PRIO*(tmpOuterRequest.iMyReqFloor-tmpCurFloor)+\
						WEIGHT_PRIO*tmpCurWeight;

					if(tmpPrioValue<iPrioValue)
					{
						iPrioValue = tmpPrioValue;
						returnVal = i;
					}
				}

				if(tmpOuterRequest.eMyReqDirection==DOWN && tmpOuterRequest.iMyReqFloor<=tmpCurFloor)
				{
					//计算该电梯的优先数
					tmpPrioValue = DIST_PRIO*(tmpCurFloor-tmpOuterRequest.iMyReqFloor)+\
						WEIGHT_PRIO*tmpCurWeight;

					if(tmpPrioValue<iPrioValue)
					{
						iPrioValue = tmpPrioValue;
						returnVal = i;
					}
				}

			}
		}
	}

	return returnVal;

}

void CMainControl::Schedule()
{

	if(lWaitQueue.getLength() == 0)
	{
		KillTimer(1);//队列空了,歇会
		return;
	}

	int iReqFloor;
	CString tempString,tempString1;
	sOuterRequest tmpOuterRequest;

	while(lWaitQueue.cutHead(tmpOuterRequest) && !tmpOuterRequest.bMyReClaimed)
	{

		if(tmpOuterRequest.iMyReqTime < BAD_REQUEST_TIME)//如果此请求长时间没有得到分配,则直接删除
		{
			trytoSchedule(tmpOuterRequest);
		}
		else//对于长时间不能调度出去的请求也要处理一下
		{
			iReqFloor = ChangeReqStruct2(tmpOuterRequest);//转换成请求按钮号
			GetDlgItem(IDC_FLOORBUTTONS+iReqFloor)->EnableWindow(TRUE);
			iTotalFailTimes++;//递增总调度失败次数
			tempString.Format(_T("%d"),tmpOuterRequest.iMyReqFloor);	
			tempString1 = (tmpOuterRequest.eMyReqDirection==UP) ? "↑":"↓";		
			AfxMessageBox(_T("很抱歉,下面的请求因超时而被系统取消,请重新请求。\r\n")+tempString+tempString1);
		}

	}

	//将本次追加到队尾的请求标识位恢复
	if(tmpOuterRequest.bMyReClaimed){
		tmpOuterRequest.bMyReClaimed = FALSE;
		lWaitQueue.appendTail(tmpOuterRequest);
	}

	lWaitQueue.refreshLink();

}



void CMainControl::trytoSchedule(sOuterRequest& tmpRequest)
{

	int targetElevator=-1,iReqFloor;
	CString tempString,tempString1;

	if((targetElevator = GoodnessEle(tmpRequest))<0)//目前没有找到合适的接受者,再放入
	{
		tmpRequest.iMyReqTime++;
		tmpRequest.bMyReClaimed = TRUE;
		lWaitQueue.appendTail(tmpRequest);
	}
	else //发消息给目标电梯
	{

		//对于电梯刚好在当前楼层的情况,电梯的返回往往比下面的程序段还要快!
		//所以此段程序不能跟下面的那行调换位置!!!
		tempString1.Format(_T("%c"),str_arrElevatorName[targetElevator]);	
		iReqFloor = ChangeReqStruct2(tmpRequest);//转换成请求按钮号
		GetDlgItem(IDC_FLOORBUTTONS+iReqFloor)->GetWindowText(tempString);	
		GetDlgItem(IDC_FLOORBUTTONS+iReqFloor)->SetWindowText(tempString+"("+tempString1+")");

		m_elevatorArr[targetElevator]->acceptReq(tmpRequest);
	}

	KillTimer(1);
	SetTimer(1,WAIT_INTERVAL*1000,NULL);//启动主控中心调度定时器
}

void CMainControl::OnTimer(UINT nIDEvent) 
{
	// TODO: Add your message handler code here and/or call default
	switch(nIDEvent)
	{
	case 1:
		Schedule();
		break;
	}

	CDialog::OnTimer(nIDEvent);
}


LONG CMainControl::OnOneFloorArrived(WPARAM wP,LPARAM lP)
{

	int iReqFloor=(int)wP;
	CString tempString;

	GetDlgItem(IDC_FLOORBUTTONS+iReqFloor)->EnableWindow(TRUE);

	//m_elevatorArr[1]->m_ElevatorBox.SetBkColor(RGB(0,0,0));
	GetDlgItem(IDC_FLOORBUTTONS+iReqFloor)->GetWindowText(tempString);

	if(tempString.GetLength() >4 )
	{
		tempString = tempString.Mid(0,tempString.GetLength()-3);
		GetDlgItem(IDC_FLOORBUTTONS+iReqFloor)->SetWindowText(tempString);
	}

	//Invalidate(); //重画窗体
	return 0;
}


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -