CnineGrid 类

        我修改的一个nineGrid类
       #include "stdafx.h"
#include "CNineGrid.h"
#include <fstream.h>

CNineGrid::CNineGrid()
{
    m_pPathList = NULL;
    m_pPlaceList = NULL;
    m_pScanbuf = NULL;
    m_iPathsize = 0;
    m_iTime = 0;
    m_bAutoRun = false;
    m_hasFeel = false;
    Reset();
}

CNineGrid::~CNineGrid()
{
    if (m_pPathList != NULL)
    {
        delete[] m_pPathList;
    }

    if (m_pScanbuf != NULL)
    {
        delete[] m_pScanbuf;
    }
}

inline void CNineGrid::ArrayToDword(unsigned char *array , DWORD& data)
{
    unsigned char night = 0;
    for ( int i = 0 ; i < 9 ; i ++)
    {
        if (array[i] == 8)
        {
            night = (unsigned char)i;
            break;
        }
    }
   
    array[night] = 0;
    data = 0;
    data =     (DWORD)((DWORD)array[0] << 29 | (DWORD)array[1] << 26 |
                     (DWORD)array[2] << 23 | (DWORD)array[3] << 20 |
                     (DWORD)array[4] << 17 | (DWORD)array[5] << 14 |
                     (DWORD)array[6] << 11 | (DWORD)array[7] <<  8 |
                     (DWORD)array[8] <<  5 | night);
   
    array[night] = 8;
}

inline void CNineGrid::DwordToArray(DWORD data , unsigned char *array)
{
    unsigned char chtem;
    for ( int i = 0 ; i < 9 ; i ++)
    {
        chtem = (unsigned char)(data >> (32 - (i + 1) * 3) & 0x00000007);
        array[i] = chtem;
    }
    chtem = (unsigned char)(data & 0x0000001F);
    array[chtem] = 8;
}

bool CNineGrid::ComputeFeel()
{
    unsigned char *array = m_iChess;
    UINT i;
    const int MAXSIZE = 362880;
    unsigned char temparray[9];
   
    DWORD target , fountain , parent , parentID = 0 , child = 1;
    ArrayToDword(m_iTargetChess , target);
    ArrayToDword(array , fountain);

    if (fountain == target)
    {
        return false;
    }

    if (m_pScanbuf != NULL)
    {
        delete[] m_pScanbuf;
    }
    m_pScanbuf = new Scanbuf[MAXSIZE];
    AddTree(fountain ,m_pPlaceList);
    m_pScanbuf[ 0 ].Place = fountain;
    m_pScanbuf[ 0 ].ScanID = -1;

    clock_t tim = clock();

    while(parentID < MAXSIZE && child < MAXSIZE)
    {
        parent = m_pScanbuf[parentID].Place;
        for ( i = 0 ; i < 4 ; i ++)
        {
            DwordToArray(parent , temparray);
            if (MoveChess(temparray,i))
            {
                ArrayToDword(temparray , fountain);
                if (AddTree(fountain, m_pPlaceList))
                {
                    m_pScanbuf[ child ].Place = fountain;
                    m_pScanbuf[ child ].ScanID = parentID;
                    if (fountain == target)
                    {
                        m_iTime = clock() - tim;
                        GetPath(child);
                        FreeTree(m_pPlaceList);
                        delete[] m_pScanbuf;
                        m_pScanbuf = NULL;
                        m_hasFeel = true;
                        return true;
                    }
                    child ++;
                }
            }
        } // for i
        parentID++;
    }

    m_iTime = clock() - tim;
    m_hasFeel = false;
    FreeTree(m_pPlaceList);
    delete[] m_pScanbuf;
    m_pScanbuf = NULL;
    return false;
}

