C语言:基于Easyx库实现连连看小游戏

EasyX 是针对 C++ 的图形库,可以帮助 C/C++ 初学者快速上手图形和游戏编程。通过查阅Easyx的官方文档我们可以很快速的上手并编写一些小游戏,如贪吃蛇、连连看等。本文章实现用C语言基于Easyx库,编写一个简单的连连看小游戏。

代码部分

先是一些头文件、宏定义等,方便后续修改游戏相关设置 

#include<time.h>
#define MAP_SIZE 10 //每一行有多少张图片
#define IMG_SIZE 39 //每张图片的宽度
#define WIDTH (MAP_SIZE +2) * IMG_SIZE //窗口的宽度
#define ANIMAL_NUM 42 //图片的总个数

int map[MAP_SIZE + 2][MAP_SIZE + 2];
int way[MAP_SIZE + 2][MAP_SIZE + 2];
IMAGE img_bk;
IMAGE img_Animal[ANIMAL_NUM][2];
struct Index
{
	int row;
	int col;
}begin = { 1, -1 }, end = { -1, -1 };
enum Cur
{
	BEGIN,
	END
};
int step = 0;
Cur state = BEGIN;

 这部分是游戏初始化的函数

void gameInit()
{
	//设置随机数种子
	srand((unsigned)time(NULL));
	//用不同的数据表示不同的图片,每种图片来10个,一共需要10种图片
	for (int i = 1; i <= MAP_SIZE; i++)
	{
		for (int k = 1; k <= MAP_SIZE; k++)
		{
			map[i][k] = i; //10个i
		}
	}
	//加载图片
	loadimage(&img_bk,"./ref/bk.jpg",WIDTH+80,WIDTH+50);   //后两个参数用来调整背景图片的位置
	IMAGE animal;
	loadimage(&animal, "./ref/animal.bmp"); //bmp
	//如何切割图片
	SetWorkingImage(&animal);  //设置工作区
	for (int i = 0; i < ANIMAL_NUM; i++)
	{
		for (int k = 0; k < 2; k++)
		{
			getimage(&img_Animal[i][k], k * IMG_SIZE, i * IMG_SIZE, IMG_SIZE, IMG_SIZE);
		}
	}
	SetWorkingImage();  //恢复默认工作区
	//打乱数组排列,让图片也随机排列
	for (int i = 1; i <= MAP_SIZE; i++)
	{
		for (int k = 1; k <= MAP_SIZE; k++)
		{
			//随即找到两个游戏区域的下标位置,然后交换值 随机函数 rand()
			int x = rand() % MAP_SIZE + 1;
			int y=  rand() % MAP_SIZE + 1;
			int _swap = map[i][k];
			map[i][k] = map[x][y];
			map[x][y] = _swap;
		}
	}
}

 我们使用一个二维数组来存储图片的位置信息,为了使每次运行程序时图片的排列方式不同,因此设置了一个随机数种子。

游戏图形的绘制 

void gameDraw()
{
	putimage(0, 0, &img_bk);
	for (int i = 1; i <= MAP_SIZE; i++)
	{
		for (int k = 1; k <= MAP_SIZE; k++)
		{
			if (map[i][k] != 0)
			{
				putimage(k * IMG_SIZE, i * IMG_SIZE, &img_Animal[map[i][k]][1], SRCAND);    //原图
				putimage(k * IMG_SIZE, i * IMG_SIZE, &img_Animal[map[i][k]][0], SRCPAINT);  //掩码图
			}
		}
	}
}

 获取鼠标消息,获取点击的两个位置的下标

 

void mouseEvent()
{
	if (MouseHit())
	{
		MOUSEMSG msg = GetMouseMsg();
		//判断鼠标点击的位置(begin,end)
		if (msg.uMsg == WM_LBUTTONDOWN && state == BEGIN)
		{
			//把鼠标的坐标转成对应的数组的下标
			begin.col = msg.x / IMG_SIZE;
			begin.row = msg.y / IMG_SIZE;
			end.col = -1;
			end.row = -1;
			state = END;  //改变状态
		}
		else if (msg.uMsg == WM_LBUTTONDOWN && state == END)
		{
			end.col = msg.x / IMG_SIZE;
			end.row = msg.y / IMG_SIZE;
			state = BEGIN; //改变状态
		}
		if (msg.uMsg == WM_LBUTTONDOWN)
		{
			printf("begin(%d,%d) end(%d,%d)\n", begin.col, begin.row, end.col, end.row);
		}
	}
}

