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

📄 hanoitowerview.cpp

📁 汉诺塔的实现
💻 CPP
📖 第 1 页 / 共 2 页
字号:
		m_nIsStart=0;
		m_nIsReset=0;
		m_nIsPause=0;
	}
	else
	{
		//恢复初始状态
		//清除链表
		pDoc->m_DiscStepList.RemoveAll();
		
		//重新初始化m_pDisc和Tower
		delete[] m_pDisc;          //释放原Disc堆栈内存
		m_pDisc=NULL;              
		pDoc->m_pDisc=NULL;

		pDoc->InitializeDisc();    //重新分配空间,并初始化Disc对象数组
		pDoc->InitializeTower();
		pDoc->AutoPlay();

		m_pDisc=pDoc->m_pDisc;
    
		//取消演示标志位
		m_nIsStart=0;
		m_nIsReset=0;
		m_nIsPause=0;
	}

	//重画初始屏幕
	Invalidate();


	
}

void CHanoiTowerView::OnRunReset() 
{
	// TODO: Add your command handler code here
		m_nIsReset=1;
		m_nIsStart=0;
}

void CHanoiTowerView::OnRunPause() 
{
	// TODO: Add your command handler code here
	if(m_nIsStart==1)
	{
		m_nIsStart=0;
		m_nIsPause=1;

	}

}

void CHanoiTowerView::OnTimer(UINT nIDEvent) 
{
	// TODO: Add your message handler code here and/or call default
	
	m_bTimeUp=TRUE;

	//CView::OnTimer(nIDEvent);
}



void CHanoiTowerView::OnUpdateRunStart(CCmdUI* pCmdUI) 
{
	// TODO: Add your command update UI handler code here
    pCmdUI->Enable(!m_nIsStart && !m_nIsAuto);
	
}

void CHanoiTowerView::OnUpdateRunSetup(CCmdUI* pCmdUI) 
{
	// TODO: Add your command update UI handler code here
	pCmdUI->Enable(!m_nIsStart);


	
}

void CHanoiTowerView::OnUpdateRunReset(CCmdUI* pCmdUI) 
{
	// TODO: Add your command update UI handler code here
	pCmdUI->Enable(m_nIsStart);
}

void CHanoiTowerView::OnUpdateRunPause(CCmdUI* pCmdUI) 
{
	// TODO: Add your command update UI handler code here
	pCmdUI->Enable(m_nIsStart);
}

void CHanoiTowerView::DrawArrow(CHanoiTowerDoc *pDoc, CDC *pDC)
{
      int olddc=pDC->SaveDC();
	  	  
	  CBrush brush;
      brush.CreateSolidBrush(RGB(0,0,255));

	   
	  TRACE("xold=%d, yold=%d, ArrowPos=%d \n", m_pointArrow.x, m_pointArrow.y, m_nArrowPos);

   	  //计算箭头初始位置
	  m_pointArrow=GetArrowPoint(m_nArrowPos);

	  TRACE("xnew=%d, ynew=%d, ArrowPos=%d \n\n", m_pointArrow.x, m_pointArrow.y, m_nArrowPos);

	  //开始画箭头
	  CPoint pvPoint[7];
	  
	  pvPoint[0].x=m_pointArrow.x;
	  pvPoint[0].y=m_pointArrow.y;

	  pvPoint[1].x=m_pointArrow.x-20;
	  pvPoint[1].y=m_pointArrow.y+30;

	  pvPoint[2].x=m_pointArrow.x-10;
	  pvPoint[2].y=m_pointArrow.y+30;

	  pvPoint[3].x=m_pointArrow.x-10;
	  pvPoint[3].y=m_pointArrow.y+80;
	  
	  pvPoint[4].x=m_pointArrow.x+10;
	  pvPoint[4].y=m_pointArrow.y+80;

	  pvPoint[5].x=m_pointArrow.x+10;
	  pvPoint[5].y=m_pointArrow.y+30;

	  pvPoint[6].x=m_pointArrow.x+20;
	  pvPoint[6].y=m_pointArrow.y+30;

	  CRgn rgnArrow;
	  rgnArrow.CreatePolygonRgn(pvPoint,7, ALTERNATE);

	  pDC->FillRgn(&rgnArrow, &brush);

	  pDC->RestoreDC(olddc);

}

