您的位置:首页 > 其它

2048游戏破解程序(源码)

2014-04-26 10:39 183 查看
前两天一时兴起,用VS2008写了个“破解”2048游戏的程序,这里用引号是因为还没有完全破解,算法需要改进。由于又要开始忙了,不能再深入探究,所以把它放上来希望有更多的人一起研究。

首先肯定是要获取图像了,在这里我也没用摄像头来获取,因为并不是所有人都有摄像头,这个程序我们用屏幕捕捉就够用了。获取图像后就是要知道当前的数据了,一开始想着用字符识别的,后来仔细想想,这个程序可以不需要字符识别,通过判断区域颜色就可以了,若不放心可以做一下灰度直方图,提高稳定性。得到数据后就该分析如何移动了,这才是本文最关心的,我的算法思想是,计算移动的有效值,这个有效值不是单一的最大数,也不是单一的空格数最多,而是这两个数与其权值乘积的和,在递归调用时,随着深度的加深,对这些权值做一定的衰减处理。这个方法在一定程度上计算可以验证是正确的,但有些时候不太理想,特别在合成的数越大时越明显,可能我设置的参数不够好吧。我在程序中没有加入分布系数(数的分布,越密集权值应越大),也没有加入路径规划(而是用了递归,本来递归遍历可以不用路径规划的,但由于我加入了权系数,所以递归的作用没有完全表现出来)。好了就讲这么多了,希望有兴趣的一起交流。

源码下载



源码如下

源码中可能有很多地方是多余的,这可能是我在调试的时候尝试过的方法,不行后没有完全将其删除

// game2048Dlg.cpp : implementation file

//

#include "stdafx.h"

#include "game2048.h"

#include "game2048Dlg.h"

#ifdef _DEBUG

#define new DEBUG_NEW

#endif

const char* strmove[] = {"无","上","下","左","右"};

// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog

{

public:

CAboutDlg();

// Dialog Data

enum { IDD = IDD_ABOUTBOX };

protected:

virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support

// Implementation

protected:

DECLARE_MESSAGE_MAP()

};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)

{

}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)

{

CDialog::DoDataExchange(pDX);

}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)

END_MESSAGE_MAP()

// Cgame2048Dlg dialog

Cgame2048Dlg::Cgame2048Dlg(CWnd* pParent /*=NULL*/)

: CDialog(Cgame2048Dlg::IDD, pParent)

, m_pBackBitmap(NULL)

, startx(0)

, starty(0)

, endx(0)

, endy(0)

, maxnum(0)

, imgwidth(0)

, imgheight(0)

, pbitmap(NULL)

{

m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);

}

void Cgame2048Dlg::DoDataExchange(CDataExchange* pDX)

{

CDialog::DoDataExchange(pDX);

}

BEGIN_MESSAGE_MAP(Cgame2048Dlg, CDialog)

ON_WM_SYSCOMMAND()

ON_WM_PAINT()

ON_WM_QUERYDRAGICON()

//}}AFX_MSG_MAP

ON_WM_MOUSEMOVE()

ON_WM_LBUTTONDOWN()

ON_BN_CLICKED(IDC_BUTTON1, &Cgame2048Dlg::OnBnClickedButton1)

ON_WM_TIMER()

ON_BN_CLICKED(IDC_BUTTON2, &Cgame2048Dlg::OnBnClickedButton2)

ON_WM_CLOSE()

ON_BN_CLICKED(IDC_BUTTON3, &Cgame2048Dlg::OnBnClickedButton3)

END_MESSAGE_MAP()

// Cgame2048Dlg message handlers

BOOL Cgame2048Dlg::OnInitDialog()

{

CDialog::OnInitDialog();

// Add "About..." menu item to system menu.

// IDM_ABOUTBOX must be in the system command range.

ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);

ASSERT(IDM_ABOUTBOX < 0xF000);

CMenu* pSysMenu = GetSystemMenu(FALSE);

if (pSysMenu != NULL)

{

CString strAboutMenu;

strAboutMenu.LoadString(IDS_ABOUTBOX);

if (!strAboutMenu.IsEmpty())

{

pSysMenu->AppendMenu(MF_SEPARATOR);

pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);

}

}

