www.pudn.com > p_eating.rar > eatingDlg.cpp


// eatingDlg.cpp : implementation file 
// 
 
#include "stdafx.h" 
#include "eating.h" 
#include "eatingDlg.h" 
 
#ifdef _DEBUG 
#define new DEBUG_NEW 
#undef THIS_FILE 
static char THIS_FILE[] = __FILE__; 
#endif 
 
#define DEBUGING 
///////////////////////////////////////////////////////////////////////////// 
// CAboutDlg dialog used for App About 
#include "math.h" 
#include "SpecialDlg.h" 
#include ".\eatingdlg.h" 
 
extern CPoint ta5[5];      //定义五个变量表示哲学家所在位置 
extern CPoint tropic5[5]; 
extern CPoint usetropic[5]; 
extern int    radius; 
extern CPoint CenterPoint; 
 
class CAboutDlg : public CDialog 
{ 
public: 
	CAboutDlg(); 
 
// Dialog Data 
	//{{AFX_DATA(CAboutDlg) 
	enum { IDD = IDD_ABOUTBOX }; 
	//}}AFX_DATA 
 
	// ClassWizard generated virtual function overrides 
	//{{AFX_VIRTUAL(CAboutDlg) 
	protected: 
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support 
	//}}AFX_VIRTUAL 
 
// Implementation 
protected: 
	//{{AFX_MSG(CAboutDlg) 
	//}}AFX_MSG 
	DECLARE_MESSAGE_MAP() 
}; 
 
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) 
{ 
	//{{AFX_DATA_INIT(CAboutDlg) 
	//}}AFX_DATA_INIT 
} 
 
void CAboutDlg::DoDataExchange(CDataExchange* pDX) 
{ 
	CDialog::DoDataExchange(pDX); 
	//{{AFX_DATA_MAP(CAboutDlg) 
	//}}AFX_DATA_MAP 
} 
 
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) 
	//{{AFX_MSG_MAP(CAboutDlg) 
		// No message handlers 
	//}}AFX_MSG_MAP 
END_MESSAGE_MAP() 
 
///////////////////////////////////////////////////////////////////////////// 
// CEatingDlg dialog 
 
CEatingDlg::CEatingDlg(CWnd* pParent /*=NULL*/) 
	: CDialog(CEatingDlg::IDD, pParent) 
	, m_Clock(0) 
{ 
	//{{AFX_DATA_INIT(CEatingDlg) 
	//}}AFX_DATA_INIT 
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32 
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); 
} 
 
void CEatingDlg::DoDataExchange(CDataExchange* pDX) 
{ 
	CDialog::DoDataExchange(pDX); 
	//{{AFX_DATA_MAP(CEatingDlg) 
	DDX_Control(pDX, IDC_SLIDER1, m_AdjustSpeed); 
	DDX_Control(pDX, IDOK, m_okBtn); 
	DDX_Control(pDX, IDC_BTN_STOP, m_stopBtn); 
	DDX_Control(pDX, IDC_BTN_BEGIN, m_beginBtn); 
	DDX_Control(pDX, IDC_STATIC_VIEW, m_wndView); 
	//}}AFX_DATA_MAP 
	DDX_Control(pDX, IDC_RADIO1, m_Strategy1); 
	DDX_Control(pDX, IDC_LIST1, m_Process); 
	DDX_Text(pDX,IDC_EDIT1,m_Clock); 
	DDX_Control(pDX, IDC_LIST2, m_Result); 
} 
 
BEGIN_MESSAGE_MAP(CEatingDlg, CDialog) 
	//{{AFX_MSG_MAP(CEatingDlg) 
	ON_WM_SYSCOMMAND() 
	ON_WM_PAINT() 
	ON_WM_QUERYDRAGICON() 
	ON_BN_CLICKED(IDC_BTN_BEGIN, OnBtnBegin) 
	ON_BN_CLICKED(IDC_BTN_STOP, OnBtnStop) 
	ON_WM_DESTROY() 
	ON_NOTIFY(NM_OUTOFMEMORY, IDC_SLIDER1, OnOutofmemorySlider1) 
	ON_NOTIFY(NM_CUSTOMDRAW, IDC_SLIDER1, OnCustomdrawSlider1) 
	ON_BN_CLICKED(IDC_BUTTON1, OnButton1) 
	//}}AFX_MSG_MAP 
	ON_BN_CLICKED(IDOK, OnBnClickedOk) 
	ON_BN_CLICKED(IDC_RADIO1, OnBnClickedRadio1) 
	ON_BN_CLICKED(IDC_RADIO2, OnBnClickedRadio2) 
	ON_BN_CLICKED(IDC_RADIO3, OnBnClickedRadio3) 
	ON_BN_CLICKED(IDC_BUTTON2, OnBnClickedButton2) 
END_MESSAGE_MAP() 
 
///////////////////////////////////////////////////////////////////////////// 
// CEatingDlg message handlers 
 