void CHanoiTowerView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 
{
	CHanoiTowerDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	
	CClientDC dc(this);
    OnPrepareDC(&dc);
	
	// TODO: Add your message handler code here and/or call default
	CRect  tempRect;
	int oldArrowPos;
	int newArrowPos;

	switch(nChar)
	{
	case VK_LEFT:
		{	
			oldArrowPos=m_nArrowPos;
			newArrowPos=m_nArrowPos-1;
			newArrowPos=(newArrowPos==0)?3:newArrowPos;
			
			if(MoveAble(oldArrowPos, newArrowPos))
			{
				
				m_nArrowPos=newArrowPos;
				if(m_bIsCapDisc)
				{
					MoveDisc(m_nCapDiscNum, oldArrowPos, m_nArrowPos);
				}
			}
			

			break; 
				
		}
	case VK_RIGHT:
		{	
			oldArrowPos=m_nArrowPos;
			newArrowPos=(m_nArrowPos)%3+1;
			
			if( MoveAble(oldArrowPos, newArrowPos) )
			{
				m_nArrowPos=newArrowPos;
				
				if(m_bIsCapDisc)
				{
					MoveDisc(m_nCapDiscNum, oldArrowPos, m_nArrowPos);
				}

			}
			

			break;

		}
	case VK_SPACE:
		{
		    if(m_bIsCapDisc)
			{	
			   m_bIsCapDisc=FALSE;
			   
			   (m_pDisc+m_nCapDiscNum-1)->m_DiscColor=pDoc->GetColor(m_nCapDiscNum);
			   
			   //重画disc
			   tempRect.CopyRect((m_pDisc+m_nCapDiscNum-1)->GetDisc());
			   dc.LPtoDP(&tempRect);

     		   InvalidateRect(tempRect);

			   //锁定disc取消
			   m_nCapDiscNum=NULL;

		

			}
			else
			{
				m_bIsCapDisc=TRUE;
				
				if(m_nArrowPos==1)
				{
				
					if(m_TowerA.m_nTopDiscSerialNum>0)
					{	
						m_nCapDiscNum=m_TowerA.m_nTopDiscSerialNum;
						(m_pDisc+m_nCapDiscNum-1)->m_DiscColor=RGB(255,255,255);
					}
				}
				else if(m_nArrowPos==2)
				{
					
				    if(m_TowerB.m_nTopDiscSerialNum>0)
					{   
						m_nCapDiscNum=m_TowerB.m_nTopDiscSerialNum;
						(m_pDisc+m_nCapDiscNum-1)->m_DiscColor=RGB(255,255,255);
					}
					
				}
				else if(m_nArrowPos==3)
				{
					
				    if(m_TowerC.m_nTopDiscSerialNum>0)
					{
						m_nCapDiscNum=m_TowerC.m_nTopDiscSerialNum;
						(m_pDisc+m_nCapDiscNum-1)->m_DiscColor=RGB(255,255,255);
					}
				}
				
				tempRect.CopyRect((m_pDisc+m_nCapDiscNum-1)->GetDisc());
				dc.LPtoDP(&tempRect);

				InvalidateRect(tempRect);
		
			}

			break;
		}
	default:
		{
			return;
			break;
		}

	}


    CRect rectNewArrow;
	CRect rectOldArrow;
	
	//计算原箭头矩形
	rectOldArrow.SetRect(m_pointArrow.x-155, m_pointArrow.y+80,
		              m_pointArrow.x+155, m_pointArrow.y-30);
	dc.LPtoDP(rectOldArrow);
	InvalidateRect(rectOldArrow);

	//获得新箭头位置
	m_pointArrow=GetArrowPoint(m_nArrowPos);
	
	//计算新箭头矩形
	rectNewArrow.SetRect(m_pointArrow.x-155, m_pointArrow.y+80,
		              m_pointArrow.x+155, m_pointArrow.y-30);

	dc.LPtoDP(rectNewArrow);
	InvalidateRect(rectNewArrow);


    CView::OnKeyDown(nChar, nRepCnt, nFlags);
}



CPoint CHanoiTowerView::GetArrowPoint(int nArrowPos)
{
	  CPoint pointArrow;
	  
	  TRACE("this is getarrowpoint: Arrowpos=%d\n", nArrowPos);
	  
	  //根据箭头当前所在塔确定箭头位置
	  switch(m_nArrowPos)
	  {
		case 1:
			{
			    TRACE("this is getarrowpoint: TowerA.totaldiscNum=%d\n", m_TowerA.m_nTotalDiscNum);

				pointArrow.x=m_TowerA.m_pointCenter.x;
				pointArrow.y=m_TowerA.m_pointCenter.y + m_TowerA.m_nTotalDiscNum*30+30;
				break;
			}
		case 2:
			{
			    TRACE("this is getarrowpoint: TowerB.totaldiscNum=%d\n", m_TowerB.m_nTotalDiscNum);

				pointArrow.x=m_TowerB.m_pointCenter.x;
				pointArrow.y=m_TowerB.m_pointCenter.y + m_TowerB.m_nTotalDiscNum*30+30;
				break;
			}
		case 3:
			{
			    TRACE("this is getarrowpoint: TowerC.totaldiscNum=%d\n", m_TowerC.m_nTotalDiscNum);

				pointArrow.x=m_TowerC.m_pointCenter.x;
				pointArrow.y=m_TowerC.m_pointCenter.y + m_TowerC.m_nTotalDiscNum*30+30;
				break;
			}
		default:
			{
				AfxMessageBox("箭头位置参数错误",NULL);
				break;
			}
	  }

	  return pointArrow;

	  

}