判断某个位置是否有图片 

bool isBlock(int row, int col)
{
	if (row < 0 || col < 0 || row >= MAP_SIZE + 2 || col >= MAP_SIZE + 2)
		return 1;
	return map[row][col] + way[row][col];
}

 在控制台打印出二维数组(为了后续观察寻路器的运作)

void showMap()
{
	for (int i = 0; i < MAP_SIZE + 2; i++)
	{
		for (int k = 0; k < MAP_SIZE + 2; k++)
		{
			printf("%-2d ", map[i][k]);
		}
		printf("\n");
	}
}

 判断鼠标点击的起点和终点是否一致

bool same(int begin_x, int begin_y, int end_x, int end_y) 
{
	if (begin_x < 0 || begin_y < 0 || end_x < 0 || end_y < 0 || end_x >= MAP_SIZE + 2 || end_y >= MAP_SIZE + 2 || begin_x >= MAP_SIZE + 2 || begin_y >= MAP_SIZE + 2)
		return false;
	if (begin_x == end_x && begin_y == end_y)
		return true;
	return false;
}

 判断是否满足消除条件

bool can_pass(int begin_x, int begin_y, int end_x, int end_y) 
{
	if (state != BEGIN || begin_x < 0 || begin_y < 0 || end_x < 0 || end_y < 0 || end_x >= MAP_SIZE + 2 || end_y >= MAP_SIZE + 2 || begin_x >= MAP_SIZE + 2 || begin_y >= MAP_SIZE + 2)
		return false;
	if (begin_x == end_x && begin_y == end_y)
		return false;
	if (map[begin.row][begin.col] != map[end.row][end.col])
		return false;
	return true;
}

 使用A*寻路算法进行递归寻路消除

bool can(int begin_x, int begin_y, int end_x, int end_y) 
{
	printf("step:%d (%d,%d)->(%d,%d)\n", step, begin_x, begin_y, end_x, end_y);
	if (step++ > 2000) //当找路太多了
		return false;
	if (begin_x < 0 || begin_y < 0 || end_x < 0 || end_y < 0 || end_x >= MAP_SIZE + 2 || end_y >= MAP_SIZE + 2 || begin_x >= MAP_SIZE + 2 || begin_y >= MAP_SIZE + 2)
		return false;
	if (same(begin_x, begin_y, end_x, end_y) || same(begin_x - 1, begin_y, end_x, end_y) || same(begin_x + 1, begin_y, end_x, end_y) || same(begin_x, begin_y - 1, end_x, end_y) || same(begin_x, begin_y + 1, end_x, end_y))
		return true;
	if (!isBlock(begin_x - 1, begin_y)) //1
	{
		way[begin_x - 1][begin_y] = 1;
		if (can(begin_x - 1, begin_y, end_x, end_y))
			return true;
		way[begin_x - 1][begin_y] = 0;
	}
	if (!isBlock(begin_x, begin_y - 1)) //3
	{
		way[begin_x][begin_y - 1] = 1;
		if (can(begin_x, begin_y - 1, end_x, end_y))
			return true;
		way[begin_x][begin_y - 1] = 0;
	}
	if (!isBlock(begin_x + 1, begin_y)) //2
	{
		way[begin_x + 1][begin_y] = 1;
		if (can(begin_x + 1, begin_y, end_x, end_y))
			return true;
		way[begin_x + 1][begin_y] = 0;
	}
	if (!isBlock(begin_x, begin_y + 1)) //4
	{
		way[begin_x][begin_y + 1] = 1;
		if (can(begin_x, begin_y + 1, end_x, end_y))
			return true;
		way[begin_x][begin_y + 1] = 0;
	}
	return false;
}

 主函数部分