BOOL CEatingDlg::OnInitDialog() 
{ 
	CDialog::OnInitDialog(); 
 
	// Add "About..." menu item to system menu. 
 
	// IDM_ABOUTBOX must be in the system command range. 
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); 
	ASSERT(IDM_ABOUTBOX < 0xF000); 
 
	CMenu* pSysMenu = GetSystemMenu(FALSE);	 
	if (pSysMenu != NULL) 
	{ 
		pSysMenu->EnableMenuItem(SC_CLOSE,MF_BYCOMMAND|MF_DISABLED|MF_GRAYED); 
		CString strAboutMenu; 
		strAboutMenu.LoadString(IDS_ABOUTBOX); 
		if (!strAboutMenu.IsEmpty()) 
		{ 
			pSysMenu->AppendMenu(MF_SEPARATOR); 
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); 
		} 
	} 
 
	// Set the icon for this dialog.  The framework does this automatically 
	//  when the application's main window is not a dialog 
	SetIcon(m_hIcon, TRUE);			// Set big icon 
	SetIcon(m_hIcon, FALSE);		// Set small icon 
	 
	m_Strategy=1; 
	m_Strategy1.SetCheck(1); 
	Clock=0;                         //全局时钟清零 
	InitStruct();                    //初始化结构体 
	m_thinker.m_speed = 20; 
 
	m_wndView.SetThinkersInfo(&m_thinker); 
	m_wndView.SetGradientColor(RGB(0,0,0));	 
	font.CreatePointFont(160,"华文行楷"); 
	m_wndView.SetFont(&font);	 
 
	m_AdjustSpeed.SetRange(0,100); 
	m_AdjustSpeed.SetPos(80); 
	//m_AdjustSpeed.SetTic(10); 
	m_AdjustSpeed.SetTicFreq(200); 
 
	// TODO: Add extra initialization here 
 
	CRect rect; 
	int   i; 
	radius = 160; 
	m_wndView.GetClientRect(&rect); 
	CenterPoint = rect.CenterPoint(); 
 
	 
	for(i = 0;i<5;i++) 
	{ 
		ta5[i] = CPoint(radius*cos((90 + i*72)*3.141526/180), 
						radius*sin((90 + i*72)*3.141526/180)); 
 
		ta5[i].x += CenterPoint.x; 
		ta5[i].y = CenterPoint.y - ta5[i].y; 
	}	 
 
	for(i = 0;i<5;i++) 
	{ 
		tropic5[i] = CPoint((radius-10)*cos((126 + i*72)*3.1415926/180), 
			                 (radius-10)*sin((126 + i*72)*3.1415926/180)); 
 
		tropic5[i].x += CenterPoint.x; 
		tropic5[i].y = CenterPoint.y - tropic5[i].y; 
	} 
	 
	for(i = 0;i<5;i++) 
	{ 
		usetropic[i] = CPoint((radius-10)*cos((90 + i*72)*3.141526/180), 
								(radius-10)*sin((90 + i*72)*3.141526/180));	 
 
		usetropic[i].x += CenterPoint.x; 
		usetropic[i].y = CenterPoint.y - usetropic[i].y;		 
 
	} 
		m_thinker.thinkerRect[0].SetRect(ta5[0].x,ta5[0].y - 60, 
			                             ta5[0].x,ta5[0].y - 60); 
			m_thinker.thinkerRect[0].InflateRect(60,20); 
 
		m_thinker.thinkerRect[1].SetRect(ta5[1].x-85,ta5[1].y, 
										ta5[1].x-85,ta5[1].y); 
			m_thinker.thinkerRect[1].InflateRect(60,20); 
 
		m_thinker.thinkerRect[2].SetRect(ta5[2].x-20,ta5[2].y+50, 
										ta5[2].x-20,ta5[2].y+50); 
			m_thinker.thinkerRect[2].InflateRect(60,20); 
 
		m_thinker.thinkerRect[3].SetRect(ta5[3].x+10,ta5[3].y+50, 
										ta5[3].x+10,ta5[3].y+50); 
			m_thinker.thinkerRect[3].InflateRect(60,20); 
 
		m_thinker.thinkerRect[4].SetRect(ta5[4].x+85,ta5[4].y, 
										ta5[4].x+85,ta5[4].y); 
			m_thinker.thinkerRect[4].InflateRect(60,20); 
			 
		m_stopBtn.EnableWindow(FALSE); 
 
		m_HasInit = TRUE; 
	 
	    m_time=0;   //运行次数与重复删除法相关 
	   for(int k=0;k<5;k++) 
	   { 
	     Total_Think[k]=0; 
	     Total_Eat[k]=0; 
	     Total_Wait[k]=0; 
	   } 
	return TRUE;  // return TRUE  unless you set the focus to a control 
} 
 
void CEatingDlg::OnSysCommand(UINT nID, LPARAM lParam) 
{ 
	if ((nID & 0xFFF0) == IDM_ABOUTBOX) 
	{ 
		CAboutDlg dlgAbout; 
		dlgAbout.DoModal(); 
	} 
	else 
	{ 
		CDialog::OnSysCommand(nID, lParam); 
	} 
} 
 
// If you add a minimize button to your dialog, you will need the code below 
//  to draw the icon.  For MFC applications using the document/view model, 
//  this is automatically done for you by the framework. 
 
void CEatingDlg::OnPaint()  
{ 
	if (IsIconic()) 
	{ 
		CPaintDC dc(this); // device context for painting 
 
		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0); 
 
		// Center icon in client rectangle 
		int cxIcon = GetSystemMetrics(SM_CXICON); 
		int cyIcon = GetSystemMetrics(SM_CYICON); 
		CRect rect; 
		GetClientRect(&rect); 
		int x = (rect.Width() - cxIcon + 1) / 2; 
		int y = (rect.Height() - cyIcon + 1) / 2; 
 
		// Draw the icon 
		dc.DrawIcon(x, y, m_hIcon); 
	} 
	else 
	{ 
		CDialog::OnPaint(); 
	} 
} 
 