inline bool CNineGrid::AddTree(DWORD place , PlaceList*& parent)
{
    if (parent == NULL)
    {
        parent = new PlaceList();
        parent->Left = parent->Right = NULL;
        parent->Place = place;
        return true;
    }
    if (parent->Place == place)
    {
        return false;
    }
    if (parent->Place > place)
    {
        return AddTree(place , parent->Right);
    }
    return AddTree(place , parent->Left);
}

void CNineGrid::FreeTree(PlaceList*& parent)
{
    if (parent != NULL)
    {
        if ( parent->Left != NULL)
            FreeTree(parent->Left);
        if ( parent->Right != NULL)
            FreeTree(parent->Right);
        delete parent;
        parent = NULL;
    }
}

inline bool CNineGrid::MoveChess(unsigned char *array , int way)
{
    int zero , chang;
    bool moveok = false;
    for ( zero = 0 ; zero < 9 ; zero ++)
    {
        if (array[zero] == 0)
            break;
    }
    POINT pnt;
    pnt.x = zero % 3;
    pnt.y = int(zero / 3);
    switch(way)
    {
    case 0 : //up
        if (pnt.y + 1 < 3)
        {
            chang = (pnt.y + 1) * 3 + pnt.x ;
            array[zero] = array[chang];
            array[chang] = 0;
            moveok = true;
        }
        break;
    case 1 : //down
        if (pnt.y - 1 > -1)
        {
            chang = (pnt.y - 1) * 3 + pnt.x ;
            array[zero] = array[chang];
            array[chang] = 0;
            moveok = true;
        }
        break;
    case 2 : //left
        if (pnt.x + 1 < 3)
        {
            chang = pnt.y * 3 + pnt.x + 1;
            array[zero] = array[chang];
            array[chang] = 0;
            moveok = true;
        }
        break;
    case 3 : //right
        if (pnt.x - 1 > -1)
        {
            chang = pnt.y * 3 + pnt.x - 1;
            array[zero] = array[chang];
            array[chang] = 0;
            moveok = true;
        }
        break;
    }
    if (moveok && !m_bAutoRun)
    {
        m_iStepCount ++ ;
       
        DWORD temp1 ,temp2;
        ArrayToDword(array , temp1);
        ArrayToDword(m_iTargetChess , temp2);
        if (temp1 == temp2)
        {
            MessageBox(NULL , "你真聪明这么快就搞定了!" , "" , 0);       
        }
    }
    return moveok;
}

bool CNineGrid::EstimateUncoil(unsigned char *array)
{
    int sun = 0;
    for ( int i = 0 ; i < 8 ; i ++)
    {
        for ( int j = 0 ; j < 9 ; j ++)
        {
            if (array[j] != 0)
            {
                if (array[j] == i +1 )
                    break;
                if (array[j] < i + 1)
                    sun++;
            }
        }
    }
    if (sun % 2 == 0)
        return true;
    else
        return false;
}

void CNineGrid::GetPath(UINT depth)
{
    int now = 0 , maxpos = 100 ;
    UINT parentid;
    if (m_pPathList != NULL)
    {
        delete[] m_pPathList;
    }
    m_pPathList = new PathList[maxpos];
    parentid = m_pScanbuf[depth].ScanID;
   
    DwordToArray(m_pScanbuf[depth].Place , m_pPathList[++now].Path);
   
    while(parentid != -1)
    {
        if (now == maxpos)
        {
            maxpos += 10;
            PathList * temlist = new PathList[maxpos];
            memcpy(temlist , m_pPathList , sizeof(PathList) * (maxpos - 10));
            delete[] m_pPathList;
            m_pPathList = temlist;
        }
        DwordToArray(m_pScanbuf[parentid].Place , m_pPathList[++now].Path);
        parentid = m_pScanbuf[parentid].ScanID;
    }
    m_iPathsize = now;
}

