gdi写的2048

//-------------------------------------------【头文件及引用】----------------------------------------------------//
#include <Windows.h>
#include <time.h>
#include <stdlib.h>
#include <vector>
#include <map>
#include <string>
#include <iostream>
#pragma comment(lib,"winmm.lib")
#pragma comment(lib,"Msimg32.lib")
using namespace std;

//-------------------------------------------【宏定义】----------------------------------------------------------//
#define WINDOW_WIDTH 800
#define WINDOW_HEIGHT 600
#define WINDOW_TITLE  L"窗口"

//-------------------------------------------【全局变量声明部分】------------------------------------------------//
HDC g_hdc = NULL, g_mdc = NULL, g_bufdc = NULL;  //全局设备环境句柄
HBITMAP g_hBitMap = NULL, g_hNumber[7] = {NULL}; //位图句柄
HFONT g_hFont;//文字句柄

int Map[4][4];
int score;
const int WinFlag = 2048;
int IsOver;

struct node
{
	int ChangeMap[4][4];//操作后的数组
	int GetScore;//得分
	int flag;//操作是否成功
	node(int CM[][4], int scr, int f)
	{
		memcpy(ChangeMap, CM, sizeof ChangeMap);
		GetScore = scr;
		flag = f;
	}
	node() {}
};

//-------------------------------------------【全局函数声明部分】------------------------------------------------//
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
BOOL Game_Init(HWND hwnd);
VOID Game_Paint(HWND hwnd);
BOOL Game_CleanUp(HWND hwnd);

VOID Map_Init();
//四种操作(主要对数组进行旋转)
node up();
node down();
node left();
node right();
//统一转成左移后操作
node change(int a[4][4]);

void InsertNumber();//随机插入数字
int judge();//判断矩阵情况,0为无法继续移动,1为可以继续移动但未达到胜利标准,2为达到胜利标准

//-------------------------------------------【 main函数 】------------------------------------------------//
int main() {
	HINSTANCE hInstance = GetModuleHandle(NULL);
	int nShowCmd = true;
	WNDCLASSEX wndClass = {
		sizeof(WNDCLASSEX),
		CS_HREDRAW | CS_VREDRAW,
		WndProc,
		0L,
		0L,
		hInstance,
		(HICON)::LoadImage(NULL,L"icon.ico", IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_LOADFROMFILE),
		LoadCursor(NULL, IDC_ARROW),
		(HBRUSH)GetStockObject(GRAY_BRUSH),
		NULL,
		L"ForTheDream",//窗口类的名称
		NULL
	};
	if( !RegisterClassEx(&wndClass)) return -1;
	HWND hWnd = CreateWindow( L"ForTheDream", WINDOW_TITLE, WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT, CW_USEDEFAULT, WINDOW_WIDTH, WINDOW_HEIGHT, NULL, NULL, hInstance, NULL);
	MoveWindow(hWnd, 250, 80, WINDOW_WIDTH, WINDOW_HEIGHT, true);
	ShowWindow(hWnd, nShowCmd);
	UpdateWindow(hWnd);

	if(!Game_Init(hWnd)) return -1;

	//消息循环过程
	MSG msg = {0};
	while(msg.message != WM_QUIT) {
		if(PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) {
			TranslateMessage(&msg); //虚拟键消息转换成字符消息
			DispatchMessage(&msg); //分发一个消息给窗口程序
		}
		else
		{
			Game_Paint(hWnd);
		}
	}
	UnregisterClass(L"ForTheDream", wndClass.hInstance );//注销

	return 0;
}