int main()
{
	//首先需要我们自己创建一个图形窗口
	initgraph(WIDTH, WIDTH, SHOWCONSOLE);
	gameInit();
	showMap();
	while (1)
	{
		//开始双缓冲绘图
		BeginBatchDraw();
		gameDraw();
		//结束双缓冲绘图
		EndBatchDraw();
		if (can_pass(begin.row, begin.col, end.row, end.col))
		{
			memset(way, 0, sizeof(way));
			way[begin.row][begin.col] = 1;
			step = 0;
			printf("inininininin");
			if (can(begin.row, begin.col, end.row, end.col))
			{
				map[begin.row][begin.col] = 0;
				map[end.row][end.col] = 0;
				begin.row = -1;
				begin.col = -1;
				end.row = -1;
				end.col = -1;
			}
		}
		mouseEvent();
	}
	getchar();
	return 0;
}

 使用双缓冲绘图防止闪烁

运行结果

(背景图片和连连看内容图片可以自行更换,这里背景我随便放了一张球星照片,注意连连看图片要同时制作其掩码图以实现透明效果)

  • 2
    点赞
  • 51
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 22
    评论
【简介】 这个绘简化了 VC 下的绘,可以在 VC 下像 TC 那么简单的绘(其实比 TC 还简单强大)(内附范例),使初学者也能很容易的做出来贪吃蛇、俄罗斯方块、推箱子、连连看等经典小游戏。 【官方介绍】   许多学编程的都是从 C 语言开始入门的,而目前的现状是:   1. 有些学校以 Turbo C 为环境讲 C 语言,只是 Turbo C 的环境实在太老了,复制粘贴都很不方便。   2. 有些学校直接拿 VC 来讲 C 语言,因为 VC 的编辑和调试环境都很优秀,并且 VC 有适合教学的免费版本。可惜在 VC 下只能做一些文字性的练习题,想画条直线画个圆都很难,还要注册窗口类、建消息循环等等,初学者会受严重打击的。初学编程想要绘就得用 TC,很是无奈。   3. 还有计算机形学,这门课程的重点是绘算法,而不是 Windows 编程。所以,许多老师不得不用 TC 教学,因为 Windows 绘太复杂了,会偏离教学的重点。新的形学的书有不少是用的 OpenGL,可是门槛依然很高。   所以,我们想给大家一个更好的学习平台,就是 VC 方便的开发平台和 TC 简单的绘功能,于是就有了这个 EasyX 。如果您刚开始学 C 语言,或者您是一位教 C 语言的老师,再或者您在教计算机形学,那么这个一定会让您兴奋的。 【系统支持】 操作系统版本:Windows 2000 及以上操作系统。 编译环境版本:Visual C++ 6.0 / 2008(x86 & x64) / 2010(x86 & x64) / 2012(x86 & x64)。VC2013 也可以用(需要手动安装) 【超简单的使用预览】 使用上,基本和 Turbo C 没太大区别。启动 Visual C++,创建一个控制台项目(Win32 Console Application),然后添加一个新的代码文件(.cpp),并引用 graphics.h 头文件就可以了。看一个画圆的例子吧: #include // 就是需要引用这个 #include void main() { initgraph(640, 480); // 这里和 TC 略有区别 circle(200, 200, 100); // 画圆,圆心(200, 200),半径 100 getch(); // 按任意键继续 closegraph(); // 关闭形界面 } 呵呵,很简单吧。 不过还是有不少区别的,比如颜色上,TC 只有 16 色,而这个支持了真彩色。还有,这个增加了鼠标、读取图片等功能。 【帮助文档】 1. 下载包里面有使用手册 EasyX_Help.chm 。 2. 在线版的使用手册:http://www.easyx.cn/help 。 【更多范例】 1. 在使用手册中附了几个很简单的范例。 2. 在 EasyX 官网有使用 VC 编写的各种绘小游戏代码,以及网友的投稿:http://www.easyx.cn/samples 3. 在百度 EasyX 贴吧的精品区有网友发表的各种代码:http://tieba.baidu.com/f?kw=easyx 【使用交流】 1. 官方 QQ 群:19430220、46612969(请写明加群验证信息:EasyX) 2. 百度 EasyX 贴吧:http://tieba.baidu.com/f?kw=easyx

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 22
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Knight12Mars

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

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

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

打赏作者

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

抵扣说明:

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

余额充值