C语言拼图游戏——Windows下基于EasyX且支持鼠标与键盘操作

一、游戏窗口

PS:此游戏为c语言开发,因EasyX库需要.cpp文件才能编译,所以工程文件后缀为.cpp,并未使用cpp的语法。

VS2013工程百度云链接:

链接:https://pan.baidu.com/s/1YkMq2DplvBDkL9fdT0zvKQ
提取码:1pxo

1.1游戏界面

C语言拼图游戏——Windows下基于EasyX且支持鼠标与键盘操作_第1张图片

1.2游戏结束界面

C语言拼图游戏——Windows下基于EasyX且支持鼠标与键盘操作_第2张图片

二、游戏源码

将main.cpp文件添加到工程里

2.1 main.cpp

#define  _CRT_SECURE_NO_WARNINGS
#include 
#include   
#include 
#include 
#include 

#define  PicLen  3 //拼图的边长  
#define  MapLen (PicLen+2) //地图的边长
#define  Blank_Map -1   //不显示的空白地图
#define  Len_Image  147  //图片边长

IMAGE img[PicLen*PicLen];
int Map[MapLen][MapLen];   //游戏地图  
int  key;  //按键保存  
int  dx[4] = { -1, 1, 0, 0 };  //左、右、上、下的方向  
int  dy[4] = { 0, 0, -1, 1 };
int Zero_pos[2] = { PicLen, PicLen };//空白位置所在的坐标
int res = -1;//模式选择结果
int nowmove;//键盘移动后下标结果

int Dir(int x, int y);//鼠标输入时 判断空白格移动方向
void CreateMap();//随机生成地图
void ShowMap();//显示地图
int LOCAL_XY(double pos);//根据鼠标点击位置返回下标
void Button();//键盘移动
void Mouse();//鼠标移动
void OnInit();//初始化所有参数
void judge();//判断游戏是否结束
void StartGame();//开始游戏