//---------------------------------------【窗口过程函数WndProc( )部分】------------------------------------------//
//描述:窗口过程函数,对窗口消息进行处理
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
	//定义一个PAINTSTRUCT结构体来记录一些绘制信息
	PAINTSTRUCT paintStruct;
	switch(message) {
	case WM_KEYDOWN:
		{
			if(wParam == VK_ESCAPE)
			{
				if(MessageBox(hwnd, L"确认退出吗?", L"退出", MB_YESNO) == IDYES)
					DestroyWindow(hwnd);
			}
			else if((wParam == VK_UP || wParam == VK_DOWN ||wParam == VK_LEFT ||wParam == VK_RIGHT) && !IsOver)
			{
				node res;
				switch(wParam)
				{
				case VK_UP:
					res = up();
					break;
				case VK_DOWN:
					res = down();
					break;
				case VK_LEFT:
					res = left();
					break;
				case VK_RIGHT:
					res = right();
					break;
				}
				memcpy(Map, res.ChangeMap, sizeof Map);
				score += res.GetScore;
				if(res.flag)
					InsertNumber();
				int JudgeRes = judge();
				if(JudgeRes == 2)
				{
					IsOver = true;
					Game_Paint(hwnd);
					if(MessageBox(hwnd, L"恭喜你胜利了!是否重新开始游戏?", L"恭喜!", MB_YESNO) == IDYES)
						Map_Init();
				}
				else if(JudgeRes == 0)
				{
					IsOver = true;
					Game_Paint(hwnd);
					if(MessageBox(hwnd, L"哈哈哈输了吧你个菜逼!是否重新开始游戏?", L"失败", MB_YESNO) == IDYES)
						Map_Init();
				}
				//MessageBox(hwnd,L"键盘",L"Mouse",MB_OK);
			}
		}
		break;
	case WM_DESTROY:
		Game_CleanUp(hwnd);
		PostQuitMessage(0);
		break;
	case WM_LBUTTONDOWN://鼠标消息
		//MessageBox(hwnd,L"鼠标左键已按下",L"Mouse",MB_OK);
		break;
	default:
		return DefWindowProc(hwnd, message, wParam, lParam);
	}
	return 0;
}

//---------------------------------------【游戏初始化部分】------------------------------------------//
//描述:贴背景贴图
BOOL Game_Init(HWND hwnd)
{
	HBITMAP bmp;
	Map_Init();
	g_hdc = GetDC(hwnd);//获取设备环境句柄k
	g_hBitMap = (HBITMAP)LoadImage(NULL, L"back.bmp", IMAGE_BITMAP, 800, 600, LR_LOADFROMFILE);//加载位图
	wchar_t filename[20];
	for(int i = 0; i < 11; i++)
	{
		memset(filename, 0, sizeof(filename));
		swprintf_s(filename, L"color%d.bmp", i);
		g_hNumber[i] = (HBITMAP)LoadImage(NULL, filename, IMAGE_BITMAP, 80, 80, LR_LOADFROMFILE);
	}
	g_mdc = CreateCompatibleDC(g_hdc);//建立兼容设备环境的内存DC
	g_bufdc = CreateCompatibleDC(g_hdc);
	bmp = CreateCompatibleBitmap(g_hdc, WINDOW_WIDTH, WINDOW_HEIGHT);//建立一个与窗口兼容的空的位图对象
	SelectObject(g_mdc, bmp);
	Game_Paint(hwnd);
	return TRUE;
}

VOID Game_Paint(HWND hwnd)
{
	SelectObject(g_bufdc, g_hBitMap);//将位图对象选入到g_mdc内存DC中
	BitBlt(g_mdc, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, g_bufdc, 0, 0, SRCCOPY);//采用BitBlt函数贴图,参数设置为窗口大小

	g_hFont = CreateFont(40, 0, 0, 0, 0, 0, 0, 0, GB2312_CHARSET, 0, 0, 0, 0, L"微软雅黑");
	SelectObject(g_mdc, g_hFont);
	SetBkMode(g_mdc, TRANSPARENT);
	wchar_t TextScore[20];
	swprintf_s(TextScore, L"%d", score);
	TextOut(g_mdc, 580, 225, TextScore, wcslen(TextScore));
	DeleteObject(g_hFont);
	for(int i = 0; i < 4; i++)
	{
		for(int j = 0; j < 4; j++)
		{
			if(Map[i][j])
			{
				int NO = 0;
				int tmp = Map[i][j];
				while(tmp != 2)
				{
					NO++;
					tmp /= 2;
				}
				SelectObject(g_bufdc, g_hNumber[NO]);
				BitBlt(g_mdc, 110 + j * 100, 110 + i * 100, 80, 80, g_bufdc, 0, 0, SRCCOPY);
			}
		}
	}
	BitBlt(g_hdc,0,0,WINDOW_WIDTH,WINDOW_HEIGHT,g_mdc,0,0,SRCCOPY);
}

//---------------------------------------【Game_CleanUp()函数】------------------------------------------//
//描述:资源清理函数
BOOL Game_CleanUp(HWND hwnd)
{
	DeleteObject(g_hBitMap);
	for(int i = 0; i < 7; i++) {
		DeleteObject(g_hNumber[i]);
	}
	DeleteDC(g_mdc);
	DeleteDC(g_bufdc);
	ReleaseDC(hwnd, g_hdc);//释放设备环境
	return TRUE;
}