unsigned __stdcall MoveChessThread(LPVOID pParam)
{
    CNineGrid * pGird = (CNineGrid *)pParam;
    RECT rect;
    pGird->m_iStepCount = 0;
    ::GetClientRect(pGird->m_hClientWin , &rect);
    for ( int i = pGird->m_iPathsize ; i > 0 ; i --)
    {
        memcpy(pGird->m_iChess , pGird->m_pPathList[i].Path , 9);
        pGird->m_iStepCount ++;
        InvalidateRect( pGird->m_hClientWin , &rect , false);
        Sleep(500);
    }
    char msg[100];
    sprintf(msg , "计算步骤用时%d毫秒" , pGird->m_iTime);
    MessageBox(NULL , msg , "运行时间" , 0);
    pGird->m_bAutoRun = false;
    return 0L;
}

void CNineGrid::ActiveShaw(HWND hWin)
{
    /*
    if (m_bAutoRun)
        return;
    m_bAutoRun = true;
   
    if (!ComputeFeel())
    {
        m_bAutoRun = true;
        return;
    }
    */
    if(!this->m_hasFeel)
    {
        m_bAutoRun = true;
        return;
    }
   
    m_hClientWin = hWin;
   
    HANDLE hThread;
    unsigned threadID;
    hThread = (HANDLE)_beginthreadex( NULL, 0, &MoveChessThread, this, 0, &threadID );
}

void CNineGrid::DrawGird(HDC hDC , RECT clientrect)
{
    int cx = clientrect.right / 2 - 180 ;
    int cy = clientrect.bottom / 2 - 60 ;
    int i , j;

    //HBRUSH hgirdbkbrush = ::CreateSolidBrush(RGB(255 , 128 , 64));
    HBRUSH hgirdbkbrush = ::CreateSolidBrush(RGB(10 , 200 , 200));
    HBRUSH hbutbrush = ::CreateSolidBrush(RGB(0 , 128 , 255));
    HBRUSH oldbrush = (HBRUSH)::SelectObject(hDC , hgirdbkbrush);
    COLORREF oldbkcolor = SetBkColor(hDC , RGB(0 , 128 , 255));
    // Draw fountain gird
    RECT rect;
    for (i = 0 ; i < 3 ; i ++)
    {
        for ( j = 0 ; j < 3 ; j ++)
        {
            SetRect(&rect , 0 , 0 , 40 , 40);
            OffsetRect(&rect , i * 40 + cx, j * 40 + cy);
            Rectangle(hDC , rect.left , rect.top , rect.right , rect.bottom);
        }
    }
   
    // Draw target gird
    cx = clientrect.right / 2 + 60 ;
    for (i = 0 ; i < 3 ; i ++)
    {
        for ( j = 0 ; j < 3 ; j ++)
        {
            SetRect(&rect , 0 , 0 , 40 , 40);
            OffsetRect(&rect , i * 40 + cx, j * 40 + cy);
            Rectangle(hDC , rect.left , rect.top , rect.right , rect.bottom);
        }
    }

    SetBkColor(hDC , oldbkcolor);
    ::SelectObject(hDC , oldbrush);
    DeleteObject(hgirdbkbrush);
    DeleteObject(hbutbrush);
}

