📄 hanoitowerview.cpp
字号:
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 + -