// 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

m_strLog.Empty();

//startx = 490;

//starty = 170;

//endx = 990;//::GetSystemMetrics(SM_CXSCREEN);

//endy = 670;//::GetSystemMetrics(SM_CYSCREEN);

//imgwidth = endx - startx;

//imgheight = endy - starty;

rgb = NULL;

//rgb = new ARGB[imgwidth*imgheight];// 0xaabbggrr

ZeroMemory(prematrix,sizeof(int)*4*4);

int i = 0;

numcolor[i++] = Color(255,204,192,179).GetValue();//ARGB

numcolor[i++] = Color(255,238,228,218).GetValue();// 2

numcolor[i++] = Color(255,237,224,200).GetValue();// 4

numcolor[i++] = Color(255,242,177,121).GetValue();// 8

numcolor[i++] = Color(255,245,149,99).GetValue();// 16

numcolor[i++] = Color(255,246,124,95).GetValue();// 32

numcolor[i++] = Color(255,246,94,59).GetValue();// 64

numcolor[i++] = Color(255,237,207,114).GetValue();// 128

numcolor[i++] = Color(255,237,204,97).GetValue();// 256

numcolor[i++] = Color(255,237,200,80).GetValue();// 512

numcolor[i++] = Color(255,237,197,63).GetValue();// 1024

numcolor[i++] = Color(255,238,194,46).GetValue();// 2048

for (;i<17;i++)

{

numcolor[i] = 0;

}

return TRUE; // return TRUE unless you set the focus to a control

}

void Cgame2048Dlg::OnSysCommand(UINT nID, LPARAM lParam)

{

if ((nID & 0xFFF0) == IDM_ABOUTBOX)

{

CAboutDlg dlgAbout;

dlgAbout.DoModal();

}

else

{

CDialog::OnSysCommand(nID, lParam);

}

}

// 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.

void Cgame2048Dlg::OnPaint()