//---------------------------------------【游戏算法部分】------------------------------------------//
VOID Map_Init()
{
	score = 0;
	memset(Map, 0, sizeof Map);
	InsertNumber();
	InsertNumber();
	//Map[0][0] = 1024, Map[0][1] = 1024;
	IsOver = false;
}

void InsertNumber()
{
	srand((unsigned int)time(NULL));
	int x, y;
	x = rand() % 4;
	y = rand() % 4;
	while(Map[x][y])
	{
		x = rand() % 4;
		y = rand() % 4;
	}
	int number = rand() % 10;
	if(number)
		Map[x][y] = 2;
	else
		Map[x][y] = 4;
}
node change(int a[4][4])
{
	vector <int> v[4];
	vector <int> tmp[4];
	int ans[4][4] = {0};
	int GetScore = 0;
	for(int i = 0; i < 4; i++)
	{
		for(int j = 0; j < 4; j++)
		{
			if(a[i][j])
				v[i].push_back(a[i][j]);
		}//去0
		while(v[i].size() > 1)
		{
			if(v[i][0] == v[i][1])
			{
				tmp[i].push_back(v[i][0] * 2);
				GetScore += v[i][0] * 2;
				v[i].erase(v[i].begin(), v[i].begin() + 2);
			}//比较是否可以合并,如果可以合并到新容器中并删除已合并的两个数
			else
			{
				tmp[i].push_back(v[i][0]);
				v[i].erase(v[i].begin(), v[i].begin() + 1);
			}//如果不可以合并把第一个放入容器中,删掉第一个数
		}
		if(v[i].size())
			tmp[i].push_back(v[i][0]);//如果有剩余的数也放进去
		int j = 0;
		for(; j < tmp[i].size(); j++)
			ans[i][j] = tmp[i][j];//存进数组
		for(; j < 4; j++)
			ans[i][j] = 0;//补零
	}
	int flag = 0;
	for(int i = 0; i < 4; i++)
	{
		for(int j = 0; j < 4; j++)
			if(ans[i][j] != a[i][j])
				flag = 1;//检查是否和原数组相同,如果相同说明不可以移动
	}
	return node(ans, GetScore, flag);
}
node up()
{
	int a[4][4];
	for(int i = 0; i < 4; i++)
		for(int j = 0; j < 4; j++)
		{
			a[i][j] = Map[j][3 - i];
		}
		node res = change(a);
		for(int i = 0; i < 4; i++)
			for(int j = 0; j < 4; j++)
			{
				a[i][j] = res.ChangeMap[3 - j][i];
			}
	return node(a, res.GetScore, res.flag);
}
node down()
{
	int a[4][4];
	for(int i = 0; i < 4; i++)
		for(int j = 0; j < 4; j++)
		{
			a[i][j] = Map[3 - j][i];
		}
		node res = change(a);
		for(int i = 0; i < 4; i++)
			for(int j = 0; j < 4; j++)
			{
				a[i][j] = res.ChangeMap[j][3 - i];
			}
			return node(a, res.GetScore, res.flag);
}
node left()
{
	return change(Map);
}
node right()
{
	int a[4][4];
	for(int i = 0; i < 4; i++)
		for(int j = 0; j < 4; j++)
		{
			a[i][j] = Map[i][3 - j];
		}
		node res = change(a);
		for(int i = 0; i < 4; i++)
			for(int j = 0; j < 4; j++)
				a[i][j] = res.ChangeMap[i][3 - j];
		return node(a, res.GetScore, res.flag);
}
int judge()
{
	for(int i = 0; i < 4; i++)
		for(int j = 0; j < 4; j++)
		{
			if(Map[i][j] == WinFlag)
				return 2;
		}
		int flag = 0;
		flag = max(flag, up().flag);
		flag = max(flag, down().flag);
		flag = max(flag, left().flag);
		flag = max(flag, right().flag);
		return flag;
}

只是一只大作业……嗯哼  

github不知道为啥安不上了……先把代码存一下……万一又异常了咋整【擦泪

时间: 2024-10-24 17:42:29

gdi写的2048的相关文章

【来写个2048吧】—— 后期优化及源代码

