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

📄 hanoitowerview.cpp

📁 汉诺塔的实现
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// HanoiTowerView.cpp : implementation of the CHanoiTowerView class
//

#include "stdafx.h"
#include "HanoiTower.h"

#include "HanoiTowerDoc.h"
#include "HanoiTowerView.h"

#include "Tower.h"
#include "ParaDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CHanoiTowerView

IMPLEMENT_DYNCREATE(CHanoiTowerView, CView)

BEGIN_MESSAGE_MAP(CHanoiTowerView, CView)
	//{{AFX_MSG_MAP(CHanoiTowerView)
	ON_COMMAND(ID_RUN_SETUP, OnRunSetup)
	ON_COMMAND(ID_RUN_START, OnRunStart)
	ON_COMMAND(ID_RUN_RESET, OnRunReset)
	ON_COMMAND(ID_RUN_PAUSE, OnRunPause)
	ON_WM_TIMER()
	ON_UPDATE_COMMAND_UI(ID_RUN_START, OnUpdateRunStart)
	ON_UPDATE_COMMAND_UI(ID_RUN_SETUP, OnUpdateRunSetup)
	ON_UPDATE_COMMAND_UI(ID_RUN_RESET, OnUpdateRunReset)
	ON_UPDATE_COMMAND_UI(ID_RUN_PAUSE, OnUpdateRunPause)
	ON_WM_KEYDOWN()
	ON_UPDATE_COMMAND_UI(ID_FILE_SAVE, OnUpdateFileSave)
	ON_UPDATE_COMMAND_UI(ID_FILE_SAVE_AS, OnUpdateFileSaveAs)
	ON_COMMAND(ID_BAR_PAUSE, OnBarPause)
	ON_COMMAND(ID_BAR_RESET, OnBarReset)
	ON_COMMAND(ID_BAR_START, OnBarStart)
	ON_COMMAND(ID_BAR_STOP, OnBarStop)
	//}}AFX_MSG_MAP
	// Standard printing commands
	ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CHanoiTowerView construction/destruction

CHanoiTowerView::CHanoiTowerView()
{
	// TODO: add construction code here
	m_pDisc=NULL;
	
	m_strSpeed="中速";
	m_nDelay=500;
	m_nArrowPos=1;
	m_nCapDiscNum=0;

		
	m_nIsAuto=0;
	m_nIsStart=0;
	m_nIsReset=0;
	m_nIsPause=0;
	m_bIsCapDisc=FALSE;
	m_bIsFirst=TRUE;
	
	m_enumTimeDelay=DISPLAY;
	m_enumTimeMove=MOVE;
	
}

CHanoiTowerView::~CHanoiTowerView()
{
	m_pDisc=NULL;
}

BOOL CHanoiTowerView::PreCreateWindow(CREATESTRUCT& cs)
{
	// TODO: Modify the Window class or styles here by modifying
	//  the CREATESTRUCT cs

	return CView::PreCreateWindow(cs);
}

/////////////////////////////////////////////////////////////////////////////
// CHanoiTowerView drawing

 void CHanoiTowerView::OnDraw(CDC* pDC)
{
	CHanoiTowerDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);

	m_nDiscNum=pDoc->m_nDiscNum;
	m_pDisc=pDoc->m_pDisc;
	//m_bIsOpenFile=pDoc->m_bIsOpenFile;

	// TODO: add draw code for native data he
  	
	DisplayMode(pDoc, pDC);  //显示游戏模式
	
	DrawTower(pDoc, pDC);   //绘汉诺塔
	DrawDisc(pDoc, pDC);    //绘disc
	
	if(m_nIsAuto==1)
	{
		DrawArrow(pDoc, pDC);
		
		if( IsFinishGame() && (!m_bIsCapDisc) )
		{
			AfxMessageBox("恭喜您完成了游戏",NULL);
			
			m_bIsFirst=TRUE;
			m_nArrowPos=1;
			
			pDoc->OnNewDocument();
			Invalidate();
		}
	}


}

/////////////////////////////////////////////////////////////////////////////
// CHanoiTowerView printing