{

if (IsIconic())

{

CPaintDC dc(this); // device context for painting

SendMessage(WM_ICONERASEBKGND, reinterpret_cast<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

{

Point pts[3];

CRect rect;

CDC *pdc = GetDlgItem(IDC_IMAGE)->GetDC();

Graphics graph(pdc->GetSafeHdc());

GetDlgItem(IDC_IMAGE)->GetClientRect(&rect);

Image image(_T("g2048.bmp"));

graph.DrawImage(&image,rect.left,rect.top,rect.right-rect.left,rect.bottom-rect.top);// 显示图像

CDialog::OnPaint();

}

}

// The system calls this function to obtain the cursor to display while the user drags

// the minimized window.

HCURSOR Cgame2048Dlg::OnQueryDragIcon()

{

return static_cast<HCURSOR>(m_hIcon);

}

void Cgame2048Dlg::OnMouseMove(UINT nFlags, CPoint point)

{

// TODO: Add your message handler code here and/or call default

CDialog::OnMouseMove(nFlags, point);

}

void Cgame2048Dlg::OnLButtonDown(UINT nFlags, CPoint point)

{

// TODO: Add your message handler code here and/or call default

// 鼠标框出目标区域

CDialog::OnLButtonDown(nFlags, point);

}

void Cgame2048Dlg::CaptureScreen2(int xStartPt, int yStartPt, int width, int height, int xToCopy, int yToCopy)

{

if (m_pBackBitmap != NULL)

{

delete m_pBackBitmap;

m_pBackBitmap = NULL;

}

m_pBackBitmap = new CBitmap();

CDC ScrDC,MemDC;

ScrDC.CreateDC(_T("DISPLAY"), NULL, NULL, NULL);

MemDC.CreateCompatibleDC(&ScrDC);

m_pBackBitmap->CreateCompatibleBitmap(&ScrDC,width,height);

MemDC.SelectObject(m_pBackBitmap); //开始拷贝

MemDC.BitBlt(xStartPt, yStartPt, width, height,&ScrDC,xToCopy,yToCopy,SRCCOPY);

ScrDC.DeleteDC();

MemDC.DeleteDC();

}

void Cgame2048Dlg::CaptureScreen(void)

{

CDC ScrDC;

ScrDC.CreateDC(_T("DISPLAY"), NULL, NULL, NULL);

if (pbitmap != NULL)

{

::delete pbitmap;

pbitmap = NULL;

}

pbitmap = ::new Bitmap((HBITMAP)::GetCurrentObject(ScrDC, OBJ_BITMAP),NULL);

ScrDC.DeleteDC();

}

int Cgame2048Dlg::GetEndcoderClsid(const WCHAR * format, CLSID * pClsid)

{

UINT num = 0;

UINT size = 0;

ImageCodecInfo *pimagecodeinfo = NULL;

GetImageEncodersSize(&num,&size);

if (size == 0)

{

return -1;

}

pimagecodeinfo = (ImageCodecInfo*)(malloc(size));

if (pimagecodeinfo == NULL)

{

return -1;

}

GetImageEncoders(num,size,pimagecodeinfo);

for (UINT i = 0;i<num;++i)

{

if (wcscmp(pimagecodeinfo[i].MimeType,format)==0)

{

*pClsid = pimagecodeinfo[i].Clsid;

free(pimagecodeinfo);

return i;

}

}

free(pimagecodeinfo);

return -1;

}

void Cgame2048Dlg::OnBnClickedButton1()

{

// TODO: Add your control notification handler code here

imgwidth = endx - startx;

imgheight = endy - starty;

//SetWindowPos(&this->wndNoTopMost,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE);

SetWindowPos(&this->wndTopMost,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE);

#if 1

int i,j;

CaptureScreen();

int t1 = GetTickCount();

int scrnwidth,scrnheight;

scrnwidth = ::GetSystemMetrics(SM_CXSCREEN);

scrnheight = ::GetSystemMetrics(SM_CYSCREEN);

Color color;

Rect imgrect(0, 0, scrnwidth,scrnheight);

BitmapData* bitmapData = new BitmapData;

pbitmap->LockBits(&imgrect,ImageLockModeRead,PixelFormat32bppARGB,bitmapData);

UINT* pixels = (UINT*)bitmapData->Scan0;

ARGB* argb1 = new ARGB[scrnwidth*scrnheight];

int stride = bitmapData->Stride / 4;

//for (i=0;i<imgheight;i++)

//{

// for (j=0;j<imgwidth;j++)

// {

// rgb[i*imgwidth + j] = pixels[i * stride + j];

// }

//}

memcpy(argb1,pixels,sizeof(UINT)*scrnwidth*scrnheight);

pbitmap->UnlockBits(bitmapData);

delete bitmapData;

ARGB blockcolor = Color(255,187,173,160).GetValue();//ARGB

imgheight = 0;

imgwidth = 0;

for(i=0;i<scrnheight;i++)

{

int h=0,w=0;

for(j=0;j<scrnwidth;j++)

{

if(argb1[i*scrnwidth + j] == blockcolor)

{

w++;

if(w > imgwidth)

{

imgwidth = w;

starty = i-5;

}

}

else

w = 0;

}

}

for(i=0;i<scrnwidth;i++)

{

int h=0,w=0;

for(j=0;j<scrnheight;j++)

{

if(argb1[i + scrnwidth * j] == blockcolor)

{

h++;

if(h > imgheight)

{

imgheight = h;

startx = i-5;

}

}

else

h = 0;

}

}

delete[] argb1;

if(imgwidth < 400 || imgheight < 400)

{

MessageBox(_T("获取游戏区域错误"));

return;

}

endx = imgwidth + startx;

endy = imgheight + starty;

if(rgb != NULL)

delete[] rgb;

rgb = new ARGB[imgwidth*imgheight];

CString str;

str.Format(_T("耗时: %d"),GetTickCount() - t1);

//MessageBox(str);

//graph.DrawImage(pbitmap,rect.left,rect.top,rect.right-rect.left,rect.bottom-rect.top);// 显示图像

#endif

//CaptureScreen(0, 0, ::GetSystemMetrics(SM_CXSCREEN), ::GetSystemMetrics(SM_CYSCREEN), 0, 0);

int scrn_w = ::GetSystemMetrics(SM_CXSCREEN);

int scrn_h = ::GetSystemMetrics(SM_CYSCREEN);

mouse_event(MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE, startx*65536/scrn_w,starty*65536/scrn_h,0, 0); //

mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP,0,0,0,0);

CString strTime;

CTime CurrentTime=CTime::GetCurrentTime();

strTime = CurrentTime.Format(_T("%Y%m%d_%H%M%S 开始游戏\r\n"));

Logging(strTime);

SetTimer(MAIN_TIMER_ID,500,NULL);

}

bool Cgame2048Dlg::SaveBitmapToFile(CBitmap* bitmap, CString lpFileName)

{

HBITMAP hBitmap;// 为刚才的屏幕位图句柄

HDC hDC; //设备描述表

int iBits; //当前显示分辨率下每个像素所占字节数

WORD wBitCount; //位图中每个像素所占字节数

DWORD dwPaletteSize = 0, //定义调色板大小

dwBmBitsSize, //位图中像素字节大小

dwDIBSize,
//位图文件大小

dwWritten; //写入文件字节数

BITMAP Bitmap; //位图属性结构

BITMAPFILEHEADER bmfHdr; //位图文件头结构

BITMAPINFOHEADER bi; //位图信息头结构

LPBITMAPINFOHEADER lpbi; //指向位图信息头结构

HANDLE fh,
//定义文件

hDib, //分配内存句柄

hPal, //调色板句柄

hOldPal = NULL;

//计算位图文件每个像素所占字节数

hBitmap = (HBITMAP)*bitmap;

hDC = CreateDC(_T("DISPLAY"),NULL,NULL,NULL);

iBits =
GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES);

DeleteDC(hDC);

if (iBits <= 1)

wBitCount =
1;

else if
(iBits <= 4)

wBitCount =
4;

else if (iBits <= 8)

wBitCount =
8;

else if
(iBits <= 24)

wBitCount =
24;

else if (iBits <= 32)

wBitCount = 32;

//计算调色板大小

if (wBitCount <= 8)

dwPaletteSize =(1 << wBitCount) * sizeof (RGBQUAD);

//设置位图信息头结构

GetObject(hBitmap, sizeof (BITMAP), (LPSTR)&Bitmap);

bi.biSize = sizeof (BITMAPINFOHEADER);

bi.biWidth = Bitmap.bmWidth;

bi.biHeight = Bitmap.bmHeight;

bi.biPlanes = 1;

bi.biBitCount =wBitCount;

bi.biCompression = BI_RGB;

bi.biSizeImage = 0;

bi.biXPelsPerMeter = 0;

bi.biYPelsPerMeter = 0;

bi.biClrUsed = 0;

bi.biClrImportant = 0;

dwBmBitsSize = ((Bitmap.bmWidth * wBitCount+31) / 32) * 4 * Bitmap.bmHeight;

//为位图内容分配内存

hDib = GlobalAlloc(GHND, dwBmBitsSize + dwPaletteSize + sizeof (BITMAPINFOHEADER));

lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib);

