Easyx-----c语言实现2048

这是一个2048游戏的实现代码,包括图像资源加载、地图初始化、随机生成数字、移动操作(上、下、左、右)等功能。游戏使用C++和EasyX图形库,通过读取键盘输入进行移动操作,并在每次移动后检查是否有新的数字生成。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

tool.hpp

#pragma once
#include<easyx.h>

void drawImg(int x, int y,IMAGE *src)
{
	// 变量初始化
	DWORD* pwin = GetImageBuffer();			//窗口缓冲区指针
	DWORD* psrc = GetImageBuffer(src);		//图片缓冲区指针
	int win_w = getwidth();				    //窗口宽高
	int win_h = getheight();
	int src_w = src->getwidth();		    //图片宽高
	int src_h = src->getheight();
	
	// 计算贴图的实际长宽
	int real_w = (x + src_w > win_w) ? win_w - x : src_w;			// 处理超出右边界
	int real_h = (y + src_h > win_h) ? win_h - y : src_h;			// 处理超出下边界
	if (x < 0) { psrc += -x;			real_w -= -x;	x = 0; }	// 处理超出左边界
	if (y < 0) { psrc += (src_w * -y);	real_h -= -y;	y = 0; }	// 处理超出上边界


	// 修正贴图起始位置
	pwin += (win_w * y + x);

	// 实现透明贴图
	for (int iy = 0; iy < real_h; iy++)
	{
		for (int ix = 0; ix < real_w; ix++)
		{
            //计算透明通道的值[0,256) 0为完全透明 255为完全不透明
			byte a = (byte)(psrc[ix] >> 24);
			if (a > 100)
			{
				pwin[ix] = psrc[ix];
			}
		}
		//换到下一行
		pwin += win_w;
		psrc += src_w;
	}
}

void drawImg(int x, int y, int dstW, int dstH, IMAGE* src, int srcX, int srcY)
{
	// 变量初始化
	DWORD* pwin = GetImageBuffer();			//窗口缓冲区指针
	DWORD* psrc = GetImageBuffer(src);		//图片缓冲区指针
	int win_w = getwidth();				    //窗口宽高
	int win_h = getheight();
	int src_w = src->getwidth();		    //图片宽高
	int src_h = src->getheight();


	// 计算贴图的实际长宽
	int real_w = (x + dstW > win_w) ? win_w - x : dstW;			    // 处理超出右边界
	int real_h = (y + dstH > win_h) ? win_h - y : dstH;			    // 处理超出下边界
	if (x < 0) { psrc += -x;			real_w -= -x;	x = 0; }	// 处理超出左边界
	if (y < 0) { psrc += (dstW * -y);	real_h -= -y;	y = 0; }	// 处理超出上边界

	//printf("realw,h(%d,%d)\n", real_w, real_h);
	// 修正贴图起始位置
	pwin += (win_w * y + x);

	// 实现透明贴图
	for (int iy = 0; iy < real_h; iy++)
	{
		for (int ix = 0; ix < real_w; ix++)
		{
            //计算透明通道的值[0,256) 0为完全透明 255为完全不透明
			byte a = (byte)(psrc[ix + srcX + srcY * src_w] >> 24);
			if (a > 100)
			{
				pwin[ix] = psrc[ix + srcX + srcY * src_w];
			}
		}
		//换到下一行
		pwin += win_w;
		psrc += src_w;
	}
}

 源.cpp

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<easyx.h>	
#include<math.h>
#include<conio.h>
#include"tools.hpp"
#define ROW 4
#define COL 4	
#define INTERVAL  15	//格子间的间隔
#define GRID_SIZE 117   //格子的宽度和高度
//38 * 195
IMAGE bk;				//背景
//存储数据的数组
int map[ROW][COL];

int flag = 0; //是否生成一个数字
//定义图片资源
IMAGE imgs[11];
//特殊处理空白图片
IMAGE zero;
void loadResource()
{
	loadimage(&bk, "./pieces/bk.png", 584, 734);
	loadimage(&zero, "./pieces/0.png", GRID_SIZE, GRID_SIZE);
	for (int i = 2,j = 0; i <= 2048; i *= 2,j++)
	{  
		char imgPath[50] = { 0 };                           //字符串格式化
		sprintf_s(imgPath, "./pieces/%d.png", i);           //缓冲区(数组) 格式字符串
		for (int i = 0; i < 17; i++)					    //字符数组必须要用for循环做打印|不能用"%s"的方式打印
		{
			printf("%c", imgPath[i]);
		}
		putchar('\n');

		//注意: 图片要一个挨着一个输出
		loadimage(&imgs[j], imgPath, GRID_SIZE, GRID_SIZE); //多字节字符集
	}
}