BOOL CHanoiTowerView::OnPreparePrinting(CPrintInfo* pInfo)
{
	// default preparation
	return DoPreparePrinting(pInfo);
}

void CHanoiTowerView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: add extra initialization before printin
	
}

void CHanoiTowerView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: add cleanup after printing
}

/////////////////////////////////////////////////////////////////////////////
// CHanoiTowerView diagnostics

#ifdef _DEBUG
void CHanoiTowerView::AssertValid() const
{
	CView::AssertValid();
}

void CHanoiTowerView::Dump(CDumpContext& dc) const
{
	CView::Dump(dc);
}

CHanoiTowerDoc* CHanoiTowerView::GetDocument() // non-debug version is inline
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CHanoiTowerDoc)));
	return (CHanoiTowerDoc*)m_pDocument;
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CHanoiTowerView message handlers

void CHanoiTowerView::OnPrepareDC(CDC* pDC, CPrintInfo* pInfo) 
{
	// TODO: Add your specialized code here and/or call the base class
    CRect rectClient;

	GetClientRect(rectClient);

	pDC->SetMapMode(MM_ANISOTROPIC);
    pDC->SetWindowExt(1320,1000);
	pDC->SetViewportExt(rectClient.right, -rectClient.bottom);
	
	pDC->SetWindowOrg(-660,900);//将逻辑点(-660,900),映射到设备点(0,0)
	                            //相当于把坐标源点从设备点(0,0)移动到(660,-900)
    
	CView::OnPrepareDC(pDC, pInfo);
}


//利用Doc,Tower数据绘画出汉诺塔
void CHanoiTowerView::DrawTower(CHanoiTowerDoc *pDoc, CDC *pDC)
{
   
	
    if(m_bIsFirst)
	{
		m_TowerA.InitialTower(pDoc->m_TowerA.m_nTowerSerialNum,
							  pDoc->m_TowerA.m_nTopDiscSerialNum,
							  pDoc->m_TowerA.m_nTotalDiscNum);
   		
		m_TowerB.InitialTower(pDoc->m_TowerB.m_nTowerSerialNum,
							  pDoc->m_TowerB.m_nTopDiscSerialNum,
							  pDoc->m_TowerB.m_nTotalDiscNum);
		
		m_TowerC.InitialTower(pDoc->m_TowerC.m_nTowerSerialNum,
							  pDoc->m_TowerC.m_nTopDiscSerialNum,
							  pDoc->m_TowerC.m_nTotalDiscNum);
		m_bIsFirst=FALSE;
	}
		
	int i=pDC->SaveDC();
	
	pDC->SelectStockObject(LTGRAY_BRUSH);
		
	//绘塔柱
    pDC->Rectangle(m_TowerA.GetPole());
	pDC->Rectangle(m_TowerB.GetPole());
	pDC->Rectangle(m_TowerC.GetPole());
	
	//绘塔基
	pDC->Rectangle(m_TowerA.GetBase());
	pDC->Rectangle(m_TowerB.GetBase());
	pDC->Rectangle(m_TowerC.GetBase());

	//写出塔标号
	pDC->TextOut(m_TowerA.m_pointCenter.x-20, m_TowerA.m_pointCenter.y, "塔1");
	pDC->TextOut(m_TowerB.m_pointCenter.x-20, m_TowerB.m_pointCenter.y, "塔2");
	pDC->TextOut(m_TowerC.m_pointCenter.x-20, m_TowerC.m_pointCenter.y, "塔3");

	pDC->RestoreDC(i);
}

void CHanoiTowerView::DrawDisc(CHanoiTowerDoc *pDoc, CDC *pDC)
{	
	
	int ref=pDC->SaveDC();
	
	
	for(int i=0; i<m_nDiscNum; i++)
	{	
		CBrush brush;
        brush.CreateSolidBrush((m_pDisc+i)->m_DiscColor);
		
		pDC->SelectObject(&brush);
		pDC->Ellipse((m_pDisc+i)->GetDisc());
		
	}

	pDC->RestoreDC(ref);

}

void CHanoiTowerView::OnRunSetup() 
{
	CHanoiTowerDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	// TODO: Add your command handler code here
	
	ParaDlg dlgSetup;

	dlgSetup.m_nDiscNum=m_nDiscNum;
	dlgSetup.m_nIsAuto=m_nIsAuto;
	dlgSetup.m_strSpeed=m_strSpeed;

	if(dlgSetup.DoModal()==IDOK)
	{
	 UpdateData(TRUE);
	 m_nDiscNum=dlgSetup.m_nDiscNum;
	 m_TowerA.m_nTotalDiscNum=m_nDiscNum;

	 m_strSpeed=dlgSetup.m_strSpeed;
	 m_nIsAuto=dlgSetup.m_nIsAuto;

	 
	 m_bIsFirst=TRUE; //设置标志位,从doc中更新Tower信息
	 m_bIsOpenFile=FALSE;
	 m_nIsReset=2;



     
	 pDoc->m_nDiscNum=m_nDiscNum;  //从对话框中读入参数,并传回Doc类
	 pDoc->m_nIsAuto=m_nIsAuto;    
	 pDoc->m_bIsOpenFile=FALSE;
	 
	 
	 pDoc->m_DiscStepList.RemoveAll(); //清除队列中的数据

	 pDoc->OnNewDocument();		   //根据参数初始化游戏

	 //判断速度选择值
	 if (m_strSpeed=="高速")
	 {
	 	 m_nDelay=250;
		 
	 }
	 else if (m_strSpeed=="中速")
	 {
		 m_nDelay=600;
		
	 }
	 else if (m_strSpeed=="低速")
	 { 
		 m_nDelay=1200;
		 
	 }
	 else
	 {
	     AfxMessageBox("速度选择不正确,采用默认值(中速)\n    要修改请重新进行游戏选择", 
			          MB_OK);
		 m_nDelay=500;
		 m_strSpeed="中速";
		

	 }


	 pDoc->m_nDelay=m_nDelay;
	 pDoc->m_strSpeed=m_strSpeed;

	 if(pDoc->m_DiscStepList.IsEmpty() && !m_nIsAuto)
	 {
		 pDoc->AutoPlay();

	 }

	 //重画屏幕
	 Invalidate();
	}
	
}

void CHanoiTowerView::DisplayMode(CHanoiTowerDoc *pDoc, CDC *pDC)
{
	m_nIsAuto=pDoc->m_nIsAuto;
	
    CFont newfont;
	newfont.CreateFont( 45,                        // nHeight
					    0,                         // nWidth
					    0,                         // nEscapement
					    0,                         // nOrientation
					    FW_NORMAL,                 // nWeight
					    FALSE,                     // bItalic
					    FALSE,                     // bUnderline
					    0,                         // cStrikeOut
					    ANSI_CHARSET,              // nCharSet
					    OUT_DEFAULT_PRECIS,        // nOutPrecision
					    CLIP_DEFAULT_PRECIS,       // nClipPrecision
					    DEFAULT_QUALITY,           // nQuality
					    DEFAULT_PITCH | FF_SWISS,  // nPitchAndFamily
					    "宋体");  
	
	CFont *oldfont=pDC->SelectObject(&newfont);

	if(m_nIsAuto==0)
	{
		pDC->TextOut(-650, 900, "当前游戏模式:自动演示");
	}
	else
	{
		pDC->TextOut(-650, 900, "当前游戏模式:手动游戏(用'空格键'和'方向键'控制)");
	}

    m_strSpeed=pDoc->m_strSpeed;
	pDC->TextOut(-650, 860, m_strSpeed);

	pDC->SelectObject(oldfont);
}

void CHanoiTowerView::OnRunStart() 
{
	if(m_nIsStart)
	{
		return;
	}
	
	
	CHanoiTowerDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);

	CClientDC dc(this);
	OnPrepareDC(&dc);

	MSG message;

	m_bIsOpenFile=pDoc->m_bIsOpenFile;
	// TODO: Add your command handler code here

	

	if(!m_bIsOpenFile)
	{
		if(m_nIsPause==0)
		{
			//每次开始设计标志位	
			m_nIsStart=1;
			m_nIsReset=0;

			//第一次,没有初始化矩形列表时,初始化之
			if(pDoc->m_DiscStepList.IsEmpty())
			{
				pDoc->AutoPlay();

			}

			pDoc->m_nDelay=m_nDelay;
	        pDoc->m_strSpeed=m_strSpeed;

			//开启计时器
			SetTimer(m_enumTimeDelay, m_nDelay, NULL);
			m_bTimeUp=FALSE;
		}
		else
		{
			m_nIsStart=1;
			m_nIsPause=0;
			
		}

	}
	else
	{
		//如果读入了文件,初始化标志位
		m_nIsStart=1;
		m_nIsPause=0;
		m_nIsReset=0;

		m_nDelay=pDoc->m_nDelay;
		
		//开启计时器
		SetTimer(m_enumTimeDelay, m_nDelay, NULL);
		m_bTimeUp=FALSE;
	}
	
	//开始循环显示汉诺塔搬移过程
	while( !(pDoc->m_DiscStepList.IsEmpty()) )
	{
   		 if(m_nIsReset)
		 {
			 break;
		 }

		 if(m_bIsOpenFile)
		 {
			 pDoc->m_bIsOpenFile=FALSE;
			 m_bIsOpenFile=FALSE;
		 }


		 if(m_nIsStart)
			{
				//起点矩形
			    CRect *FromRect;
				
				FromRect=(CRect*)pDoc->m_DiscStepList.GetHead();
				
				pDoc->m_DiscStepList.RemoveHead();
			
				//判断当前移动disc,并修改其位置值
				for (int i=0; i<m_nDiscNum; i++)
				{
					CSize sz=FromRect->Size();
					sz.cy=-sz.cy;
					if ((m_pDisc+i)->m_sizeDisc==sz)
					{
						(m_pDisc+i)->m_pointCenterBottom=FromRect->CenterPoint();
						(m_pDisc+i)->m_pointCenterBottom.y-=15;
					}
				}
			
				dc.LPtoDP(FromRect);
				InvalidateRect(FromRect);


				//终点矩形
				CRect *ToRect;
				//在新位置画出碟子
				ToRect=pDoc->m_DiscStepList.GetHead();

				pDoc->m_DiscStepList.RemoveHead();

				//判断当前移动disc,并修改其位置值
				for ( i=0; i<m_nDiscNum; i++)
				{
					CSize sz=ToRect->Size();
					sz.cy=-sz.cy;
					
					if ((m_pDisc+i)->m_sizeDisc==sz)
					{
						(m_pDisc+i)->m_pointCenterBottom=ToRect->CenterPoint();
						(m_pDisc+i)->m_pointCenterBottom.y-=15;
					}
				}

				dc.LPtoDP(ToRect);
				InvalidateRect(ToRect);

				pDoc->SetPathName(" ");
			}
		 
		
		 //定时器延时
		 while(!m_bTimeUp)
		 {
			 if(::PeekMessage(&message, NULL, 0, 0, PM_REMOVE))
			 {
				 ::TranslateMessage(&message);
				 ::DispatchMessage(&message);
			 }
		 }
		 m_bTimeUp=FALSE;   //重新进入延时循环		

	}

	//销毁计时器
	KillTimer(m_enumTimeDelay);
	m_bTimeUp=FALSE;

	//提示完成
	if(!m_nIsReset)
	{
		AfxMessageBox("完成自动演示");
	}
	else if(m_nIsReset==1)   
	{	
		m_nIsReset=0;  //取消重置标志位
		AfxMessageBox("停止自动演示,并重新设置游戏");
	}
	
	//如果运行过程中打开了新文件,
	//则不进行链表和disc数组初始化
	if(m_bIsOpenFile)
	{
		AfxMessageBox("读入新游戏演示");

		pDoc->InitializeTower();
	
		//取消演示标志位

⌨️ 快捷键说明

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