*lpbi =
bi;

// 处理调色板

hPal = GetStockObject(DEFAULT_PALETTE);

if (hPal)

{

hDC = ::GetDC(NULL);

hOldPal = ::SelectPalette(hDC, (HPALETTE)hPal, FALSE);

RealizePalette(hDC);

}

// 获取该调色板下新的像素值

GetDIBits(hDC, hBitmap,0, (UINT) Bitmap.bmHeight,

(LPSTR)lpbi + sizeof (BITMAPINFOHEADER)+ dwPaletteSize,

(LPBITMAPINFO)lpbi,DIB_RGB_COLORS);

//恢复调色板

if (hOldPal)

{

SelectPalette(hDC, (HPALETTE)hOldPal, TRUE);

RealizePalette(hDC);

::ReleaseDC(NULL, hDC);

}

//创建位图文件

fh = CreateFile(lpFileName, GENERIC_WRITE,

0, NULL, CREATE_ALWAYS,

FILE_ATTRIBUTE_NORMAL |FILE_FLAG_SEQUENTIAL_SCAN, NULL);

if (fh == INVALID_HANDLE_VALUE)

return FALSE;

// 设置位图文件头

bmfHdr.bfType =0x4D42;
//"BM"

dwDIBSize = sizeof (BITMAPFILEHEADER)