//随机产生2or4 2的概率更高
int createNumber()
{
	if (rand() % 10 != 0)
	{
		return  2;
	}
	else
	{
		return 4;
	}
}
//给数组空白处填充一个数
void mapFillNumber()
{
	//随机产生两个下标
	while (true)
	{
		//多次产生下标的时候,可能会重复 0 1 0 1 虽然概率比较小但还是有可能
		int r = rand() % ROW;	//0 1 2 3
		int c = rand() % COL;	//0 1 2 3
		//避免出现问题 首先判断原来位置是不是等于 0 如果等于 0 才放入数据
		if (map[r][c] == 0)
		{
			map[r][c] = createNumber();
			return;
		}
	}
}
//初始化
void init()
{
	//设置随机数种子
	srand(time(NULL));

	//随机产生一个数,并且放到数组里面去 map[?][?] = createNumber();
	for (int i = 0; i < 2; i++)
	{
		mapFillNumber();
	}
}
//绘制
void draw()
{
	for (int i = 0; i < ROW; i++)
	{
		for (int k = 0; k < COL; k++)
		{
			//把每个格子左上角的坐标求出来
			int x = k * GRID_SIZE + (k + 1) * INTERVAL + 38-18;
			int y = i * GRID_SIZE + (i + 1) * INTERVAL + 195-17;	
			switch (map[i][k]) {	
			case 0:
				drawImg(x, y, &zero);
				break;
			case 2:
				drawImg(x, y, &imgs[0]);
				break;
			case 4:
				drawImg(x, y, &imgs[1]);
				break;
			case 8:
				drawImg(x, y, &imgs[2]);
				break;
			case 16:
				drawImg(x, y, &imgs[3]);
				break;
			case 32:
				drawImg(x, y, &imgs[4]);
				break;
			case 64:
				drawImg(x, y, &imgs[5]);
				break;
			case 128:
				drawImg(x, y, &imgs[6]);
				break;
			case 256:
				drawImg(x, y, &imgs[7]);
				break;
			case 512:
				drawImg(x, y, &imgs[8]);
				break;
			case 1024:
				drawImg(x, y, &imgs[9]);
				break;
			case 2048:
				drawImg(x, y, &imgs[10]);
				break;
			}
		}
		printf("\n");
	}
}
//向上移动
void moveUp()
{
	/*
	向上移动:遍历每列
	*/
	for (int i = 0; i < COL; i++)
	{
		int temp = 0;
		for (int begin = 1; begin < ROW; begin++)
		{
			if (map[begin][i] != 0)
			{
				if (map[temp][i] == 0)
				{
					map[temp][i] = map[begin][i];
					map[begin][i] = 0;
				}
				else if (map[temp][i] == map[begin][i])
				{
					map[temp][i] += map[begin][i];
					map[begin][i] = 0;
					temp++;
				}
				else
				{
					map[temp + 1][i] = map[begin][i];
					if (temp + 1 != begin)//如果temp+1和begn不在同一个位置,就让begin所在的位置的数字置空
					{
						map[begin][i] = 0;
					}
					temp++;
				}
				flag = 1;
			}
		}
	}
}
//向下移动
void moveDown()
{
	for (int i = 0; i < COL; i++)
	{
		int temp = ROW - 1;
		for (int begin = ROW - 2; begin >= 0; begin--)
		{
			if (map[begin][i] != 0)
			{
				if (map[temp][i] == 0)
				{
					map[temp][i] = map[begin][i];
					map[begin][i] = 0;
				}
				else if (map[temp][i] == map[begin][i])
				{
					map[temp][i] += map[begin][i];
					map[begin][i] = 0;
					temp--;
				}
				else
				{
					map[temp - 1][i] = map[begin][i];
					if ((temp - 1) != begin)
					{
						map[begin][i] = 0;
					}
					temp--;
				}
				flag = 1;
			}
		}
	}
}
//向左移动
void moveLeft()
{
	for (int i = 0; i < COL; i++)
	{
		int temp = 0;
		for (int begin = 1; begin < ROW; begin++)
		{
			if (map[i][begin] != 0)
			{
				if (map[i][temp] == 0)
				{
					map[i][temp] = map[i][begin];
					map[i][begin] = 0;;
				}
				else if (map[i][temp] == map[i][begin])
				{
					map[i][temp] += map[i][begin];
					map[i][begin] = 0;
					temp++;
				}
				else
				{
					map[i][temp + 1] = map[i][begin];
					if (temp + 1 != begin)
					{
						map[i][begin] = 0;
					}
					temp++;
				}
				flag = 1;
			}
		}
	}
}
//向右移动
void moveRight()
{
	for (int i = 0; i < ROW; i++)
	{
		int temp = COL - 1;
		for (int begin = COL - 2; begin >= 0; begin--)
		{
			if (map[i][begin] != 0)
			{
				if (map[i][temp] == 0)
				{
					map[i][temp] = map[i][begin];
					map[i][begin] = 0;
				}
				else if (map[i][temp] == map[i][begin])
				{
					map[i][temp] += map[i][begin];
					map[i][begin] = 0;
					temp--;
				}
				else
				{
					map[i][temp - 1] = map[i][begin];
					if (temp - 1 != begin)
					{
						map[i][begin] = 0;
					}
					temp--;
				}
				flag = 1;
			}
		}
	}
}
//移动格子
void move()
{
	//获取键盘按键 72 80 75 77
	int key = _getch();
	switch (key)
	{
	case 'W':
	case 'w':
	case 72:
		moveUp();
		break;
	case 80:
		moveDown();
		break;
	case 75:
		moveLeft();
		break;
	case 77:
		moveRight();
		break;
	}
	if (flag == 1)
	{
		mapFillNumber();
		flag = 0;
	}
}
int main()
{	
	//窗口
	initgraph(584,734, EW_SHOWCONSOLE);

	init();
	loadResource();


	drawImg(0, 0, &bk);
	while (true)
	{
		draw();
		move();
		for (int i = 0; i < ROW; i++) {
			for (int j = 0; j < COL; j++) {
				printf("%d", map[i][j]);
			}
			printf("\n");
		}
	}
	getchar();
	return 0;
}
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qiuqiuyaq

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值