龙空技术网

【项目实战】C/C++轻松实现4399小游戏:围住神经猫!

C语言编程 465

前言:

今天各位老铁们对“c语言电子地图”大体比较注重,我们都想要知道一些“c语言电子地图”的相关知识。那么小编在网上网罗了一些有关“c语言电子地图””的相关内容,希望大家能喜欢,看官们快快来了解一下吧!

每天一个C语言小项目,提升你的编程能力!

一、游戏说明

本游戏仿造 4399 的小游戏-围住神经猫。

游戏操作:通过鼠标点击操作,设置路障,围住神经猫,当成功围住神经猫时,游戏胜利。当神经猫逃离地图边缘,游戏失败。

二、游戏截图三、实现思路

1. 地图还原:

首先是游戏的道路,这里我们采用绘制灰白色的圆来表示可走的路,用黄色的圆来表示已存在的障碍物。同时还需要注意奇偶行需要交错排列。

2. 猫的移动:

这里我们采用广度优先搜索求最短路径。"猫"在一个位置,能够移动的方向有6个,需要注意的是:

由于奇偶行交替排列,导致奇偶行猫的可行路径是不一样的,奇数行:上,下,左,右,左下,左上。

偶数行:上,下,左,右,右下,右上。剩下的就是常规的求最短路径即可。

注:代码中所用图片,请见文末

四、完整代码

简单了解游戏后我们就来试试吧!(直接上源码,大家可以看注释)

