一个MFC实现的汉诺塔程序

汉诺塔采用的是一个经典递归算法,以前我在学《数据结构》时涉及过,前不久公司组织拓展活动,活动期间有一项就是移动汉诺塔,因此活动结束后我重新设计并实现了这一算法。其中和书中讲的略有区别,但大同小异,以记后来。

1 头文件声明

// 一个汉诺塔
struct stOneHLT{
    stOneHLT()
    {
        HLTName = "";
        SourceNums = 0;
        Numslist.clear();
        //pUpHLT = NULL;

    }
    stOneHLT(const stOneHLT& otherOneHLT)
    {
        if (this != &otherOneHLT)
        {
            Numslist.clear();
            list<int>::const_iterator it = otherOneHLT.Numslist.begin();
            while (it != otherOneHLT.Numslist.cend())
            {
                Numslist.push_back(*it);
                it++;
            }

            HLTName = otherOneHLT.HLTName;
            SourceNums = otherOneHLT.SourceNums;

        }
    }
    stOneHLT operator = (const stOneHLT& otherOneHLT)
    {
        if (this != &otherOneHLT)
        {
            Numslist.clear();
            list<int>::const_iterator it = otherOneHLT.Numslist.begin();
            while (it != otherOneHLT.Numslist.cend())
            {
                Numslist.push_back(*it);
                it++;
            }

            HLTName = otherOneHLT.HLTName;
            SourceNums = otherOneHLT.SourceNums;

        }
        return *this;
    }
    CString HLTName; // 汉诺塔名
    int SourceNums; // 原始所有层级
    list<int> Numslist; // 当前塔的所有盘子
    //stOneHLT* pUpHLT;
};

// 汉诺塔
class CHLT{
public:
    CHLT(int cj,CListBox* pListBox);

protected:

    // 判断移动方向,moveLeve:为待移动的层级
    stOneHLT& CheckMoveDirection(int moveLeve, stOneHLT& sourceOneHLT, stOneHLT& tmpOneHLT, stOneHLT& TargetOneHLT);
    
    void Move4(stOneHLT& sourceOneHLT, stOneHLT& tmpOneHLT, stOneHLT& TargetOneHLT, int movenum);

    stOneHLT& FindHLT(int findValue, stOneHLT& sourceOneHLT, stOneHLT& tmpOneHLT, stOneHLT& TargetOneHLT);

    void showMove(int i, stOneHLT& sourceOneHLT, stOneHLT& TargetOneHLT);

public:
    
    void beginMove();


private:
    stOneHLT AOneHLT; // A汉诺塔
    stOneHLT BOneHLT; // B汉诺塔
    stOneHLT COneHLT; // C汉诺塔
    int m_MoveNums; // 移动的次数
    stOneHLT* PrevHLT;
    CListBox* m_pListBox; // 
};

 

2 实现文件

//----------------------------------CHLT begin------------------------------------------------------

CHLT::CHLT(int cj,CListBox* pListBox)
{
    AOneHLT.HLTName = _T("A");
    BOneHLT.HLTName = _T("B");
    COneHLT.HLTName = _T("C");
    m_pListBox = pListBox;

    for (int i = 0; i < cj; i++)
    {
        AOneHLT.Numslist.push_back(i + 1);
    }
    AOneHLT.SourceNums = AOneHLT.Numslist.size();
    BOneHLT.Numslist.clear();
    COneHLT.Numslist.clear();
    PrevHLT = NULL;
    m_MoveNums = 0;
}

stOneHLT& CHLT::FindHLT(int findValue, stOneHLT& sourceOneHLT, stOneHLT& tmpOneHLT, stOneHLT& TargetOneHLT)
{
    list<int>::iterator it = sourceOneHLT.Numslist.begin();
    while ( it != sourceOneHLT.Numslist.end() )
    {
        if (findValue == *it)
        {
            return sourceOneHLT;
        }
        it++;
    }

    it = tmpOneHLT.Numslist.begin();
    while (it != tmpOneHLT.Numslist.end())
    {
        if (findValue == *it)
        {
            return tmpOneHLT;
        }
        it++;
    }

    it = TargetOneHLT.Numslist.begin();
    while (it != TargetOneHLT.Numslist.end())
    {
        if (findValue == *it)
        {
            return TargetOneHLT;
        }
        it++;
    }

}