+ sizeof (BITMAPINFOHEADER)

+ dwPaletteSize+ dwBmBitsSize;

bmfHdr.bfSize =dwDIBSize;

bmfHdr.bfReserved1 = 0;

bmfHdr.bfReserved2 = 0;

bmfHdr.bfOffBits = (DWORD)sizeof (BITMAPFILEHEADER)

+ (DWORD)sizeof (BITMAPINFOHEADER)

+ dwPaletteSize;

// 写入位图文件头

WriteFile(fh, (LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER), &dwWritten,NULL);

// 写入位图文件其余内容

WriteFile(fh, (LPSTR)lpbi, dwDIBSize,&dwWritten, NULL);

//清除

GlobalUnlock(hDib);

GlobalFree(hDib);

CloseHandle(fh);

return TRUE;

}

// 返回:1、2 、3、4 对应 上下左右,返回0则表示无法移动

int Cgame2048Dlg::calc_move(int* num)

{

if (num == NULL)

return 0;

int mernum[4][4*4];// 四个方向合成后的数据

int i2p1[4][4*4];// 新增2 可能的位置

int empty = 0,maxnum = 0;

double mermax[4]={0};

int merempty[4]={0};

int movedir=0,defmov=0;// 小于0 表示不能移动

int i,j,k;

for(i=0;i<4*4;i++)

{

if(num[i] == 0)

empty++;

else if(maxnum < num[i])

maxnum = num[i];

}

for (i=0;i<4;i++)

{

memcpy(mernum[i],num,sizeof(int)*4*4);

if(1)//(maxnum < 9)

{

// 权值方法

mermax[i] = num_move(mernum[i],i+1,1);

}

else

{

num_move(mernum[i],i+1,1);

for (j=0;j<4*4;j++)

{

if(mernum[i][j] == 0)

merempty[i]++;

else if(mermax[i] < mernum[i][j])

mermax[i] = mernum[i][j];

}

if(memcmp(num,mernum[i],sizeof(int)*4*4)!=0)

defmov = i+1;

}

}

if(1)//(maxnum < 9)

{

double weight = -1;

for(i = 0;i<4;i++)

{

if(mermax[i] > weight)

{

movedir = i+1;

weight = mermax[i];

}

}

}

else

{

int* p = num; // 移动后的肯定要比移动前的优,不然算法是无效的,或已经无法再移动

for(i=0;i<4;i++)

{

if(MatrixCmp(mernum[i],p,4*4,maxnum)>0)// 应该是广义的最大值,除了值 的大小,还有值的合成度

{

movedir = i+1;

p = mernum[i];

}

}

}

if(movedir==0)

movedir = defmov;

return movedir;

}

int Cgame2048Dlg::get_dir_move(int* num, int dir)

{

int ret = 1;

switch(dir)

{

case 1:// up 有些时候,有0存在的时候也能移动

if( num[0]&&num[1]&&num[2]&&num[3])

return 1;

else

{

if((num[0] == 0)&&(num[1]||num[2]||num[3]))

ret = 0;

if((num[1] == 0)&&(num[0]||num[2]||num[3]))

ret = 0;

if((num[2] == 0)&&(num[1]||num[0]||num[3]))

ret = 0;

if((num[3] == 0)&&(num[1]||num[2]||num[0]))

ret = 0;

}

break;

case 2:// down

if( num[12]&&num[13]&&num[14]&&num[15])

return 1;

else

{

if((num[12] == 0)&&(num[13]||num[14]||num[15]))

ret = 0;

if((num[13] == 0)&&(num[12]||num[14]||num[15]))

ret = 0;

if((num[14] == 0)&&(num[12]||num[13]||num[15]))

ret = 0;

if((num[15] == 0)&&(num[12]||num[13]||num[14]))

ret = 0;

}

break;

case 3:// left

if( num[0]&&num[4]&&num[8]&&num[12])

return 1;

else

{

if((num[0] == 0)&&(num[4]||num[8]||num[12]))

ret = 0;

if((num[4] == 0)&&(num[0]||num[8]||num[12]))

ret = 0;

if((num[8] == 0)&&(num[0]||num[4]||num[12]))

ret = 0;

if((num[12] == 0)&&(num[0]||num[4]||num[8]))

ret = 0;

}

break;

case 4:// right

if(num[3]&&num[7]&&num[11]&&num[15])

return 1;

else

{

if((num[3] == 0)&&(num[7]||num[11]||num[15]))

ret = 0;

if((num[7] == 0)&&(num[3]||num[11]||num[15]))

ret = 0;

if((num[11] == 0)&&(num[3]||num[7]||num[15]))

ret = 0;

if((num[15] == 0)&&(num[3]||num[7]||num[11]))

ret = 0;

}

break;

default:

return 0;

break;

}

return ret;

}