/////////////////////////////////////////////////////////// 程序名称:围住神经猫// 编译环境  Visual Studio2019(C++语言标准选择C++17),EasyX// C语言/C++编程交流Q群:734106058#include <graphics.h>#include <queue>#include <cstring>#include <ctime>#include <vector>#pragma comment( lib, "MSIMG32.LIB")#define pix		 50			// 像素比例#define hight	(14 * pix)#define width	(10 * pix)using namespace std;int stepS;					// 记录已经走的步数int startBarrier;			// 开始的障碍物数目wchar_t Score_[30];MOUSEMSG m;					// 鼠标操作IMAGE pig, bkimg;;			// 加载图片enum class picture{	none, barrier};struct XY{	int x, y;	int lastX, lastY;	//记录上一个点的坐标}cat;struct node{	int x, y;			//坐标,圆心位置	picture pic;		//当前位置的图片内容};node canvas[10][10];	//  地图bool visit[10][10];		//	记录是否访问过地图中的元素int path[10][10][2];	//  记录上一个位置//注意:因为地图是交错排列的,奇数列与偶数列猫的移动不同int dirOdd[6][2]{ 1,0,-1,0,0,1,0,-1,-1,-1,-1,1 };	//控制方向奇数列int dirEven[6][2]{ 1,0,-1,0,0,1,0,-1,1,-1,1,1 };	//控制方向偶数列int main();//贴图函数void transparentimage(IMAGE* dstimg, int x, int y, IMAGE* srcimg,int direction){	HDC dstDC = GetImageHDC(dstimg);	HDC srcDC = GetImageHDC(srcimg);	int w = 50;	int h = 100;	// 使用 Windows GDI 函数实现透明位图	if (direction == 0)		TransparentBlt(dstDC, x, y, w, h, srcDC, 0, 0, w, h, 0);	else		TransparentBlt(dstDC, x, y, w, h, srcDC, 10, 187, w, h, 0);}//游戏初始化void initial(){	srand(time(0));	stepS = 0;	startBarrier = rand() % 6 + 8;	//障碍物数量	loadimage(&pig, L"pig.png");	loadimage(&bkimg, L"bkground.jpg", width, hight, true);	initgraph(width, hight);	HWND wnd = GetHWnd();	SetWindowText(wnd, L"围住神经猫");//设置文章标题	for (int i = 1; i <= 9; ++i)		for (int j = 1; j <= 9; ++j)		{			if (i & 1)	//如果是奇数行				canvas[i][j] = node{ j * pix - pix / 4, pix * 4 + i * pix ,picture::none };			else				canvas[i][j] = node{ j * pix + pix / 4, pix * 4 + i * pix ,picture::none };		}	cat.x = 5; cat.y = 5;	//猫最开始的地方	while (startBarrier--)	{		int bx, by;			//设置初始障碍		do		{			bx = rand() % 10;			by = rand() % 10;		} while (canvas[by][bx].pic == picture::barrier || (by == cat.y && bx == cat.x));		canvas[by][bx].pic = picture::barrier;	}	setbkmode(TRANSPARENT);	BeginBatchDraw();}//绘制游戏画面, 白色:空  黄色:障碍物 void show(){	putimage(0, 0, &bkimg);	setbkcolor(WHITE);	settextstyle(20, 0, L"微软雅黑");	outtextxy(200, 170, L"重玩");	outtextxy(250, 180, L"步数: ");	swprintf(Score_, 29, L"%d", stepS);	outtextxy(290, 180, Score_);	for (int i = 1; i <= 9; ++i)	{		for (int j = 1; j <= 9; ++j)		{			if (canvas[i][j].pic == picture::barrier)				setfillcolor(YELLOW);			else				setfillcolor(LIGHTGRAY);			solidcircle(canvas[i][j].x, canvas[i][j].y, (pix - 4) / 2);		}	}	if (cat.y & 1)	//奇数列		transparentimage(NULL, cat.x * pix - pix / 4 - 25, pix * 3 + cat.y * pix - 21, &pig,0);	else			//偶数列		transparentimage(NULL, cat.x * pix - 25 + pix / 4, pix * 3 + cat.y * pix - 21, &pig,1);	FlushBatchDraw();}//寻找下一个点的位置struct LastOrder{	int x, y;};vector<LastOrder> vec;void findNextXY(int x, int y){	if (x == cat.x && y == cat.y)	{		vec.push_back({ x,y });		return;	}	else	{		findNextXY(path[y][x][0], path[y][x][1]);		vec.push_back({ x,y });	}}//利用广度优先搜索求最短路径,xy为数组的i,j下标,注意传参void bfs(XY xy){	//每次搜索时初始化数组	memset(visit, false, sizeof(visit));	memset(path, 0, sizeof(path));	bool tag = true;	queue<XY> que;	que.push(xy);	visit[xy.y][xy.x] = true;	while (!que.empty())	{		XY temp = que.front();		que.pop();		//如果找到出口		if (temp.x == 1 || temp.x == 9 || temp.y == 1 || temp.y == 9)		{			findNextXY(temp.x, temp.y);			cat.x = vec[1].x;			cat.y = vec[1].y;			vec.clear();			tag = false;			break;		}		int dx, dy;		//寻找可走的路		for (int i = 0; i < 6; ++i)		{			if (temp.y & 1)			{				dx = temp.x + dirOdd[i][0];				dy = temp.y + dirOdd[i][1];			}			else			{				dx = temp.x + dirEven[i][0];				dy = temp.y + dirEven[i][1];			}			if (dx >= 1 && dx <= 9 && dy >= 1 && dy <= 9 && !visit[dy][dx] && canvas[dy][dx].pic == picture::none)			{				visit[dy][dx] = true;				path[dy][dx][0] = temp.x;				path[dy][dx][1] = temp.y;				que.push({ dx,dy,temp.x,temp.y });			}		}	}	if (tag)					//如果没找到出口	{		show();		HWND wnd = GetHWnd();		swprintf(Score_, 29, L"你共用了%d步,重玩一局吗", stepS);		FlushBatchDraw();		if (MessageBox(wnd, Score_, L"成功", MB_YESNO | MB_ICONQUESTION) == IDYES)			main();		else			exit(-1);	}}//鼠标操作void dataChangeWithMouseHit(){	while (true)	{		m = GetMouseMsg();		if (m.x >= 200 && m.x <= 230 && m.y >= 170 && m.y <= 200)			settextcolor(BLACK);		else			settextcolor(WHITE);		outtextxy(200, 170, L"重玩");		FlushBatchDraw();		if (m.uMsg == WM_LBUTTONDOWN)		{			if (m.x >= 200 && m.x <= 230 && m.y >= 170 && m.y <= 200)				main();			for (int i = 1; i <= 9; ++i)				for (int j = 1; j <= 9; ++j)					//如果在当前方格内,则改变信息					if (canvas[i][j].pic != picture::barrier && (m.x - canvas[i][j].x) * (m.x - canvas[i][j].x) +						(m.y - canvas[i][j].y) * (m.y - canvas[i][j].y) <= (pix - 4) * (pix - 4) / 4)					{						canvas[i][j].pic = picture::barrier;						stepS++;						bfs({ cat.x,cat.y,0,0 });						return;					}		}	}}//不需要鼠标的操作,判断猫是否跑掉void dataChangeWithoutMouseHit(){	if (cat.x == 1 || cat.y == 1 || cat.x == 9 || cat.y == 9)	{		show();		HWND wnd = GetHWnd();		if (MessageBox(wnd, L"游戏结束。\n神经猫跑掉了!,重玩一局吗", L"询问", MB_YESNO | MB_ICONQUESTION) == IDYES)			main();		else			exit(-1);	}}int main(){	initial();	while (true)	{		show();		dataChangeWithMouseHit();		dataChangeWithoutMouseHit();		Sleep(20);	}	return 0;}

大家赶紧去动手试试吧!

此外,我也给大家分享我收集的其他资源,从最零基础开始的教程到C语言C++项目案例,帮助大家在学习C语言的道路上披荆斩棘!

编程学习书籍分享:

编程学习视频分享:

整理分享(多年学习的源码、项目实战视频、项目笔记,基础入门教程)最重要的是你可以在群里面交流提问编程问题哦!

对于C/C++感兴趣可以关注小编在后台私信我:【编程交流】一起来学习哦!可以领取一些C/C++的项目学习视频资料哦!已经设置好了关键词自动回复,自动领取就好了!

标签: #c语言电子地图