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();
}
}
}
}
6x6的格子意味着你恐怕永远也不会输。
顺带编写一个自动玩2048的程序出来?
页:
[1]