double Cgame2048Dlg::num_move(int* num, int dir, int cmove)

{

int change = -1;

double Weight = 0;

if (dir <= 0 || dir > 4 || num == NULL)

return 0;

int i,j,index;

int emp = 0,tmax=0;

// 先矩阵变换,然后统一处理

matrixchange(num,dir);

// 统一按上移处理

for (i=0;i<4;i++)

{

index = 0;

for (j=1;j<4;j++)

{

if(tmax < num[j*4+i])

tmax = num[j*4+i];

if (num[j*4+i] != 0)

{

if (num[index*4+i] == 0)

{

num[index*4+i] = num[j*4+i];

num[j*4+i] = 0;

if(change == -1)

change = 0;

}

else if(num[index * 4+i] == num[j*4+i])

{

Weight+=num[index*4+i]*num[index*4+i]*num[index*4+i];//x^2 , x^3 ,x^4, x^2*lg(cmove)或者多项式...

num[index*4+i]++;

index++;

num[j*4+i] = 0;

change++;

}

else

{

index++;

}

}

}

}

for(i=0;i<4*4;i++)

{

if(num[i] == 0)

{

emp++;

index=i;

}

}

if(emp==1)

{

num[index] = 1;// 补2 处理

}

// 在数据较大时应考虑路径规划,或调整相关系数

if(cmove > 0 && change >= 0&&cmove<6)// 因为组合移动6次足够了,不需要太多次

{

int mernum[4][4*4];// 四个方向合成后的数据

int tweight[4]={0};

cmove += 1;;// 防止死循环

// 四个方向继续移动

for(i=0;i<4;i++)

{

memcpy(mernum[i],num,sizeof(int)*4*4);

if(get_dir_move(mernum[i],i+1)) // 递归的时候应该考虑下2会出现的位置,也用相关数供稿计算

tweight[i] = num_move(mernum[i],i+1,cmove);

else

tweight[i] = num_move(mernum[i],i+1);

}

if(0)//(tmax >= 9)

{

int* tmar = mernum[0];

for(i=1;i<4;i++)

{

if(MatrixCmp(mernum[i],tmar,4*4,tmax)>0)

{

tmar = mernum[i];

}

}

memcpy(num,tmar,sizeof(int)*4*4);

}

else

{

double maxweight = 0;

for(i=0;i<4;i++)

{

if(maxweight < tweight[i])

maxweight = tweight[i];

}

maxweight = maxweight/(cmove*cmove);// x^2 x*lg(x) ...

Weight += maxweight;

}

}

// 还原矩阵

switch (dir)

{

case 1:

break;

case 2:

matrixchange(num,2);

break;

case 3:

matrixchange(num,4);

break;

case 4:

matrixchange(num,3);

break;

}

if(change < 0)

return change;

else

return Weight;

}

void Cgame2048Dlg::matrixchange(int* num, int dir)

{

int i,j;

int temp[4*4];

memcpy(temp,num,sizeof(int)*4*4);

switch (dir)

{

case 1:// 上移

// 默认处理方法,不处理

break;

case 2:// 下移

for (i=0;i<4;i++)

{

for (j=0;j<4;j++)

num[i*4+j] = temp[(3-i)*4+3-j];

}

break;

case 3:// 左移

for (i=0;i<4;i++)

{

for (j=0;j<4;j++)

num[i*4+j] = temp[(3-j)*4+i];

}

break;

case 4:// 右移

for (i=0;i<4;i++)

{

for (j=0;j<4;j++)

num[i*4+j] = temp[j*4+3-i];

}

break;

}

}

