**C语言写羊了个羊第一关
学了C语言,也尝试自己做一些小游戏,当然因水平有限,这只是第一关,还是简化版的,也非常希望大家学了C语言,能够去学习,然后做一些有趣的小游戏,进一步来提高自己的开发能力。
1.首先,制作相对较高体验的游戏,肯定都要摆脱黑窗口,对于初学者来说,学会easyx库的使用,必不可少, 如果有不懂的可以去看我之前写的一篇讲解 easyx的使用。
2.制作游戏,数组的运用肯定少不了,大部分游戏都需要数组来绘制地图
3.这是一款类似消消乐的游戏, 那么要让每次出现的都不一样,我就采用了随机数的运用(随机数种子以及随机数)
4.当然,游戏也运用了, 函数,指针,结构体。
5.最后也运用了 , bool类型(布尔类型), C++中会介绍,当然也不用感到会怕,这类似于(int char),它有两种返回值 (return true 和 return false),这一般用于,来判断游戏是否结束, 游戏结束肯定就 return true
以上所说的运用的知识点,如果有不知道的,可以先在csdn上了解下 ,不会也别急,见得多了自然就会了。
void initmenu()
{
mciSendString("open ./res/封面.mp3", 0, 0, 0);
mciSendString("play ./res/封面.mp3", 0, 0, 0);
loadimage(&MENU1, "./res/新建文件夹/1.png");
putimage(0, 0, &MENU1);
_getch();
char arr2[30];
for (int i = 0; i < 4; i++)
{
BeginBatchDraw();
sprintf_s(arr2, sizeof(arr2), "./res/新建文件夹/%d.png", i + 2);
loadimage(&MENU2[i], arr2);
putimage(0, 0, &MENU2[i]);
Sleep(1050);
EndBatchDraw();
}
loadimage(&MENU3, "./res/新建文件夹/11.png");
putimage(0, 0, &MENU3);
Sleep(1050);
}
这游戏的界面的设计很简答,主要是运用easyx库,放一些游戏界面的图片,和游戏界面的音乐,
最后那个Sleep()函数,起到个延迟的作用,参数是延迟的时间(以毫秒为单位)
不知道怎么使用easy库,建议去看下我之前写的博客关于easyx库的使用,再来学习这个
void initgame()
{
mciSendString("open ./res/sheep.mp3", 0, 0, 0);
mciSendString("play ./res/sheep.mp3", 0, 0, 0);
mciSendString("close ./res/封面.mp3", 0, 0, 0);
loadimage(&BG, "./res/bg.png");
for (int i = 0; i < 3; i++)
{
char arr[100];
sprintf_s(arr, sizeof(arr), "./res/%d.png", i + 1); // sprintf 打印字符串
loadimage(&Role[i], arr);
}
srand(time(NULL));
initMap();
for (int i = 0; i < 7; i++)
{
cao[i] = 0;
}
}
这里进入游戏中,
1.先关闭游戏界面的音乐,然后播放游戏的音乐
2.加载游戏的背景图片
3.产生随机种子(srand(time(NULL))),便于后面产生随机数
4.当然,我这里也调用了一个我构造的函数,游戏的地图初始化的函数
下一步讲解
5.对羊槽就行初始化(游戏中的棕色部分),地图最初都是以数组的形式存在的
void initMap()
{
// 1 1 1
// 2 2 2
// 3 3 3
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
map[i][j] = i + 1;
}
}
for (int i = 0; i < 20; i++)
{
int x1 = rand() % 3;
int y1 = rand() % 3;
int x2 = rand() % 3;
int y2 = rand() % 3;
int tmp = map[x1][y1];
map[x1][y1] = map[x2][y2];
map[x2][y2] = tmp;
}
}
这个函数,主要用来绘制游戏的地图,
当然这个游戏地图,只是简化版的
思路:用一个三维数组来绘制的,因为3个就消掉,肯定要确保有3组3个一样的,我用数组中元素的值1,2,3,分别代表着一张图片,然后打印照片,如果数组中的值被改为0的话,就不打印照片,意思就是被消掉了
1.先对数组进行会初始化
1 1 1
2 2 2
3 3 3
2.因为游戏中,照片都是打乱的,就让数组中的2个元素对调,用一个循环,循环次数可以自己随便设置,我这里用了20次,至于哪2个元素对调,我这里用的随机数,随机的
void updategame()
{
BeginBatchDraw(); // 双缓冲区, 加载图片的时候, 防止闪烁
putimage(0, 0, &BG);
int distanceX = (504 - 61 * 3 - 15 * 2) / 2;
int distanceY = 270;
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
if (map[i][j] == 0) //
{
continue;
}
else
{
int x = distanceX + j * (61 + 15);
int y = distanceY + i * (68 + 15);
putimage(x, y, &Role[map[i][j] - 1]);
}
}
}
for (int i = 0; i < 7; i++)
{
if (cao[i] != 0)
{
int x = 26 + 64.7 * i;
int y = 696;
putimage(x, y, &Role[cao[i] - 1]);
}
}
EndBatchDraw();
}
1.在加载图片的过程中,可能会出现图片的闪烁
解决办法:建立一个双缓冲区
用BeighBatchDraw()函数和EedBatchDraw()函数。
将加载图片的步骤,放在两个函数的中间。
2.放置背景图片
3… 放置游戏图片 , 数组中 1代表的是 第一张图片, 2代表的是第二张图片, 3代表的是第三张图片, 0则不打印图片(即直接continue)
这里需要做一些简单的计算, 通过背景图片的大小和游戏图片的大小,,计算出相对应的距离,让图片放在相应的位置
distancex是图片离,游戏左框框的位置(初始值需要具体计算)
distancey是图片离, 游戏上框框的位置(图片没在中间, 初始值随便恰当给个距离)
15(可以自己随便设置) 为2张图片的间隔距离
4.放置羊槽的图片,羊槽中最多可以放置7张图片, 这里需要在画图工具,用刻度尺,自己量一下羊槽的总距离,在根据元游戏图片的大小,进行一个简单的计算。
羊槽的元素最开始初始化为0, 打印图片,
肯定是cao[i] ! = 0;
typedef struct location
{
int row;
int col;
}LO;
bool userClick(LO* Location)
{
ExMessage m;
if (peekmessage(&m) && m.message == WM_LBUTTONDOWN) //检查是否有鼠标左键的消息
{
int distanceX = (504 - 61 * 3 - 15 * 2) / 2;
int distanceY = 270;
int col = (m.x - distanceX) / (61 + 15);
int row = (m.y - distanceY) / (68 + 15);
if (row >= 0 && row < 3 && col >= 0 && col < 3)
{
Location->row = row;
Location->col = col;
return true;
}
printf("%d %d\n", col, row);
}
return false;
}
函数作用:通过鼠标的左键点击图片,并且记录鼠标点击位置
这里使用了结构体(int row int col 分别代表行和列), 通过指针传递,同时函数用的是bool类型,为真肯定句调用,为假就不调用。
1.先定义一个结构体。
2.用easxy库, 检查有无鼠标左键的消息。
3.鼠标点击的范围的设置(只能在游戏那个三维数组中才能够生效)。
4.这里也需要做一些计算,算出三维数组的位置,而结构体记录鼠标点击的位置。
void work(LO* Location)
{
int index = map[Location->row][Location->col];
int i = 0;
//for (; i < 7 && cao[i]; i++); //如果第一个槽为0,结束, 如果第一个槽不为0, 就继续++,直到找到槽为0的时候,此时i的值结束。
//if (i < 7)
//{
// cao[i] = index;
//
//}
for (int i = 0; i < 7; i++)
{
if (cao[i] == 0)
{
cao[i] = index;
break;
}
}
int cout = 0;
for (int i = 0; i < 7; i++)
{
if (cao[i] == map[Location->row][Location->col])
{
cout++;
}
}
if (cout == 3)
{
for (int i = 0; i < 7; i++)
{
if (cao[i] == map[Location->row][Location->col])
{
cao[i] = 0;
}
}
}
map[Location->row][Location->col] = 0;
}
1.这里用 int index 来接受 鼠标点击数组元素的大小(通过结构体记录鼠标点击的位置)
2.图片的转移, 图片转移到羊槽上去,就如果羊槽中的元素为0,
就让它 = index,让它从左到右,挨个打印照片, 具体操作这里写了2种方法,代码注释读的部分是方法二
3.图片的消除,在羊槽中3个一样的便会消除, 这里我用cout这个变量来记录的图片重复出现的次数, (用循环)如果羊槽中数组的值等于游戏三维数组的值,那么cout++。 (用循环)if cout == 3, 那么羊槽中 这个元素与三维数组元素相等的,cao[i] = 0;,消掉
4.图片的删除,就让鼠标点击的那个三维数组的值
bool gameover()
{
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
if (map[i][j] == 1)
{
return false;
}
else if (map[i][j] == 2)
{
return false;
}
else if (map[i][j] == 3)
{
return false;
}
}
return true;
}
游戏结束,也是用bool 类型来判断,结束的话就返回 true
游戏结束的标志:,三维数组中的值 不等于1,不等于2,不等于3(都不等于的话,代表着,三维数组值都为0,没有了图片,都在羊槽中被消掉了)
int main()
{
initgraph(504, 900);
initmenu();
initgame();
LO Location;
while (1)
{
if (userClick(&Location))
{
work(&Location);
}
updategame();
if (gameover())
{
setbkmode(TRANSPARENT);
settextcolor(YELLOW);
settextstyle(50, 0, "楷体");
outtextxy(30, 300, "不愧是你!!");
outtextxy(100, 400, "恭喜通关!!");
outtextxy(200, 500, "你赢了!!");
break;
}
}
system("pause");
return 0;
}
当然主函数中,调用游戏结束那部分,后面也用了easyx库的东西,打印字,以及字体的颜色,模式,大小。
注意:别忘了用initgraph()函数,创建一个窗口。
#include
#include
#include
#pragma comment(lib, "winmm.lib")
#include
#include
#include
IMAGE MENU1;
IMAGE MENU2[4];
IMAGE MENU3;
IMAGE BG;
IMAGE Role[3];
int map[3][3];
int cao[7];
void initmenu();
void initgame();
void initMap();
void updategame();
bool gameover();
typedef struct location
{
int row;
int col;
}LO;
bool userClick(LO* location);
void work(LO* Location);
这部分代码,很简单,有的就是一些固定的格式,就不在讲解了
百度网盘图片素材和源码链接
提取码:1111
老铁们,这是压缩包,下载后,直接解压就行。
点个关注,点个赞。
你们的关注和点赞以及收藏真的对我很重要, 后续会与大家分享更多优质的博客