LRESULT CALLBACK CBTHookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
	HWND hwnd = (HWND)wParam;
	if (nCode == HCBT_ACTIVATE)
	{
		if (nCode == HCBT_ACTIVATE)
		{
			SetDlgItemText((HWND)wParam, IDYES, "&3×3");
			SetDlgItemText((HWND)wParam, IDNO, "&4×4");
			SetDlgItemText((HWND)wParam, IDOK, "&OK");
			SetDlgItemText((HWND)wParam, IDCANCEL, "&无屏障(困难)");
			SetDlgItemText((HWND)wParam, IDABORT, "&有屏障");
			SetDlgItemText((HWND)wParam, IDRETRY, "&无屏障");
			SetDlgItemText((HWND)wParam, IDIGNORE, "&BGM已关闭");
		}
	}
	return 0;
}
int Msg(HWND hwnd, TCHAR *szText, TCHAR *szCaption, UINT uType)
{
	int ret;
	HHOOK hHook = SetWindowsHookEx(WH_CBT, CBTHookProc, NULL, GetCurrentThreadId());
	ret = MessageBox(hwnd, szText, szCaption, uType);
	UnhookWindowsHookEx(hHook);
	return ret;
}
int Dir(int x,int y)
{
	if ((abs(Zero_pos[0] - x) + abs(Zero_pos[1] - y)) == 1)//在附近
	{
		if (Zero_pos[0] - x == -1)
			return 0;//所点击位置向 左 移动到达空白格 
		if (Zero_pos[0] - x == 1)
			return 1;//所点击位置向 右 移动到达空白格
		if (Zero_pos[1] - y == -1)
			return 2;//所点击位置向 上 移动到达空白格
		if (Zero_pos[1] - y == 1)
			return 3;//所点击位置向 下 移动到达空白格
	}
	return -1;
}
void CreateMap()//随机生成地图
{
	//初始化地图
	for (int i = 0; i < MapLen; i++)
		for (int j = 0; j < MapLen; j++)
			if (i == 0 || i == (MapLen - 1) || j == 0 || j == (MapLen - 1))
				Map[i][j] = Blank_Map;

	for (int i = 0; i < PicLen * PicLen; i++)
		Map[i %  PicLen + 1][i / PicLen + 1] = i + 1;

	Map[PicLen][PicLen] = 0;//右下角设为0  即为空白处

	srand((unsigned int)time(NULL));
	//随机移动打乱地图
	int tt;
	for (int i = 0; i < 200; i++)
	{
		tt = rand() % 4 + 1;
	    switch (tt)
		{
		case 1: //按下左  空白格向右移动
			nowmove = 1;
			break;
		case 2: //右 
			nowmove = 0;
			break;
		case 3: //上
			nowmove = 3;
			break;
		case 4: //下  
			nowmove = 2;
			break;
		}
		//移动后的空白格位置需在地图内
		if ((Zero_pos[0] + dx[nowmove]) >= 1
			&& (Zero_pos[0] + dx[nowmove]) <= PicLen
			&& (Zero_pos[1] + dy[nowmove]) >= 1
			&& (Zero_pos[1] + dy[nowmove]) <= PicLen
			)
		{
			Map[Zero_pos[0]][Zero_pos[1]] = Map[Zero_pos[0] + dx[nowmove]][Zero_pos[1] + dy[nowmove]];//交换值 并记录空白格位置
			Zero_pos[0] = Zero_pos[0] + dx[nowmove];
			Zero_pos[1] = Zero_pos[1] + dy[nowmove];
			Map[Zero_pos[0]][Zero_pos[1]] = 0;
		}
	}
}
void ShowMap()//显示地图
{
	cleardevice();
	for (int i = 1; i < PicLen + 1; i++)
		for (int j = 1; j < PicLen + 1; j++)
			putimage((i - 1) * Len_Image, (j - 1) * Len_Image, &img[Map[i][j]]);
}
int LOCAL_XY(double pos)
{
	return (int)(pos / 150 + 1);
}
void Button()  //键盘移动
{
	if (_kbhit() != 0) //检查当前是否有键盘输入,若有则返回一个非0值,否则返回0  
	{		
		while (_kbhit() != 0)  //可能存在多个按键,要全部取完,以最后一个为主  
			key = _getch(); //将按键从控制台中取出并保存到key中

		switch (key)
		{
		case 75: //按下左  空白格向右移动
			nowmove = 1;
			break;
		case 77: //右 
			nowmove = 0;
			break;
		case 72: //上
			nowmove = 3;
			break;
		case 80: //下  
			nowmove = 2;
			break;
		}
		//移动后的空白格位置需在地图内
		if ((Zero_pos[0] + dx[nowmove]) >= 1 
			&& (Zero_pos[0] + dx[nowmove])<= PicLen
			&& (Zero_pos[1] + dy[nowmove]) >= 1
			&& (Zero_pos[1] + dy[nowmove]) <= PicLen
			)
		{
			Map[Zero_pos[0]][Zero_pos[1]] = Map[Zero_pos[0] + dx[nowmove]][Zero_pos[1] + dy[nowmove]];//交换值 并记录空白格位置
			Zero_pos[0] = Zero_pos[0] + dx[nowmove];
			Zero_pos[1] = Zero_pos[1] + dy[nowmove];
			Map[Zero_pos[0]][Zero_pos[1]] = 0;
			ShowMap();
		}	
	}
}
void Mouse()//鼠标移动
{
	if (MouseHit())
	{
		MOUSEMSG msg = GetMouseMsg();
		switch (msg.uMsg)
		{
		case WM_LBUTTONDOWN://左键按下
			int nowmove = Dir(LOCAL_XY(msg.x), LOCAL_XY(msg.y));
			if (nowmove != -1)//所点击的位置可移动
			{			
				//移动并存储空白格位置
				Map[LOCAL_XY(msg.x) + dx[nowmove]][LOCAL_XY(msg.y) + dy[nowmove]] = Map[LOCAL_XY(msg.x)][LOCAL_XY(msg.y)];
				Map[LOCAL_XY(msg.x)][LOCAL_XY(msg.y)] = 0;
				Zero_pos[0] = LOCAL_XY(msg.x);
				Zero_pos[1] = LOCAL_XY(msg.y);
				ShowMap();
			}
			break;
		}	
	}
}
void OnInit()//初始化所有参数
{  
	closegraph();
	key=0;  //按键保存  
	res = -1;//模式选择结果
	Zero_pos[0] = PicLen;//空白位置所在的坐标
	Zero_pos[1] = PicLen;
}
void judge()
{
	int flag = 1;
	for (int i = 0; i < PicLen * PicLen-2; i++)
	{
		if (Map[i%PicLen + 1][i / PicLen + 1] >= Map[(i + 1) % PicLen + 1][(i + 1) / PicLen + 1])
		{
			flag = 0;
			break;
		}		
	}
	if (flag)//已拼完
	{
		char s[20];
		sprintf(s, "恭喜您,已完成!是否重开?");
		int res=MessageBoxA(0, s, "拼图", MB_YESNO|MB_SYSTEMMODAL);
		if (res==IDYES)
		{
			OnInit();
			StartGame();
		}
		else
		{
			closegraph();
			exit(0);
		}
	}
}
void StartGame()//开始游戏
{
	initgraph(Len_Image * PicLen, Len_Image * PicLen);	//初始绘图窗口
	for (int i = 0; i < PicLen*PicLen; i++)//加载图像
	{
		char s[20];
		sprintf(s, "3\\%d.png", i);
		loadimage(&img[i], s);
	}
	CreateMap();
	ShowMap();
	while (1)
	{
		Button();	
		Mouse();
		judge();
	}
}
void main()
{
	StartGame();
}

由 LiangJian 写于 2019 年 10 月 15 日

你可能感兴趣的:(EasyX)