void Cgame2048Dlg::OnTimer(UINT_PTR nIDEvent)

{

// TODO: Add your message handler code here and/or call default

if(nIDEvent == MAIN_TIMER_ID)

{

KillTimer(MAIN_TIMER_ID);

int i,j;

int matrix[4*4];

CaptureScreen( );

Bitmap dispbitmap(imgwidth,imgheight,PixelFormat32bppARGB);

Rect imgrect(startx, starty, imgwidth, imgheight);

Rect dispimgrect(0, 0, imgwidth, imgheight);

BitmapData* bitmapData = new BitmapData;

BitmapData* dispbitmapData = new BitmapData;

pbitmap->LockBits(&imgrect,ImageLockModeRead,PixelFormat32bppARGB,bitmapData);

dispbitmap.LockBits(&dispimgrect,ImageLockModeWrite,PixelFormat32bppARGB,dispbitmapData);

UINT* pixels = (UINT*)bitmapData->Scan0;

UINT* disppixels = (UINT*)dispbitmapData->Scan0;

int stride = bitmapData->Stride / 4;

for (i=0;i<imgheight;i++)

{

for (j=0;j<imgwidth;j++)

{

rgb[i*imgwidth + j] = pixels[i * stride + j];

disppixels[i * stride + j] = pixels[i * stride + j];

}

}

pbitmap->UnlockBits(bitmapData);

dispbitmap.UnlockBits(dispbitmapData);

delete bitmapData;

delete dispbitmapData;

int w = 122;

int off = 30;

for (i=0;i<4;i++)

{

for (j=0;j<4;j++)

{

int k;

for (k=0;k<17;k++)

{

if(rgb[(i*w+ off)*imgwidth + j*w + off] == numcolor[k])

break;

}

if(k == 0)

{

matrix[i*4+j] = 0;

}

else if(k<17)

matrix[i*4+j] = k; // pow(2.0,1.0*k);

else if(maxnum < 17 && numcolor[maxnum]==0)// 合成较大的值,保存其颜色

{

numcolor[maxnum] = rgb[(i*w+ off)*imgwidth + j*w + off];

matrix[i*4+j] = maxnum;

}

else

{

// game over

//MessageBox(_T("识别出错"));

}

}

}

int movedir = calc_move(matrix);

CString log(_T("当前数据:\t"));

char strnum[200] = {0};

for (int i=0;i<4;i++)

{

if(i!=0)

sprintf(strnum,"%s\t\t",strnum);

for (int j=0;j<4;j++)

{

sprintf(strnum,"%s%4d ",strnum,matrix[i*4 + j]);

}

sprintf(strnum,"%s\r\n",strnum);

}

sprintf(strnum,"%s移动方向为:%s\r\n\r\n",strnum,strmove[movedir]);

log += strnum;

Logging(log);

switch (movedir)

{

case 1:

keybd_event(VK_UP,0,WM_KEYDOWN | WM_KEYUP,0);

break;

case 2:

keybd_event(VK_DOWN,0,WM_KEYDOWN | WM_KEYUP,0);

break;

case 3:

keybd_event(VK_LEFT,0,WM_KEYDOWN | WM_KEYUP,0);

break;

case 4:

keybd_event(VK_RIGHT,0,WM_KEYDOWN | WM_KEYUP,0);

break;

default :

break;

}

Point pts[3];

CRect rect;

CDC *pdc = GetDlgItem(IDC_IMAGE)->GetDC();

Graphics graph(pdc->GetSafeHdc());

GetDlgItem(IDC_IMAGE)->GetClientRect(&rect);

graph.DrawImage(&dispbitmap,rect.left,rect.top,rect.right-rect.left,rect.bottom-rect.top);// 显示图像

if(movedir >=1&&movedir<=4)

{

maxnum = 0;

num_move(matrix,movedir);

memcpy(prematrix,matrix,sizeof(int)*4*4);

for(int i=0;i<4*4;i++)

{

if(maxnum < prematrix[i])

maxnum = prematrix[i];

}

SetTimer(MAIN_TIMER_ID,400,NULL);

}

else

{

CString str;

CaptureScreen2(0,0,imgwidth,imgheight,startx,starty);

SaveBitmapToFile(m_pBackBitmap,_T("g2048.bmp"));

str.Format(_T("g2048_%d.bmp"),maxnum);

SaveBitmapToFile(m_pBackBitmap,str);

str.Format(_T("maxnum is %d"),maxnum);

Logging(str);

Logging(_T("game over"));

MessageBox(_T("game over"));

WriteLogToFile();

SetWindowPos(&this->wndNoTopMost,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE);

}

}

CDialog::OnTimer(nIDEvent);

}

