元始天尊 发表于 2014-5-22 18:22:23

MFC写的2048


看到0xAA55的Dos版2048,突发奇想搞了个MFC的2048,基本上是模拟了原游戏吧,还是很容易的,只有不到500行代码。。。
这也是我的习惯,我用的代码量还是很少的// 2048Dlg.cpp : implementation file
//

#include "stdafx.h"
#include "2048.h"
#include "2048Dlg.h"
#include <stdlib.h>
#include <time.h>
#include <vector>
using namespace std;

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

CMy2048Dlg::CMy2048Dlg(CWnd* pParent /*=NULL*/)
    : CDialog(CMy2048Dlg::IDD, pParent)
{
    //{{AFX_DATA_INIT(CMy2048Dlg)
      // NOTE: the ClassWizard will add member initialization here
    //}}AFX_DATA_INIT
    // Note that LoadIcon does not require a subsequent DestroyIcon in Win32
    m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CMy2048Dlg::DoDataExchange(CDataExchange* pDX)
{
    CDialog::DoDataExchange(pDX);
    //{{AFX_DATA_MAP(CMy2048Dlg)
      // NOTE: the ClassWizard will add DDX and DDV calls here
    //}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CMy2048Dlg, CDialog)
    //{{AFX_MSG_MAP(CMy2048Dlg)
    ON_WM_SYSCOMMAND()
    ON_WM_PAINT()
    ON_WM_QUERYDRAGICON()
    ON_WM_KEYUP()
    //}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CMy2048Dlg message handlers

BOOL CMy2048Dlg::OnInitDialog()
{
    CDialog::OnInitDialog();

    // Set the icon for this dialog.The framework does this automatically
    //when the application's main window is not a dialog
    SetIcon(m_hIcon, TRUE);                        // Set big icon
    SetIcon(m_hIcon, FALSE);                // Set small icon
   
    // TODO: Add extra initialization here
    srand(time(NULL));
    InitGame();

    return TRUE;// return TRUEunless you set the focus to a control
}

// If you add a minimize button to your dialog, you will need the code below
//to draw the icon.For MFC applications using the document/view model,
//this is automatically done for you by the framework.

#define RRGB(x,y,z) (RGB(0xFF-x,0xFF-y,0xFF-z))

COLORREF getColor(int val)
{
    switch(val)
    {
      case 0x0:
            return RRGB(0x00,0x00,0x00);
      case 0x2:
            return RRGB(0x00,0x00,0x50);
      case 0x4:
            return RRGB(0x00,0x00,0xA0);
      case 0x8:
            return RRGB(0x00,0x00,0xF0);
      case 0x10:
            return RRGB(0x00,0x50,0x00);
      case 0x20:
            return RRGB(0x00,0x50,0x50);
      case 0x40:
            return RRGB(0x00,0x50,0xA0);
      case 0x80:
            return RRGB(0x00,0x50,0xF0);
      case 0x100:
            return RRGB(0x00,0xA0,0x00);
      case 0x200:
            return RRGB(0x00,0xA0,0x50);
      case 0x400:
            return RRGB(0x00,0xA0,0xA0);
      case 0x800:
            return RRGB(0x00,0xA0,0xF0);
      case 0x1000:
            return RRGB(0x00,0xF0,0x00);
      case 0x2000:
            return RRGB(0x00,0xF0,0x50);
      case 0x4000:
            return RRGB(0x00,0xF0,0xA0);
      case 0x8000:
            return RRGB(0x00,0xF0,0xF0);

      default:
            return RRGB(0xFF,0xFF,0xFF);
    }
}

void CMy2048Dlg::OnPaint()
{
    if (IsIconic())
    {
      CPaintDC dc(this); // device context for painting

      SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

      // Center icon in client rectangle
      int cxIcon = GetSystemMetrics(SM_CXICON);
      int cyIcon = GetSystemMetrics(SM_CYICON);
      CRect rect;
      GetClientRect(&rect);
      int x = (rect.Width() - cxIcon + 1) / 2;
      int y = (rect.Height() - cyIcon + 1) / 2;

      // Draw the icon
      dc.DrawIcon(x, y, m_hIcon);
    }
    else
    {
      CPaintDC dc(this);
      RECT rt;
      GetClientRect(&rt);

      int celllen=rt.right/SIZE;
      int cellhei=rt.bottom/SIZE;
      for(int i=0;i<SIZE;i++)
      {
            for(int j=0;j<SIZE;j++)
            {
                CPen pen(PS_SOLID,1,RGB(255,0,0));
                dc.SelectObject(pen);
                CBrush brush(getColor(Data));
                dc.SelectObject(brush);
                RECT rts={j*celllen,i*cellhei,j*celllen+celllen,i*cellhei+cellhei};
                dc.Rectangle(&rts);

                if(Data)
                {
                  char buffer;
                  itoa(Data,buffer,10);
                  
                  CFont font;
                  font.CreateFont(50,0,0,0,FW_NORMAL,FALSE,FALSE,0,ANSI_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,
                        DEFAULT_QUALITY,DEFAULT_PITCH|FF_SWISS,"Arial");
                  dc.SelectObject(font);
                  dc.SetTextColor(RGB(255,0,0));
                  dc.DrawText(buffer,&rts,DT_CENTER|DT_VCENTER|DT_SINGLELINE);
                }
            }
      }
      
    }
}

void CMy2048Dlg::InitGame()
{
    scroll=0;
    int* curData=(int*)Data;
    for(int i=0;i<SIZE*SIZE;i++)
    {
      curData=0;
    }
    GetLeftCellsToRandomPlace();
}

BOOL CMy2048Dlg::GetLeftCellsToRandomPlace()
{
    int* curData=(int*)Data;
    vector<int> left;
    for(int i=0;i<SIZE*SIZE;i++)
    {
      if(!curData)
            left.push_back(i);
    }
    if(left.size() == 0)
      return FALSE;

    int sel=rand()%left.size();
    if(rand()%4)
      curData]=2;
    else
      curData]=4;

    RECT rt;
    GetClientRect(&rt);
    Invalidate(FALSE);

    return TRUE;
}

BOOL CMy2048Dlg::Judge()
{
    int i,j;
    for(i=0;i<SIZE;i++)
    {
      for(j=0;j<SIZE;j++)
      {
            if(Data == 0)
                return TRUE;
            if(i+1<SIZE && Data == Data)
                return TRUE;
            if(j+1<SIZE && Data == Data)
                return TRUE;
      }
    }
    for(i=0;i<SIZE;i++)
    {
      for(j=0;j<SIZE;j++)
      {
            if(Data == 0)
                return TRUE;
      }
    }
    return FALSE;
}

BOOL CMy2048Dlg::Combine(UINT direction)
{
    BOOL moved=FALSE;
    switch(direction)
    {
      case VK_LEFT:
            {
                for(int l=0;l<SIZE;l++)
                {
                  //两两向左合并
                  int first=0,second;
                  boolean over=false;
                  while(first<SIZE && !over)
                  {
                        while(first<SIZE-1 && Data == 0)
                            first++;
                        
                        if(first>=SIZE-1)
                        {
                            over=true;
                            break;
                        }

                        second=first+1;
                        while(second<SIZE && Data == 0)
                            second++;

                        if(second>=SIZE)
                        {
                            over=true;
                            break;
                        }

                        if(Data == Data)
                        {
                            Data += Data;
                            Data=0;
                            moved=TRUE;
                            first=second+1;
                        }
                        else
                        {
                            first=second;
                        }
                  }
                  
                  //全部向左聚集
                  first=0;
                  while(Data)
                        first++;//找到第一个空白处
                  if(first<SIZE)
                  {
                        second=first+1;
                        while(second<SIZE)
                        {//找到下一个有值处      
                            while(second<SIZE && Data == 0)
                            {
                              second++;
                            }
                            if(second<SIZE)
                            {
                              Data=Data;
                              Data=0;
                              first++;
                              second++;
                              moved=TRUE;
                            }
                        }
                  }
                }
            }
            break;

      case VK_RIGHT:
            {
                for(int l=0;l<SIZE;l++)
                {
                  //两两向右合并
                  int first=0,second;
                  boolean over=false;
                  while(first<SIZE && !over)
                  {
                        while(first<SIZE-1 && Data == 0)
                            first++;
                        
                        if(first>=SIZE-1)
                        {
                            over=true;
                            break;
                        }
                        
                        second=first+1;
                        while(second<SIZE && Data == 0)
                            second++;
                        
                        if(second>=SIZE)
                        {
                            over=true;
                            break;
                        }
                        
                        if(Data == Data)
                        {
                            Data += Data;
                            Data=0;
                            moved=TRUE;
                            first=second+1;
                        }
                        else
                        {
                            first=second;
                        }
                  }
                  
                  //全部向右聚集
                  first=0;
                  while(Data)
                        first++;//找到第一个空白处
                  if(first<SIZE)
                  {
                        second=first+1;
                        while(second<SIZE)
                        {//找到下一个有值处      
                            while(second<SIZE && Data == 0)
                            {
                              second++;
                            }
                            if(second<SIZE)
                            {
                              Data=Data;
                              Data=0;
                              first++;
                              second++;
                              moved=TRUE;
                            }
                        }
                  }
                }
            }
            break;

      case VK_UP:
            {
                for(int c=0;c<SIZE;c++)
                {
                  //两两向上合并
                  int first=0,second;
                  boolean over=false;
                  while(first<SIZE && !over)
                  {
                        while(first<SIZE-1 && Data == 0)
                            first++;
                        
                        if(first>=SIZE-1)
                        {
                            over=true;
                            break;
                        }
                        
                        second=first+1;
                        while(second<SIZE && Data == 0)
                            second++;
                        
                        if(second>=SIZE)
                        {
                            over=true;
                            break;
                        }
                        
                        if(Data == Data)
                        {
                            Data += Data;
                            Data=0;
                            moved=TRUE;
                            first=second+1;
                        }
                        else
                        {
                            first=second;
                        }
                  }
                  
                  //全部向上聚集
                  first=0;
                  while(Data)
                        first++;//找到第一个空白处
                  if(first<SIZE)
                  {
                        second=first+1;
                        while(second<SIZE)
                        {//找到下一个有值处      
                            while(second<SIZE && Data == 0)
                            {
                              second++;
                            }
                            if(second<SIZE)
                            {
                              Data=Data;
                              Data=0;
                              first++;
                              second++;
                              moved=TRUE;
                            }
                        }
                  }
                }
            }
            break;

      case VK_DOWN:
            {
                for(int c=0;c<SIZE;c++)
                {
                  //两两向右合并
                  int first=0,second;
                  boolean over=false;
                  while(first<SIZE && !over)
                  {
                        while(first<SIZE-1 && Data == 0)
                            first++;
                        
                        if(first>=SIZE-1)
                        {
                            over=true;
                            break;
                        }
                        
                        second=first+1;
                        while(second<SIZE && Data == 0)
                            second++;
                        
                        if(second>=SIZE)
                        {
                            over=true;
                            break;
                        }
                        
                        if(Data == Data)
                        {
                            Data += Data;
                            Data=0;
                            moved=TRUE;
                            first=second+1;
                        }
                        else
                        {
                            first=second;
                        }
                  }
                  
                  //全部向右聚集
                  first=0;
                  while(Data)
                        first++;//找到第一个空白处
                  if(first<SIZE)
                  {
                        second=first+1;
                        while(second<SIZE)
                        {//找到下一个有值处      
                            while(second<SIZE && Data == 0)
                            {
                              second++;
                            }
                            if(second<SIZE)
                            {
                              Data=Data;
                              Data=0;
                              first++;
                              second++;
                              moved=TRUE;
                            }
                        }
                  }
                }
            }
            break;
    }
    return moved;
}

void CMy2048Dlg::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags)
{
    if(nChar >= VK_LEFT && nChar <= VK_DOWN)
    {
      if(Combine(nChar))
      {
            GetLeftCellsToRandomPlace();
            scroll+=100;
            if(!Judge())
            {
                CString str;
                if(scroll < 2048)
                  str.Format("失败! 最终得分:%d",scroll);
                else
                  str.Format("恭喜! 最终得分:%d",scroll);
                AfxMessageBox(str);
                InitGame();
            }
      }
    }
}

0xAA55 发表于 2014-5-23 22:56:54

6x6的格子意味着你恐怕永远也不会输。
顺带编写一个自动玩2048的程序出来?
页: [1]
查看完整版本: MFC写的2048