// The system calls this to obtain the cursor to display while the user drags 
//  the minimized window. 
HCURSOR CEatingDlg::OnQueryDragIcon() 
{ 
	return (HCURSOR) m_hIcon; 
} 
 
void CEatingDlg::InitStruct() 
{ 
 
		m_thinker.thinkerStatus[0] = THINKING_STATUS; 
		m_thinker.tropics[0] = CreateMutex(NULL,FALSE,NULL);         //初始化MUTEX变量 
		m_thinker.tropicStatus[0] =  1;                             //筷子空闲	 
 
		m_thinker.thinkerStatus[1] = EATING_STATUS; 
		m_thinker.tropics[1] = CreateMutex(NULL,FALSE,NULL);         //初始化MUTEX变量 
		m_thinker.tropicStatus[1] =  1;                             //筷子空闲	 
 
		m_thinker.thinkerStatus[2] = THINKING_STATUS; 
		m_thinker.tropics[2] = CreateMutex(NULL,FALSE,NULL);         //初始化MUTEX变量 
		m_thinker.tropicStatus[2] =  1;                             //筷子空闲	 
 
		m_thinker.thinkerStatus[3] = EATING_STATUS; 
		m_thinker.tropics[3] = CreateMutex(NULL,FALSE,NULL);         //初始化MUTEX变量 
		m_thinker.tropicStatus[3] =  1;                             //筷子空闲	 
 
		m_thinker.thinkerStatus[4] = THINKING_STATUS; 
		m_thinker.tropics[4] = CreateMutex(NULL,FALSE,NULL);         //初始化MUTEX变量 
		m_thinker.tropicStatus[4] = 0;                             //筷子空闲	 
     
 
	m_thinker.m_view     = m_wndView.GetSafeHwnd(); 
	m_thinker.ThinkerCnt = -1; 
	m_thinker.ThreadExit = CreateEvent(NULL,TRUE,FALSE,NULL);    //初始化为没有被使用,可用 
} 
 
int GetRandTime(void) 
{ 
	srand((unsigned)time(NULL)); 
	return rand()%500; 
} 
UINT Eating(PVOID pParam) 
{ 
 
	pThinkers m_ph = (pThinkers)pParam;	 
	int ID = m_ph->ThinkerCnt;    
	while(WaitForSingleObject(m_ph->ThreadExit,0) != WAIT_OBJECT_0) 
	{ 
 
		// Thinking 
		#ifdef DEBUGING 
		TRACE("the %d ID is thinking\n ",ID); 
		#endif 
		//::InvalidateRgn(m_ph->m_view,m_ph->rect,TRUE); 
 
		m_ph->thinkerStatus[ID] = THINKING_STATUS; 
		int  m=GetRandTime(); 
		Sleep(800 + 20*(m_ph->m_speed) + m); 
		 
		//hungry 
		#ifdef DEBUGING 
		TRACE("the %d ID is hungry \n",ID); 
		#endif 
 
		m_ph->thinkerStatus[ID] = HUNGRY_STATUS; 
		::InvalidateRect(m_ph->m_view,m_ph->thinkerRect[ID],TRUE); 
		while(TRUE) 
		{	 
			if(WaitForSingleObject(m_ph->tropics[(ID + THINKER_NUM -1)%THINKER_NUM],60+GetRandTime()) == WAIT_OBJECT_0)  //得到了左边的筷子 
			{				 
				if(WaitForSingleObject(m_ph->tropics[ID],100) != WAIT_OBJECT_0)				 
					ReleaseMutex(m_ph->tropics[(ID + THINKER_NUM -1)%THINKER_NUM]);//如果没有得到右边的筷子,就释放自己获得的左边的筷子,等待 
				else 
					break; 
			} 
			Sleep(600 + 10*(m_ph->m_speed)+GetRandTime()); 
		} 
 
				//begin to eating 
				#ifdef DEBUGING 
				TRACE("the %d ID is eating\n ",ID); 
				#endif 
 
				m_ph->thinkerStatus[ID] = EATING_STATUS; 
				 
				m_ph->tropicStatus[(ID + THINKER_NUM -1)%THINKER_NUM] = 1; 
				m_ph->tropicStatus[ID] = 1; 
 
				::InvalidateRect(m_ph->m_view,m_ph->userect[ID],TRUE); 
				::InvalidateRect(m_ph->m_view,m_ph->Idlerect[ID],TRUE); 
				::InvalidateRect(m_ph->m_view,m_ph->Idlerect[(ID + THINKER_NUM -1)%THINKER_NUM],TRUE); 
				::InvalidateRect(m_ph->m_view,m_ph->thinkerRect[ID],TRUE); 
								 
 
				Sleep(800 +25*(m_ph->m_speed) + GetRandTime()); 
				 
 
				//cast the tropic and continue to think 
					m_ph->thinkerStatus[ID] = THINKING_STATUS; 
				m_ph->tropicStatus[(ID + THINKER_NUM -1)%THINKER_NUM] = 0; 
				m_ph->tropicStatus[ID] = 0; 
				::InvalidateRect(m_ph->m_view,m_ph->userect[ID],TRUE); 
				::InvalidateRect(m_ph->m_view,m_ph->Idlerect[ID],TRUE); 
				::InvalidateRect(m_ph->m_view,m_ph->Idlerect[(ID + THINKER_NUM -1)%THINKER_NUM],TRUE); 
				::InvalidateRect(m_ph->m_view,m_ph->thinkerRect[ID],TRUE); 
				ReleaseMutex(m_ph->tropics[(ID + THINKER_NUM -1)%THINKER_NUM]); 
				ReleaseMutex(m_ph->tropics[ID]); 
				 
				TRACE(" the %d ID is exiting ",ID); 
				 
				 
		}	 
	m_ph->ThinkerCnt--; 
	m_ph->thinkerStatus[ID] = NORMAL_STATUS; 
	::InvalidateRect(m_ph->m_view,m_ph->thinkerRect[ID],TRUE); 
	if(m_ph->ThinkerCnt == -1) 
		ResetEvent(m_ph->ThreadExit); 
	return 1; 
} 
 
void CEatingDlg::OnBtnBegin()  
{ 
	int i; 
	if(!m_HasInit) 
		InitStruct(); 
	m_beginBtn.EnableWindow(FALSE); 
    m_wndView.m_pthinker=&m_thinker; 
	m_wndView.OnPaint(); 
	UpdateData(); 
   //先把所有的时间清零 
   for(i = 0;i0&&p->m_Timem_Time;                           //走动时钟 
		  temp_Cus=p->m_Customer; 
		  temp_Trop=p->Trop; 
		  if(p->AorD==1) 
		  {    
			  Arrial(temp_Cus,temp_Trop,p); 
		  } 
		  else 
		  { 
			  Departure(temp_Cus,temp_Trop,p); 
		  } 
		  Sleep(m_thinker.m_speed*10); 
		 p=(CCalendar*)CA_List.GetAt(0); 
	  } 
	  Statistic(); 
	  m_beginBtn.EnableWindow(TRUE); 
   } 
   else 
   { 
    if(m_Strategy==2) 
	{ 
	  srand( (unsigned)time( NULL ) ); 
      InitList(); 
	  m_time++; 
	  m_Process.ResetContent(); 
	  m_wndView.m_pthinker=&m_thinker; 
	  CCalendar  *p=(CCalendar*)CA_List.GetAt(0);//每次都是取日程表的第一个数 
	  while(CA_List.GetSize()>0&&p->m_Timem_Time;                           //走动时钟 
		  Service(p->m_Customer,p->Trop,p); 
		  Sleep(m_thinker.m_speed*10); 
		 p=(CCalendar*)CA_List.GetAt(0); 
	  } 
	  Statistic(); 
	  m_beginBtn.EnableWindow(TRUE); 
	} 
	else 
	{ 
	   for(i = 0;i0) 
	{ 
	    for(i=0;i<5;i++) 
		{ 
			j=Think[i].GetSize(); 
			t=m_thinker.ThinkTime[i]; 
			t=t/j; 
			j=Eat[i].GetSize(); 
			e=m_thinker.EatTime[i]; 
			e=e/j; 
			j=Wait[i].GetSize(); 
			w=m_thinker.WaitTime[i]; 
			if(j!=0) 
             w=w/j; 
			else 
			  w=0; 
			str.Format("哲学家 %d 平均思考时间 %2d,平均吃饭时间 %2d,平均等待时间 %2d.",i,t,e,w); 
			m_Result.AddString(str); 
		} 
	} 
	else 
	   MessageBox("还没有仿真的数据","错误"); 
} 
 
void CEatingDlg::OnBnClickedOk() 
{ 
	// TODO: 在此添加控件通知处理程序代码 
	OnOK(); 
} 
 
void CEatingDlg::OnBnClickedRadio1() 
{ 
	// TODO: 在此添加控件通知处理程序代码 
	m_Strategy=1; 
} 
 
void CEatingDlg::OnBnClickedRadio2() 
{ 
	// TODO: 在此添加控件通知处理程序代码 
	m_Strategy=2; 
} 
 
void CEatingDlg::OnBnClickedRadio3() 
{ 
	// TODO: 在此添加控件通知处理程序代码 
	m_Strategy=3; 
} 
void   CEatingDlg::InitList() 
{ 
   int temp; 
   for(int i = 0;im_Time=temp; 
			p->m_Customer=i;  //哲学家只能获取相邻的筷子 
			p->AorD=1;        //表示哲学家要获得这个筷子,进入筷子的队列 
			p->Trop=(i-1+THINKER_NUM)%THINKER_NUM;//先获取左边的筷子 
			Add(p); 
			CCalendar  *p1=new CCalendar;//再获右边的       
			p1->m_Time=temp; 
			p1->m_Customer=i;   
			p1->AorD=1;   
			p1->Trop=i;   
            Add(p1); 
		} 
		else 
		{ 
		  if(m_thinker.thinkerStatus[i]==EATING_STATUS)//如果哲学家在吃饭 
		  { 
		    temp=GetEqualTime(); 
			m_thinker.EatTime[i]+=temp; 
			Eat[i].AddTail(temp);   //每次吃饭的时间加入到用餐的列表中,备后面分析使用 
			CCalendar  *p=new CCalendar; 
			p->m_Time=temp; 
			p->m_Customer=i;   
			p->AorD=0;                           //表示哲学家吃完要释放筷子 
			p->Trop=(i-1+THINKER_NUM)%THINKER_NUM;//先释放左边的筷子 
			Add(p); 
			CCalendar  *p1=new CCalendar;//再释放右边的筷子       
			p1->m_Time=temp; 
			p1->m_Customer=i;   
			p1->AorD=0;   
			p1->Trop=i;   
            Add(p1); 
		  } 
		} 
	} 
} 
void  CEatingDlg::Add(CCalendar *p)//按照时间顺序添加到日程表中 
{ 
	CCalendar  *ptemp; 
	CA_List.Add((CCalendar*)p); 
	int m_Size=CA_List.GetSize(); 
	int i; 
	for(i=m_Size-1;i>0;i--) 
	{ 
		ptemp=(CCalendar*)CA_List.GetAt(i-1); 
		if(ptemp->m_Time>p->m_Time) 
		{ 
			CA_List.SetAt(i,(CCalendar*)ptemp); 
		} 
		else 
		{ 
			CA_List.SetAt(i,(CCalendar*)p); 
		    break; 
		} 
	} 
	if(i==0) 
     CA_List.SetAt(i,(CCalendar*)p); 
} 
void  CEatingDlg::Arrial(int i,int j,CCalendar *p) 
{ 
   CString str;//在进度栏里加入事件 
   if(m_thinker.tropicStatus[j]==0) //如果筷子是空闲的 
   { 
	   m_thinker.HaveTrop[i]++; 
	   if(m_thinker.HaveTrop[i]==2) 
	   { 
	      int temp=GetEqualTime();//吃饭时间服从均匀分布 
		  m_thinker.EatTime[i]+=temp; 
		  Eat[i].AddTail(temp);   //每次吃饭的时间加入到用餐的列表中,备后面分析使用 
		  m_thinker.thinkerStatus[i]=EATING_STATUS; 
		  m_thinker.tropicStatus[j]=1;//筷子不再是空闲的 
          //开始吃饭意味着等待就结束 
		  int temp1; 
          if(m_thinker.WaitBegin[i]!=0)   
		  { 
			  temp1=p->m_Time-m_thinker.WaitBegin[i]; 
			  m_thinker.WaitTime[i]+=temp1; 
			  Wait[i].AddTail(temp1);   // 每次等待的时间加入到等待列表中,备后面分析使用 
              m_thinker.WaitBegin[i]=0 ;//重新回到初值 
		  } 
		  str.Format("时刻: %4d 哲学家 %d 获取筷子 %d 成功,开始吃饭!",p->m_Time,p->m_Customer,p->Trop); 
		  m_Process.InsertString(0,str); 
		  m_Process.RedrawWindow(NULL,NULL,RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE); 
          ::InvalidateRect(m_thinker.m_view,m_thinker.userect[i],TRUE); 
		  ::InvalidateRect(m_thinker.m_view,m_thinker.Idlerect[i],TRUE); 
		  ::InvalidateRect(m_thinker.m_view,m_thinker.Idlerect[(i + THINKER_NUM -1)%THINKER_NUM],TRUE); 
		  ::InvalidateRect(m_thinker.m_view,m_thinker.thinkerRect[i],TRUE); 
		  m_wndView.OnPaint(); 
		  CCalendar *p1=new CCalendar;  //吃完饭要调度释放筷子的事件 
		  p1->m_Time=p->m_Time+temp; 
		  p1->m_Customer=i; 
		  p1->Trop=(i-1+THINKER_NUM)%THINKER_NUM; 
		  p1->AorD=0; 
		  Add(p1); 
 
		  CCalendar *p2=new CCalendar;  //右边的 
		  p2->m_Time=p->m_Time+temp; 
		  p2->m_Customer=i; 
		  p2->Trop=i; 
		  p2->AorD=0; 
		  Add(p2); 
	   } 
	   else 
	   {   
          int  l; 
	      if(p->m_Customer==j) 
			  l=(p->m_Customer+4)%5; 
		  else 
			  l=p->m_Customer; 
		  m_thinker.tropicStatus[j]=1;//筷子不再是空闲的 
          if(m_thinker.WaitBegin[i]==0)     //如果还没有等待的话在这个时刻开始等待 
		      m_thinker.WaitBegin[i]=p->m_Time;  
	      str.Format("时刻: %4d 哲学家 %d 获取筷子 %d 成功,等待筷子 %d",p->m_Time,p->m_Customer,p->Trop,l); 
		  m_Process.InsertString(0,str); 
		  m_Process.RedrawWindow(NULL,NULL,RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE); 
		  m_thinker.thinkerStatus[i]=HUNGRY_STATUS; 
		  ::InvalidateRect(m_thinker.m_view,m_thinker.thinkerRect[i],TRUE); 
		  m_wndView.OnPaint(); 
	   } 
	   
   } 
   else 
   { 
	   if(m_thinker.WaitBegin[i]==0)   //如果还没有等待的话在这个时刻开始等待 
		      m_thinker.WaitBegin[i]=p->m_Time;  
	   str.Format("时刻: %4d 哲学家 %d 获取筷子 %d 不成功,开始等待筷子 %d",p->m_Time,p->m_Customer,p->Trop,p->Trop); 
	   m_Process.InsertString(0,str); 
	   m_Process.RedrawWindow(NULL,NULL,RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE); 
	   m_thinker.thinkerStatus[i]=HUNGRY_STATUS; 
	   ::InvalidateRect(m_thinker.m_view,m_thinker.thinkerRect[i],TRUE); 
	   m_wndView.OnPaint(); 
	   m_thinker.WaitQueue[j][m_thinker.HaveCur[j]]=i; 
	   m_thinker.HaveCur[j]++;//代表等待队列的长度 
   } 
} 
void  CEatingDlg::Departure(int i,int j,CCalendar *p) 
{ 
 
	m_thinker.tropicStatus[j]=0;  //释放筷子资源 
	 if(m_thinker.WaitQueue[j][0]>=0)  //如果有哲学家在等待这个筷子,那么调度这个哲学家来取 
	 { 
		  CCalendar *p2=new CCalendar;  //加进日程表给等待的哲学家 
	      p2->m_Time=p->m_Time; 
	      p2->m_Customer=m_thinker.WaitQueue[j][0]; 
	      p2->Trop=j; 
	      p2->AorD=1; 
	      Add(p2); 
		  if(m_thinker.HaveCur[j]==2) 
		  { 
			  m_thinker.WaitQueue[j][0]=m_thinker.WaitQueue[j][1]; 
		  } 
		  else 
			  m_thinker.WaitQueue[j][0]=-1;  //恢复初始值 
		  m_thinker.HaveCur[j]--; 
	 } 
     int temp=GetNormalTime();  //思考时间服从正态分布 
	 m_thinker.ThinkTime[i]+=temp; 
	 Think[i].AddTail(temp);   //每次思考的时间进入列表,备后面分析使用 
     m_thinker.thinkerStatus[i]=THINKING_STATUS; 
    ::InvalidateRect(m_thinker.m_view,m_thinker.userect[i],TRUE); 
	::InvalidateRect(m_thinker.m_view,m_thinker.Idlerect[i],TRUE); 
	::InvalidateRect(m_thinker.m_view,m_thinker.Idlerect[(i + THINKER_NUM -1)%THINKER_NUM],TRUE); 
	::InvalidateRect(m_thinker.m_view,m_thinker.thinkerRect[i],TRUE); 
	 m_wndView.OnPaint(); 
	 m_thinker.HaveTrop[i]--; 
     m_thinker.HaveFree[i]++; 
	 if(m_thinker.HaveFree[i]==2)//当两个都释放后 
	 { 
	    CCalendar *p1=new CCalendar;//调度下次i再来要j的时间,也就是思考完的时间 
 	    p1->m_Time=p->m_Time+temp; 
	    p1->m_Customer=i; 
	    p1->Trop=(i-1+THINKER_NUM)%THINKER_NUM; 
	    p1->AorD=1; 
	    Add(p1); 
	      
		CCalendar  *p3=new CCalendar;//再获右边的       
		p3->m_Time=p->m_Time+temp; 
		p3->m_Customer=i; 
	    p3->Trop=i; 
		p3->AorD=1;     
		Add(p3); 
	    m_thinker.HaveFree[i]=0;//复原已释放的资源数目 
	 } 
 
	 CString str;//在进度栏里加入事件 
	 if(m_thinker.HaveTrop[i]==0) 
	      str.Format("时刻: %4d 哲学家 %d 释放筷子 %d 开始思考!",p->m_Time,p->m_Customer,p->Trop); 
	 else 
		  str.Format("时刻: %4d 哲学家 %d 释放筷子 %d.",p->m_Time,p->m_Customer,p->Trop); 
     m_Process.InsertString(0,str); 
	 m_Process.RedrawWindow(NULL,NULL,RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE); 
	 
} 
void  CEatingDlg::Arrial2(int i,int j,CCalendar *p) 
{ 
     int temp=GetNormalTime();  //思考时间服从正态分布 
	 m_thinker.ThinkTime[i]+=temp; 
	 Think[i].AddTail(temp);   //每次思考的时间进入列表,备后面分析使用 
     m_thinker.thinkerStatus[i]=THINKING_STATUS; 
	 m_thinker.tropicStatus[j]=0;//释放完后筷子变为空闲 
    ::InvalidateRect(m_thinker.m_view,m_thinker.userect[i],TRUE); 
	::InvalidateRect(m_thinker.m_view,m_thinker.Idlerect[i],TRUE); 
	::InvalidateRect(m_thinker.m_view,m_thinker.Idlerect[(i + THINKER_NUM -1)%THINKER_NUM],TRUE); 
	::InvalidateRect(m_thinker.m_view,m_thinker.thinkerRect[i],TRUE); 
	 m_wndView.OnPaint(); 
	 m_thinker.HaveTrop[i]--; //拥有的筷子数减一 
      m_thinker.HaveFree[i]++; 
	 if(m_thinker.HaveFree[i]==2)//当两个都释放后 
	 { 
	    CCalendar *p1=new CCalendar;//调度下次i再来要j的时间,也就是思考完的时间 
 	    p1->m_Time=p->m_Time+temp; 
	    p1->m_Customer=i; 
	    p1->Trop=(i-1+THINKER_NUM)%THINKER_NUM; 
	    p1->AorD=1; 
	    Add(p1); 
	      
		CCalendar  *p3=new CCalendar;//再获右边的       
		p3->m_Time=p->m_Time+temp; 
		p3->m_Customer=i; 
	    p3->Trop=i; 
		p3->AorD=1;     
		Add(p3); 
	    m_thinker.HaveFree[i]=0;//复原已释放的资源数目 
	 } 
	  CString str;//在进度栏里加入事件 
	 if(m_thinker.HaveTrop[i]==0) 
	      str.Format("时刻: %4d 哲学家 %d 释放筷子 %d 开始思考!",p->m_Time,p->m_Customer,p->Trop); 
	 else 
		  str.Format("时刻: %4d 哲学家 %d 释放筷子 %d.",p->m_Time,p->m_Customer,p->Trop); 
     m_Process.InsertString(0,str); 
	 m_Process.RedrawWindow(NULL,NULL,RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE); 
} 
void  CEatingDlg::Departure2(int i,int j,CCalendar *p) 
{ 
	      CString  str; 
	      int temp=GetEqualTime();//吃饭时间服从均匀分布 
		  m_thinker.EatTime[i]+=temp; 
		  Eat[i].AddTail(temp);   //每次吃饭的时间加入到用餐的列表中,备后面分析使用 
		  m_thinker.thinkerStatus[i]=EATING_STATUS; 
		  m_thinker.tropicStatus[j]=1;//筷子不再是空闲的 
          //开始吃饭意味着等待就结束 
		  int temp1; 
          if(m_thinker.WaitBegin[i]!=0)   
		  { 
			  temp1=p->m_Time-m_thinker.WaitBegin[i]; 
			  m_thinker.WaitTime[i]+=temp1; 
			  Wait[i].AddTail(temp1);   // 每次等待的时间加入到等待列表中,备后面分析使用 
              m_thinker.WaitBegin[i]=0 ;//重新回到初值 
		  } 
		  str.Format("时刻: %4d 哲学家 %d 获取筷子 %d 成功,开始吃饭!",p->m_Time,p->m_Customer,p->Trop); 
		  m_Process.InsertString(0,str); 
		  m_Process.RedrawWindow(NULL,NULL,RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE); 
          ::InvalidateRect(m_thinker.m_view,m_thinker.userect[i],TRUE); 
		  ::InvalidateRect(m_thinker.m_view,m_thinker.Idlerect[i],TRUE); 
		  ::InvalidateRect(m_thinker.m_view,m_thinker.Idlerect[(i + THINKER_NUM -1)%THINKER_NUM],TRUE); 
		  ::InvalidateRect(m_thinker.m_view,m_thinker.thinkerRect[i],TRUE); 
		  m_wndView.OnPaint(); 
		  CCalendar *p1=new CCalendar;  //吃完饭要调度释放筷子的事件 
		  p1->m_Time=p->m_Time+temp; 
		  p1->m_Customer=i; 
		  p1->Trop=(i-1+THINKER_NUM)%THINKER_NUM; 
		  p1->AorD=0; 
		  Add(p1); 
 
		  CCalendar *p2=new CCalendar;  //右边的 
		  p2->m_Time=p->m_Time+temp; 
		  p2->m_Customer=i; 
		  p2->Trop=i; 
		  p2->AorD=0; 
		  Add(p2); 
} 
void  CEatingDlg::Service(int i,int j,CCalendar *p) 
{ 
	int  que; 
	CString str; 
	if(p->AorD)  //判断哲学家是取筷子用餐还是用完餐释放筷子 
	{ 
	    if((m_thinker.tropicStatus[j]==0)&&(m_thinker.WaitQueue[j][0]>=0))//如果j空闲且它的排队不空 
		{ 
		     que=m_thinker.WaitQueue[j][0];  //取出排在前面的哲学家 
		 
			 if(m_thinker.HaveCur[j]==2)     //如果有两个哲学家在等待j 
			 { 
			    m_thinker.WaitQueue[j][0]=m_thinker.WaitQueue[j][1];//移出第一个哲学家 
				m_thinker.WaitQueue[j][1]=-1; 
			 } 
			 else 
			 { 
			   m_thinker.WaitQueue[j][0]=-1;  //如果只有一个哲学家在等待,就移出这个哲学家 
			 } 
			 m_thinker.HaveCur[j]--;   
			 
			 m_thinker.HaveTrop[que]++;    //如果que这个哲学家已经获得两个筷子了就调动departure 
			if(m_thinker.HaveTrop[que]==2) 
			{ 
				Departure2(que,j,p); 
			} 
			else 
			{ 
			       int  l; 
	               if(que==j) 
			          l=(que+4)%5; 
		           else 
			          l=que; 
                  if(m_thinker.WaitBegin[que]==0)     //如果还没有等待的话在这个时刻开始等待 
		              m_thinker.WaitBegin[que]=p->m_Time;  
	               str.Format("时刻: %4d 哲学家 %d 获取筷子 %d 成功,等待筷子 %d",p->m_Time,que,j,l); 
	               m_Process.InsertString(0,str); 
	               m_Process.RedrawWindow(NULL,NULL,RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE); 
	               m_thinker.thinkerStatus[que]=HUNGRY_STATUS; 
	               ::InvalidateRect(m_thinker.m_view,m_thinker.thinkerRect[que],TRUE); 
	               m_wndView.OnPaint(); 
			} 
		} 
		else 
		{ 
            if(m_thinker.tropicStatus[j]==0)  //如果筷子是空闲的 
			{ 
			   m_thinker.HaveTrop[i]++; 
			   if(m_thinker.HaveTrop[i]==2) 
			   { 
				   Departure2(i,j,p); 
			   } 
			   else 
			   { 
				   int  l; 
	               if(p->m_Customer==j) 
			          l=(p->m_Customer+4)%5; 
		           else 
			          l=p->m_Customer; 
                  if(m_thinker.WaitBegin[i]==0)     //如果还没有等待的话在这个时刻开始等待 
		              m_thinker.WaitBegin[i]=p->m_Time;  
	               str.Format("时刻: %4d 哲学家 %d 获取筷子 %d 成功,等待筷子 %d",p->m_Time,p->m_Customer,p->Trop,l); 
		           m_Process.InsertString(0,str); 
		           m_Process.RedrawWindow(NULL,NULL,RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE); 
		           m_thinker.thinkerStatus[i]=HUNGRY_STATUS; 
		           ::InvalidateRect(m_thinker.m_view,m_thinker.thinkerRect[i],TRUE); 
		           m_wndView.OnPaint(); 
				   m_thinker.tropicStatus[j]=1;//筷子不再是空闲的 
			   } 
           
			} 
			else   //表明筷子不空而它的等待队列是空的 
			{ 
			   if(m_thinker.WaitBegin[i]==0)   //如果还没有等待的话在这个时刻开始等待 
		               m_thinker.WaitBegin[i]=p->m_Time;  
	           str.Format("时刻: %4d 哲学家 %d 获取筷子 %d 不成功,开始等待筷子 %d",p->m_Time,p->m_Customer,p->Trop,p->Trop); 
	           m_Process.InsertString(0,str); 
	           m_Process.RedrawWindow(NULL,NULL,RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE); 
	           m_thinker.thinkerStatus[i]=HUNGRY_STATUS; 
	           ::InvalidateRect(m_thinker.m_view,m_thinker.thinkerRect[i],TRUE); 
	           m_wndView.OnPaint(); 
			   m_thinker.WaitQueue[j][m_thinker.HaveCur[j]]=i; 
	           m_thinker.HaveCur[j]++;//代表等待队列的长度      
			} 
		} 
	} 
	else  //表明哲学家是用完餐释放筷子 
	{ 
	    if((m_thinker.WaitQueue[j][0]>=0)) //如果筷子的等待队列不是空的 
		{ 
		       CCalendar *p2=new CCalendar;  //加进日程表给等待的哲学家 
	           p2->m_Time=p->m_Time; 
	           p2->m_Customer=m_thinker.WaitQueue[j][0]; 
	           p2->Trop=j; 
	           p2->AorD=1; 
	           Add(p2); 
		       if(m_thinker.HaveCur[j]==2) 
		       { 
			       m_thinker.WaitQueue[j][0]=m_thinker.WaitQueue[j][1]; 
		       } 
		       else 
			       m_thinker.WaitQueue[j][0]=-1;  //恢复初始值 
		       m_thinker.HaveCur[j]--; 
		} 
		else 
		{ 
		   m_thinker.tropicStatus[j]=0;//i释放了j,j空闲 
		} 
		Arrial2(i,j,p); 
	} 
} 
int CEatingDlg::GetNormalTime() 
{ 
	  float m_u1,m_u2,m_x1; 
	  m_u1=(float)rand()/0x7fff; 
	  m_u1=(float)rand()/0x7fff; 
	  m_u2=(float)rand()/0x7fff; 
	 
	 
	 float v1=2*m_u1-1; 
	 float v2=2*m_u2-1; 
     float W=v1*v1+v2*v2; 
	 if(W<1) 
	 { 
	    m_x1=v1*sqrt(((-2)*log(W))/W); 
	    m_x1=10+m_x1*sqrt((double)8); 
		return  (int)m_x1; 
	 } 
	 else 
		 return 10; 
} 
int CEatingDlg::GetEqualTime() 
{ 
	 int  m; 
	 m=rand()%11; 
	 m=m+15; 
	 return m; 
} 
 
 
void CEatingDlg::OnBnClickedButton2() 
{ 
	// TODO: 在此添加控件通知处理程序代码 
	CString str; 
	int  t,e,w; 
	if(m_time>0) 
	{ 
		m_Result.ResetContent(); 
		str.Format("共进行了 %d 次仿真:",m_time); 
		m_Result.AddString(str); 
        for(int i=0;i<5;i++) 
		{ 
		   t=Total_Think[i]/m_time; 
		   e=Total_Eat[i]/m_time; 
		   w=Total_Wait[i]/m_time; 
		   str.Format("哲学家 %d 平均思考时间 %2d,平均吃饭时间 %2d,平均等待时间 %2d.",i,t,e,w); 
		   m_Result.AddString(str); 
		} 
	} 
	else 
		MessageBox("没有仿真数据","错误"); 
} 
void  CEatingDlg::Statistic() 
{ 
	    int i,j,t,e,w; 
        for(i=0;i<5;i++) 
		{ 
			j=Think[i].GetSize(); 
			t=m_thinker.ThinkTime[i]; 
			if(j!=0) 
			  t=t/j; 
			else 
			  t=0; 
			Total_Think[i]+=t; 
		 
			j=Eat[i].GetSize(); 
			e=m_thinker.EatTime[i]; 
			if(j!=0) 
			  e=e/j; 
			else 
			  e=0; 
			Total_Eat[i]+=e; 
		 
			j=Wait[i].GetSize(); 
			w=m_thinker.WaitTime[i]; 
			if(j!=0) 
             w=w/j; 
			else 
			 w=0; 
			Total_Wait[i]+=w; 
			 
		} 
}