卡片里的数字假设越来越大则会超过卡片,这样看起来不好看,所以我们要推断数字的位数然后设置合适的大小. 在Card.cpp的setNumber()中增加例如以下代码 //设置数字大小 if ( num >= 0) { labelCardNumber->setFontSize (100); } if ( num >= 16) { labelCardNumber->setFontSize (90); } if ( num >= 128) { labelCardNumber->

280行代码:Javascript 写的2048游戏

2048 原作者就是用Js写的,一直想尝试,但久久未动手. 昨天教学生学习JS代码.不妨就做个有趣的游戏好了.2048这么火,是一个不错的选择. 思路: 1. 数组 ,2维数组4x4 2. 移动算法,移动后有数字的对齐,无数字(我用的0,但不显示)补齐. 移动前 移动后(注意程序合并了第一行2个2,并产生了新的2) 移动算法分2步: 第一步骤:移动 第二步骤:合并 移动代码参考: [html] view plaincopy function left(t,i) { var j; var len 

js写的2048

闲着无聊,用js写个简单的2048玩儿...引用了jquery,需要改下地址 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html><head><title>2048</title> <script src="jquery-1.8

【来写个2048吧】—— 游戏结束检测与添加分数

一. 游戏结束检测 //检测游戏是否结束 void GameScene :: doCheck() { bool isGameOver = true ; //判断每一个的上下左右和自己是否相同 for ( int y = 0 ; y < 4; y++) { for ( int x = 0 ; x < 4; x++) { if ( cardArr [x ][ y]-> getNumber () == 0 || ( x< 3 && cardArr[ x ][y ]->

【来写个2048吧】—— 后期优化及源码

卡片里的数字如果越来越大则会超过卡片,这样看起来不好看,所以我们要判断数字的位数然后设置合适的大小. 在Card.cpp的setNumber()中加入如下代码 //设置数字大小 if ( num >= 0) { labelCardNumber->setFontSize (100); } if ( num >= 16) { labelCardNumber->setFontSize (90); } if ( num >= 128) { labelCardNumber->se

【来写个2048吧】—— 创建卡片类以及添加

一.创建卡片类 首先想想卡片是一个精灵,那么我们就继承精灵类.然后还要有数字,背景颜色.基本就这些,那么看代码吧. Card.h代码 #ifndef _CARD_H_ #define _CARD_H_ #include "cocos2d.h" USING_NS_CC ; class CardSprite : public Sprite { public : //这里number是卡片数字,wight和height是宽和高,cardSpriteX和CardSpriteY是卡片坐标 sta

【来写个2048吧】—— 手势识别框架搭建

迭代是一开发种技术,用来把系统功能传递到一系列的增量的完整版本,每个版本一个特定固定的时间段被开发,该时间段称之为迭代. 每个迭代的经历过程: 整个迭代过程: 图中颜色代表每次开发每项活动所占的比重不同 迭代式开发的优点: 1.降低风险 2.得到早期用户反馈 3.持续测试和集成 4.适应变更 开发特征: 1.在进行大规模的投资前,就解决了关键的风险问题 2.使的早期用户反馈在初始迭代中就能出现 3.连续进行测试和集成. 4.各个目标里程碑提供了短期的焦点. 5.对过程的测量是通过实现的评定来进行

【来写个2048吧】—— 移动算法与随机数字生成

一.移动算法 其实2048的移动算法蛮简单,看代码很容易明白,就不多说了. 向左滑动 //左滑动 bool GameScene:: doLeft () { //判断有没有发生移动 bool isMove = false ; for ( int y = 0 ; y < 4; y++) { for ( int x = 0 ; x < 4; x++) { for ( int x1 = x +1 ; x1 < 4; x1++) { if ( cardArr [x1 ][ y]-> getN

分享一下自己写的2048游戏(3*3,4*4,5*5,6*6多种玩法,可反悔)

2048是一款非常常见的小游戏,所以我也想自己尝试着写一款,给自己练练手.说道练手,这里需要交代一下:我从事Android的工作刚刚一年,平时的工作主要是客制化UI和修改Bug,也就是这里改改,那里改改,因此,完整的开发项目的机会比较少,所以,对我而言,想要提高自己的编程水平,抽出时间自己做一些小项目是有意义的.虽然平时的工作主要是客制化UI和修改bug,但并不意味这我的工作是简单枯燥的,我时常会遇到系统中的一些bug,这样我有机会阅读android系统的源码,并从中分析问题出现的原因,这份工作