void Cgame2048Dlg::OnBnClickedButton2()

{

// TODO: Add your control notification handler code here

KillTimer(MAIN_TIMER_ID);

KillTimer(CAP_TIMER_ID);

Logging(_T("用户停止"));

WriteLogToFile();

SetWindowPos(&this->wndNoTopMost,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE);

}

void Cgame2048Dlg::OnClose()

{

// TODO: Add your message handler code here and/or call default

Logging(_T("软件关闭"));

WriteLogToFile();

delete rgb;

CDialog::OnClose();

}

int Cgame2048Dlg::Logging(CString log)

{

if(m_strLog.GetLength()>20000)

WriteLogToFile( );

m_strLog += log + _T("\r\n");

return 0;

}

int Cgame2048Dlg::WriteLogToFile(void)

{

CString Filename,str;

CFile pfile;

Filename.Format(_T("log.txt"));

m_strLog = str + m_strLog;

if (!pfile.Open(Filename,CFile::modeWrite|CFile::modeRead|CFile::modeNoTruncate))

{

pfile.Open(Filename,CFile::modeWrite|CFile::modeRead|CFile::modeCreate|CFile::modeNoTruncate);

}

pfile.SeekToEnd();

#ifdef _UNICODE

USES_CONVERSION;

pfile.Write(W2CA(m_strLog),((CStringA)m_strLog).GetLength());

#else

pfile.Write(m_strLog,m_strLog.GetLength());

#endif

pfile.Close();

m_strLog.Empty();

return 0;

}

int Cgame2048Dlg::MatrixCmp(int* ma1, int* ma2, int n,int m)

{

int i;

int ret = 0;

int* tm1 = new int
;

int* tm2 = new int
;

int n1=0,n2=0;

memcpy(tm1,ma1,sizeof(int)*n);

memcpy(tm2,ma2,sizeof(int)*n);

SortInt(tm1,n);

SortInt(tm2,n);

// 移动后最大数和格子数都有可能不变,则再多考虑一步

// 或者移动后的整齐度,或者再多考虑一步能合成更大的数

// 或者多一步时消除的更多

// 优先处理

for(i = 0;i<n;i++)

{

if(tm1[i]!=0)

n1++;

if(tm2[i]!=0)

n2++;

}

//普通处理

//if(n1 == n2 || m >= 9)

if(n1 == n2 )

{

for(i = 0;i<n;i++)

{

// 综合判断

if(tm1[i] < tm2[i])

{

ret = -1;

break;

}

else if(tm1[i] > tm2[i])

{

ret = 1;

break;

}

}

}

else if(n1 < n2)

ret = 1;

else

ret = -1;

delete[] tm1;

delete[] tm2;

return ret;

}

void Cgame2048Dlg::SortInt(int* buf, int n)

{

int t;

for(int i=0;i<n;i++)

{

for(int j = i+1;j<n;j++)

{

if(buf[i] < buf[j])

{

t = buf[i];

buf[i] = buf[j];

buf[j] = t;

}

}

}

}

void Cgame2048Dlg::OnBnClickedButton3()

{

// TODO: Add your control notification handler code here

SetWindowPos(&this->wndTopMost,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE);

SetTimer(CAP_TIMER_ID,50,NULL);

}

由于是用了GDI+,所以在InitInstance( ) 函数中需要启动GDI+,即在该函数中加

GdiplusStartup(&m_GdiplusToken,&m_GdiplusStartupInput,NULL);

在ExitInstance() 加

GdiplusShutdown(m_GdiplusToken);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: