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

📄 hanoitowerdoc.cpp

📁 汉诺塔的实现
💻 CPP
字号:
// HanoiTowerDoc.cpp : implementation of the CHanoiTowerDoc class
//

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


#include "HanoiTowerDoc.h"

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

/////////////////////////////////////////////////////////////////////////////
// CHanoiTowerDoc

IMPLEMENT_DYNCREATE(CHanoiTowerDoc, CDocument)

BEGIN_MESSAGE_MAP(CHanoiTowerDoc, CDocument)
	//{{AFX_MSG_MAP(CHanoiTowerDoc)
		// NOTE - the ClassWizard will add and remove mapping macros here.
		//    DO NOT EDIT what you see in these blocks of generated code!
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CHanoiTowerDoc construction/destruction

CHanoiTowerDoc::CHanoiTowerDoc()
{
	// TODO: add one-time construction code here
	m_pDisc=NULL;
	m_nDiscNum=5;
	m_nIsAuto=0;
	m_nIsFinished=0;
	m_bIsOpenFile=FALSE;


	m_strSpeed="中速";
	m_nDelay=600;


}

CHanoiTowerDoc::~CHanoiTowerDoc()
{
	//清楚堆栈,消灭野指针
	if(m_pDisc!=NULL)
	{
		delete[] m_pDisc;
		m_pDisc=NULL;

	}
	

	m_DiscStepList.RemoveAll();

}

BOOL CHanoiTowerDoc::OnNewDocument()
{
	if (!CDocument::OnNewDocument())
		return FALSE;

    //注意顺序
	InitializeTower();
	InitializeDisc();
	
	
	
	
	

	return TRUE;
}



/////////////////////////////////////////////////////////////////////////////
// CHanoiTowerDoc serialization

void CHanoiTowerDoc::Serialize(CArchive& ar)
{

		if (ar.IsStoring())
		{	//storing code
			if(m_DiscStepList.IsEmpty())
			{
				AfxMessageBox("没有开始游戏,不能存盘", NULL);
			}
			else
			{
				ar<<m_nIsAuto<<m_nDiscNum<<m_nDelay<<m_strSpeed;	

				TRACE("saving m_nIsAuto is:%d, m_nDiscNum is:%d\n", m_nIsAuto, m_nDiscNum);

				ListSerialize(ar);

				DiscArrSerialize(ar);

			}
		}
		else
		{	//loading code
			ar>>m_nIsAuto>>m_nDiscNum>>m_nDelay>>m_strSpeed;

			m_bIsOpenFile=TRUE;
			
			TRACE("loading m_nIsAuto is:%d, m_nDiscNum is:%d\n", m_nIsAuto, m_nDiscNum);
		
			ListSerialize(ar);

			DiscArrSerialize(ar);

			//路径清空
			
			SetPathName(" ");
		
		
		}


	
}

/////////////////////////////////////////////////////////////////////////////
// CHanoiTowerDoc diagnostics

#ifdef _DEBUG
void CHanoiTowerDoc::AssertValid() const
{
	CDocument::AssertValid();
}

void CHanoiTowerDoc::Dump(CDumpContext& dc) const
{
	CDocument::Dump(dc);
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CHanoiTowerDoc commands


void CHanoiTowerDoc::AutoPlay()
{
	//复制一个disc对象组,以保留原对象组。
	Disc *pDiscArr=NULL;
    pDiscArr=new Disc[m_nDiscNum];
	
	for(int i=0; i<m_nDiscNum; i++)
	{
		(pDiscArr+i)->m_nDiscCurrentLayer=(m_pDisc+i)->m_nDiscCurrentLayer;
		(pDiscArr+i)->m_nDiscCurrentTower=(m_pDisc+i)->m_nDiscCurrentTower;
		(pDiscArr+i)->m_nDiscSerialNum=(m_pDisc+i)->m_nDiscSerialNum;
		(pDiscArr+i)->m_pointCenterBottom=(m_pDisc+i)->m_pointCenterBottom;
		(pDiscArr+i)->m_sizeDisc=(m_pDisc+i)->m_sizeDisc;
		
	}

	
	
	//自动运算,并记录步骤
	Hanoi(m_nDiscNum, m_TowerA, m_TowerB, m_TowerC, pDiscArr);
	
	//释放堆栈空间,清除野指针
	delete[] pDiscArr;
	pDiscArr=NULL;

	m_nIsFinished=1;
}


void CHanoiTowerDoc::Hanoi(int nCount, 
						   Tower &T1, 
						   Tower &T2, 
						   Tower &T3, 
						   Disc *pDiscArr)
{	
	if (nCount==1)
	{
		
		move(T1, T3, pDiscArr);
	}
	else
	{

		Hanoi(nCount-1, T1, T3, T2, pDiscArr);

		move(T1, T3, pDiscArr);

		Hanoi(nCount-1, T2, T1, T3, pDiscArr);
	}

}

void CHanoiTowerDoc::move(Tower &FromTower, 
						  Tower &ToTower, 
						  Disc *pDiscArr)
{
	Disc *pMoveDisc;               
	
	//获得当前搬运的disc序号
	pMoveDisc=pDiscArr+FromTower.m_nTopDiscSerialNum-1;

    //原disc矩形存入链表
    CRect *oldDiscRect;

	oldDiscRect=new CRect;      //建立CRect类指针,用于存储原Disc矩形

	oldDiscRect->CopyRect(&(pMoveDisc->GetDisc()));  //复制原矩形
	
	m_DiscStepList.AddTail(oldDiscRect) ; 

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

	ToTower.m_nTopDiscSerialNum=pMoveDisc->m_nDiscSerialNum;   //目标塔顶层disc序号改为当前搬运的disc序号

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

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

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


	//移动后的disc存入链表
	
	CRect *newDiscRect;
	newDiscRect=new CRect;      //建立CRect类指针,用于存储移动后Disc矩形
	
	newDiscRect->CopyRect(&(pMoveDisc->GetDisc()));  //复制移动后矩形
	
	m_DiscStepList.AddTail(newDiscRect); 
	
}



void CHanoiTowerDoc::InitializeDisc()
{	
	 //初始化碟子
    m_pDisc=new Disc[m_nDiscNum];
	for(int i=0; i<m_nDiscNum; i++)
	{
		//位置相关
		(m_pDisc+i)->m_nDiscCurrentTower=1;
		(m_pDisc+i)->m_nDiscCurrentLayer=i+1;
		(m_pDisc+i)->m_nDiscSerialNum=i+1;
		
		//绘图相关
		(m_pDisc+i)->m_sizeDisc.cy=30;
		(m_pDisc+i)->m_sizeDisc.cx=100+20*i;
		
		(m_pDisc+i)->m_pointCenterBottom.x=m_TowerA.m_pointCenter.x;
		(m_pDisc+i)->m_pointCenterBottom.y=m_TowerA.m_sizeBase.cy+(m_nDiscNum-i-1)*30;
		(m_pDisc+i)->m_DiscColor=GetColor(i+1);
	}

}

void CHanoiTowerDoc::InitializeTower()
{
	//初始化汉诺塔
	m_TowerA.InitialTower(1, 1, m_nDiscNum);
	m_TowerB.InitialTower(2, 0, 0);
	m_TowerC.InitialTower(3, 0, 0);

}

COLORREF CHanoiTowerDoc::GetColor(int nDiscNum)
{
	COLORREF Color; 
	
	//根据碟子序号决定碟子颜色

	int ColorNum=(nDiscNum-1)%3;
	
	switch(ColorNum)
	{
	case 0:
		{
			Color=RGB(0,255,0);
			break;
		}
	case 1:
		{
			Color=RGB(255,0,0);
			break;
		}
	case 2:
		{
			Color=RGB(0,128,255);
			break;
		}
	default:
		{
			break;
		}

	}

	return Color;
}

void CHanoiTowerDoc::ListSerialize(CArchive& ar)
{
	int listlen;  //记录链表长度
	POSITION position;   //链表位置指针

	if (ar.IsStoring())
	{	//storing code
		CRect tempRect;  //建立临时矩形对象

		//保存链表
		listlen=m_DiscStepList.GetCount(); //获得链表长度

		ar<<listlen;   //保存链表长度

		position=m_DiscStepList.GetHeadPosition();

		for(int i=0; i<listlen; i++)
		{
			tempRect=(*m_DiscStepList.GetAt(position));
			ar<<tempRect;
			m_DiscStepList.GetNext(position);

			TRACE("save list %d is: %d\n", i, tempRect.bottom);
		}
	}
	else
	{	//loading code
		CRect *pTempRect;  //临时矩形对象
		
		ar>>listlen;  //读出长度
		
		
		m_DiscStepList.RemoveAll();   //清除原队列

		for(int i=0; i<listlen; i++)
		{	
			pTempRect=new CRect;
			ar>>(*pTempRect);
     		m_DiscStepList.AddTail(pTempRect);

			TRACE("load list %d is: %d\n", i, pTempRect->bottom);
	
		}
	}
}

void CHanoiTowerDoc::DiscArrSerialize(CArchive &ar)
{
		
	if (ar.IsStoring())
	{	//storing code
		for(int i=0; i<m_nDiscNum; i++)
		{
			Disc tempDisc;
			tempDisc=*(m_pDisc+i);
			
			ar<<tempDisc.m_DiscColor
			  <<tempDisc.m_nDiscCurrentLayer
			  <<tempDisc.m_nDiscCurrentTower
			  <<tempDisc.m_nDiscSerialNum
			  <<tempDisc.m_pointCenterBottom
			  <<tempDisc.m_sizeDisc;

			TRACE("saving DiscNum is:%d\n", tempDisc.m_nDiscSerialNum);
		}

		
	}
	else
	{	//loading code
		//删除原disc数组

		delete[] m_pDisc;
		m_pDisc=new Disc[m_nDiscNum];
		
		for(int i=0; i<m_nDiscNum; i++)
		{
			Disc *tempDisc;
			
			tempDisc=new Disc;
			
			ar>>(m_pDisc+i)->m_DiscColor
			  >>(m_pDisc+i)->m_nDiscCurrentLayer
			  >>(m_pDisc+i)->m_nDiscCurrentTower
			  >>(m_pDisc+i)->m_nDiscSerialNum
			  >>(m_pDisc+i)->m_pointCenterBottom
			  >>(m_pDisc+i)->m_sizeDisc;

			TRACE("loading DiscNum is:%d\n", (m_pDisc+i)->m_nDiscSerialNum);
		}
    }



}

⌨️ 快捷键说明

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