void CHLT::showMove(int i, stOneHLT& sourceOneHLT, stOneHLT& TargetOneHLT)
{
    m_MoveNums++;
    CString msg;
    msg.Format(_T("%d %s->%s"), i, sourceOneHLT.HLTName.GetBuffer(), TargetOneHLT.HLTName.GetBuffer());
    sourceOneHLT.HLTName.ReleaseBuffer();
    TargetOneHLT.HLTName.ReleaseBuffer();
    CString tmp = msg;
    

    //msg.Format(_T("第%d层"), i, sourceOneHLT.HLTName.GetBuffer(), TargetOneHLT.HLTName.GetBuffer());

    OutputDebugString(msg.GetBuffer());
    if (m_pListBox)
    {
        m_pListBox->AddString((LPCTSTR)tmp.GetBuffer());
        tmp.ReleaseBuffer();
    }

    
}


void CHLT::Move4(stOneHLT& sourceOneHLT, stOneHLT& tmpOneHLT, stOneHLT& TargetOneHLT, int movenum)
{
    for (int i = 1; i <= movenum; i++)
    {
        sourceOneHLT.SourceNums = movenum;
        stOneHLT& FindMovedHLT = CheckMoveDirection(i, sourceOneHLT, tmpOneHLT, TargetOneHLT);
        if (FindMovedHLT.Numslist.size() == 0 || i < FindMovedHLT.Numslist.front())
        {
            sourceOneHLT.Numslist.pop_front();
            FindMovedHLT.Numslist.push_front(i);

            showMove(i, sourceOneHLT, FindMovedHLT);

            if (i != 1)
            {
                stOneHLT& upHLT = FindHLT(i - 1, sourceOneHLT, tmpOneHLT, TargetOneHLT);
                if (sourceOneHLT.HLTName.Compare(upHLT.HLTName.GetBuffer()) != 0 && sourceOneHLT.HLTName.Compare(FindMovedHLT.HLTName.GetBuffer()) != 0)
                    Move4(upHLT, sourceOneHLT, FindMovedHLT, i - 1);  // 将辅助塔上面的当前目标塔
                else
                    if (tmpOneHLT.HLTName.Compare(upHLT.HLTName.GetBuffer()) != 0 && tmpOneHLT.HLTName.Compare(FindMovedHLT.HLTName.GetBuffer()) != 0)
                        Move4(upHLT, tmpOneHLT, FindMovedHLT, i - 1);  // 将辅助塔上面的移到当前目标塔    
                    else
                        Move4(upHLT, TargetOneHLT, FindMovedHLT, i - 1);  // 将辅助塔上面的移到当前目标塔    
                
            }
        }
        
    }
}


stOneHLT& CHLT::CheckMoveDirection(int moveLeve, stOneHLT& sourceOneHLT, stOneHLT& tmpOneHLT, stOneHLT& TargetOneHLT)
{
    int nNums = sourceOneHLT.SourceNums;
    if (nNums % 2 == 0) // 总数为双数
    {
        if (moveLeve % 2 == 0) // 
            return TargetOneHLT; // 双数层 移动到目标层
        else
            return tmpOneHLT; // 单数层移动到中间层
    }
    else // 总数为单数
    {
        if (moveLeve % 2 == 0) //  
            return tmpOneHLT; // 双数层移动到中间层
        else
            return TargetOneHLT; // 单数层移动到目标层
    }
}

void CHLT::beginMove()
{
#if 0
    Move(AOneHLT, BOneHLT, COneHLT, AOneHLT.Numslist.size());
#else
    Move4(AOneHLT, BOneHLT, COneHLT, AOneHLT.Numslist.size());
#endif
    //char msg[100] = { 0 };
    //CListBox* pListbox = (CListBox*)GetDlgItem(IDC_LIST1);
    CString msg;
    msg.Format(_T("移动的总次数:%d"), m_MoveNums);
    //sprintf_s(msg, 100, "移动的总次数:%d\n", m_MoveNums);
    //OutputDebugString(msg.GetBuffer());
    if (m_pListBox)
    {
        m_pListBox->AddString(msg.GetBuffer());
        int nCount = m_pListBox->GetCount();
        if (nCount > 0)
            m_pListBox->SetCurSel(nCount - 1);
    }
}

//----------------------------------CHLT end------------------------------------------------------

 

3 调用程序

在mfc的界面上放入一个按钮,在此按钮的单击事件中实现如下代码:

void CHLTDlg::OnBnClickedButton1()
{
    // TODO: Add your control notification handler code here
    UpdateData(TRUE);
    for (int i = m_pBox->GetCount() - 1; i >= 0; i--)
    {
        m_pBox->DeleteString(i);
    }
    CHLT HLT(m_nCJ, m_pBox/*pListbox*/);
    HLT.beginMove();


}
 

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值