void CNineGrid::DrawChess(HDC hDC , RECT clientrect)
{
    int cx = clientrect.right / 2 - 180 ;
    int cy = clientrect.bottom / 2 - 60 ;

    RECT rect;
    char ch[2];
    int i , j;
    int tcount = 0;
   
    COLORREF oldbkcolor = SetBkColor(hDC , RGB(10 , 200 , 200));
   
    // Draw fountain number
    for ( i = 0 ; i < 3 ; i ++)
    {
        for ( j = 0 ; j < 3 ; j ++)
        {
            int t = m_iChess[tcount++];
            rect.left = j * 40;
            rect.top = i * 40;
            rect.right =  rect.left + 15;
            rect.bottom =  rect.top + 15;
            OffsetRect(&rect , 12 + cx , 12 + cy);
            if (t != 0 )
            {
                ch[0] = t + '0';
                DrawText(hDC , ch , 1 , &rect , DT_CENTER);
            }
            else
            {
                ch[0] = ch[1] = ' ';
                DrawText(hDC , ch , 2 , &rect , DT_CENTER);
            }
        }
    }
   
    // Draw target number
    cx = clientrect.right / 2 + 60 ;
    tcount = 0;
    for ( i = 0 ; i < 3 ; i ++)
    {
        for ( j = 0 ; j < 3 ; j ++)
        {
            int t = m_iTargetChess[tcount++];
            rect.left = j * 40;
            rect.top = i * 40;
            rect.right =  rect.left + 15;
            rect.bottom =  rect.top + 15;
            OffsetRect(&rect , 12 + cx , 12 + cy);
            if (t != 0 )
            {
                ch[0] = t + '0';
                DrawText(hDC , ch , 1 , &rect , DT_CENTER);
            }
            else
            {
                ch[0] = ch[1] = ' ';
                DrawText(hDC , ch , 2 , &rect , DT_CENTER);
            }
        }
    }
    SetBkColor(hDC , oldbkcolor);
}

void CNineGrid::Reset()
{
    if(m_bAutoRun) return;
    vector<int> vs;
    int i;
    for (i = 1 ; i < 9 ; i ++)
        vs.push_back(i);
    vs.push_back(0);
    random_shuffle(vs.begin(), vs.end());
    random_shuffle(vs.begin(), vs.end());
    for ( i = 0 ; i < 9 ; i ++)
    {
        m_iChess[i] = vs[i];
    }
   
    if (!EstimateUncoil(m_iChess))
    {
        unsigned char array[9] = {1,2,3,8,0,4,7,6,5};
        memcpy(m_iTargetChess , array , 9);
    }
    else
    {
        unsigned char array[9] = {1,2,3,4,5,6,7,8,0};
        memcpy(m_iTargetChess , array , 9);
    }

    m_iStepCount = 0;
    m_hasFeel = false;
}

void CNineGrid::MoveChess(int way)
{
    MoveChess(m_iChess , way);
}

void CNineGrid::OnButton(POINT pnt , HWND hWin)
{
    if (PtInRect(&m_rResetButton , pnt))
    {
        Reset();
    }
    else if (PtInRect(&m_rAutoButton , pnt))
    {
        ActiveShaw(hWin);
    }
}

void CNineGrid::GetResultList()
{
    ::ofstream ofs;
    ofs.open("result.html");
    ofs.write("<html><body>",12);
    CString strTemp = "";
    strTemp = "<table style='border:0px'><tr>";
    ofs.write(strTemp,strTemp.GetLength());   
    for ( int i = this->m_iPathsize ; i > 0 ; i --)
    {
        strTemp.Format("<td>第%d步</td><td><table style='border:1px solid blue;'>",this->m_iPathsize - i + 1);
        //strTemp.Format("<td><table style='border:1px solid blue;'>");
        ofs.write(strTemp,strTemp.GetLength());   
        for(int k=0;k<3;k++)
        {
            ofs.write("<tr>",4);       
            //ofs.write(strTemp,strTemp.GetLength());
            for(int j=0;j<3;j++)
            {
                if(this->m_pPathList[i].Path[k*3+j]+'0' != '0')
                {
                    strTemp.Format("<td background='bg.gif' style='line-height:30px;'>&nbsp;%s&nbsp;</td>",CString(this->m_pPathList[i].Path[k*3+j]+'0'));
                }
                else
                {
                    strTemp.Format("<td background='bg.gif' style='line-height:30px;'>&nbsp;&nbsp;&nbsp;</td>",CString(this->m_pPathList[i].Path[k*3+j]+'0'));
                }
                ofs.write(strTemp,strTemp.GetLength());   
            }
            ofs.write("</tr>",5);
        }
        ofs.write("</table></td>",13);   
    }
    ofs.write("</td></tr></table>",18);
    ofs.write("</html></body>",14);
    ofs.close();
    this->m_bAutoRun = false;
}
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值