void CHanoiTowerView::MoveDisc(int CapDiscNum, 
							   int SorTower, 
							   int DesTower)
{
	Disc *pMoveDisc;               
	Tower *FromTower;
	Tower *ToTower;

	if(CapDiscNum!=0)
	{
		//获得当前搬运的disc序号
		pMoveDisc=m_pDisc+CapDiscNum-1;

		//获得原塔和目标塔
		FromTower=WhichTower(SorTower);
		ToTower=WhichTower(DesTower);

		//移动Disc并修改相关数据成员
		FromTower->m_nTotalDiscNum--;      //源塔中disc总数减一
		ToTower->m_nTotalDiscNum++;        //目标塔中disc总数加一      

		ToTower->m_nTopDiscSerialNum=pMoveDisc->m_nDiscSerialNum;   //目标塔顶层disc序号改为当前搬运的disc序号
		if(FromTower->m_nTotalDiscNum==0) {FromTower->m_nTopDiscSerialNum=0;}

		//遍历所有disc,将原目标塔上的disc的所在层加一;
		//将源塔上的所有disc所在层减一
		//被移动的disc,目前还在原塔,但是其所在层已经由1变为0
		//这不影响,下一步就是修改被移动disc的属性。
		for(int i=0; i<m_nDiscNum; i++)
		{
			if( (m_pDisc+i)->m_nDiscCurrentTower==FromTower->m_nTowerSerialNum )
			{
				(m_pDisc+i)->m_nDiscCurrentLayer--;
				
				if((m_pDisc+i)->m_nDiscCurrentLayer==1)
				{
					FromTower->m_nTopDiscSerialNum=(i+1);
				}

			}
			else if((m_pDisc+i)->m_nDiscCurrentTower==ToTower->m_nTowerSerialNum )
			{
				(m_pDisc+i)->m_nDiscCurrentLayer++;
			}
		}

		//修改被移动disc的属性
		pMoveDisc->m_nDiscCurrentLayer=1;
		pMoveDisc->m_nDiscCurrentTower=ToTower->m_nTowerSerialNum;
		//重新获得disc的重点位置
		pMoveDisc->SetCerterBottomPoint(*ToTower);
	}


}

Tower* CHanoiTowerView::WhichTower(int TowerNum)
{
	//根据塔序号,返回相应Tower类对象
	if(TowerNum==1)
	{
		return &m_TowerA;
	}
	else if(TowerNum==2)
	{
		return &m_TowerB;
	}
	else
	{
		return &m_TowerC;
	}
}

bool CHanoiTowerView::MoveAble(int oldArrowPos, int newArrowPos)
{	
	Tower *FromTower;
	Tower *ToTower;

	FromTower=WhichTower(oldArrowPos);
	ToTower=WhichTower(newArrowPos);

	//如果有碟子被选中	
	if(m_bIsCapDisc)
	{
		//如果目标塔顶碟子序号小于当前选定碟子序号,不可移动,返回
		if(m_nCapDiscNum<ToTower->m_nTopDiscSerialNum || ToTower->m_nTopDiscSerialNum==0 )
		{
			return TRUE;
		}
	}
	else
	{
		return TRUE;
	}

	return FALSE;


}

bool CHanoiTowerView::IsFinishGame()
{
	int count=0;
	
	//如果所有碟子都在TowerC上,游戏结束
	for(int i=0; i<m_nDiscNum; i++)
	{
		if( (m_pDisc+i)->m_nDiscCurrentTower==3 )
		{
			count++;
		}
	}

	if(count==m_nDiscNum)
	{
		return TRUE;
	}
	else
	{
		return FALSE;
	}
}



void CHanoiTowerView::OnUpdateFileSave(CCmdUI* pCmdUI) 
{
	// TODO: Add your command update UI handler code here
			
	pCmdUI->Enable(!m_nIsAuto);

}

void CHanoiTowerView::OnUpdateFileSaveAs(CCmdUI* pCmdUI) 
{
	// TODO: Add your command update UI handler code here
			
	pCmdUI->Enable(!m_nIsAuto );
}





void CHanoiTowerView::OnBarPause() 
{
	// TODO: Add your command handler code here
   if(!m_nIsAuto)
   {
	
	   OnRunPause();
   }
   else
   {
	   AfxMessageBox("手动游戏模式下不能使用此功能",NULL);
   }


}

void CHanoiTowerView::OnBarReset() 
{
	// TODO: Add your command handler code here
	OnRunSetup();

}

void CHanoiTowerView::OnBarStart() 
{
	// TODO: Add your command handler code here
	   if(!m_nIsAuto)
   {
		OnRunStart();

   }
   else
   {
	   AfxMessageBox("手动游戏模式下不能使用此功能",NULL);
   }

}

void CHanoiTowerView::OnBarStop() 
{
	// TODO: Add your command handler code here
   if(!m_nIsAuto)
   {
	OnRunReset();

   }
   else
   {
	   AfxMessageBox("手动游戏模式下不能使用此功能",NULL);
   }

}

⌨️ 快捷键说明

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