1. 程式人生 > >一個MFC實現的漢諾塔程式

一個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();

}