耗时三小时写了一个图形化的贪吃蛇,第一次使用easyx图形库,算是小小实战吧

发布时间:2024-12-19 03:20

每一张照片都是一次个人形象的小小展示 #生活乐趣# #生活日常# #日常生活摄影# #个人形象搭配#

文章目录 头文件1.写出图形化界面2.绘制3.移动4.绘制球球5.吃球球6.加上音乐(灵魂)7.主函数8.完整代码小结

熬夜连干三个小时写了这个小游戏,虽然很简单,我这次只写了无敌模式,你也可以自己继续优化,但是我收获了很多,就来分享一下我遇到的问题和逻辑。

效果(gif没有背景音乐,实际上是有的):
在这里插入图片描述

头文件

三个都是现学的,easyx图形库直接去网上搜下载安装到编译器就,很容易上手,我习惯先去阅读官方文档,有没见过的查阅学习。

#include<stdio.h>//标准io #include<conio.h>//控制键盘操作 #include<graphics.h>//easyx图形库,创建图形化窗口 #include<stdlib.h>//本次主要用来生成随机数 #include<mmstream.h>//最后这两个,就是花里胡哨,可以播放音乐,升华 #pragma comment(lib ,"winmm.lib") 123456

1.写出图形化界面

注释都写好了

#include<stdio.h> #include<graphics.h>//引入图形库 //需要知识:结构体,循环,函数,easyx图形库,结构体数组 int main() {initgraph(640,480);//init graph 初始化 图形窗口while (1)//卡死{}return 0; } 123456789101112

效果:
在这里插入图片描述
好ok,就是这样,第一步就完成了。加个背景颜色优化一下

//设置背景颜色setbkcolor(RGB(82,143,22));//清空绘图设备cleardevice(); 12345

效果:
在这里插入图片描述
,完成

2.绘制

说一下,后来背景颜色我要调了一下,配色白痴。。。。。。浪费了可长时间,然后细节代码里都写注释了。

1,好习惯
2,方便学习和增删改查

#include<stdio.h> #include<graphics.h>//引入图形库 //需要知识:结构体,循环,函数,easyx图形库,结构体数组 //宏定义的最大节数,宏定义建议大写,好的编码习惯 #define SNAKE_MAX 400 //结构体定义的结构 struct Snake {int size;//节数int speed;//速度int dir;//方向//坐标,定义好的结构体(x,y)POINT coor[SNAKE_MAX];//通过宏定义定义的最大400节,想开挂,直接去修改宏定义 }snake; //数据初始化,用函数模块化编程思想 void Gameinit() {//init graph 初始化 图形窗口initgraph(640, 480);//初始化,开始游戏有3节snake.size = 3;snake.speed = 10;snake.dir;//通过循环初始化出3段for (int i = snake.size; i >= 0; i--){snake.coor[i].x = 10*i+40;//x坐标慢慢调试,合适位置snake.coor[i].y = 30;} } //绘制,也单独写一个函数 void Gamedraw() {//设置背景颜色setbkcolor(RGB(193, 205, 193));cleardevice();//循环绘制3段setfillcolor(GREEN);for (int i = 0; i < snake.size; i++){solidcircle(snake.coor[i].x, snake.coor[i].y, 5);//三个参数,x坐标,y坐标,半径}EndBatchDraw(); } int main() {Gameinit();Gamedraw();while (1)//卡死{}return 0; }

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566

简简单单,无压力。最浪费我时间的就是逻辑判断和码字速度,需要多锻炼。
看下效果:
在这里插入图片描述

3.移动

初步效果:
在这里插入图片描述
很简单,只需要循环让三节在x轴++就实现了,但是有很多问题。

//移动 void snakeMove() {for (int i = 0; i < snake.size; i++){snake.coor[i].x++;} } 123456789

用枚举加按键改变方向,这里要引入#include<conio.h>//控制键盘操作这个头文件,这里需要注意_getch()是一个阻塞函数,我们通过函数_kbhit()判断有没有按键来解决,有按键就返回真就移动,这里入坑了,没问题

#include<stdio.h> #include<conio.h>//控制键盘操作 #include<graphics.h>//引入图形界面的头文件 //需要知识:结构体,循环,函数,easyx图形库,结构体数组 //宏定义的最大节数,宏定义建议大写,好的编码习惯 #define SNAKE_MAX 400 //的方向通过枚举实现 enum DIR {UP,DOWN,LEFT,RIGHT, }; //结构体定义的结构 struct Snake {int size;//节数int speed;//速度int dir;//方向//坐标,定义好的结构体(x,y)POINT coor[SNAKE_MAX];//通过宏定义定义的最大400节,想开挂,直接去修改宏定义 }snake; //数据初始化,用函数模块化编程思想 void Gameinit() {//init graph 初始化 图形窗口initgraph(640, 480);//初始化,开始游戏有3节snake.size = 3;snake.speed = 10;//默认往右走snake.dir=RIGHT;//通过循环初始化出3段for (int i = snake.size; i >= 0; i--){snake.coor[i].x = 10*i+40;//x坐标慢慢调试,合适位置snake.coor[i].y = 30;} } //绘制,也单独写一个函数 void Gamedraw() {//设置背景颜色setbkcolor(RGB(193, 205, 193));cleardevice();//循环绘制3段setfillcolor(GREEN);for (int i = 0; i < snake.size; i++){solidcircle(snake.coor[i].x, snake.coor[i].y, 5);//三个参数,x坐标,y坐标,半径}EndBatchDraw(); } //移动 void snakeMove() {for (int i = 0; i < snake.size; i++){switch (snake.dir){case UP:snake.coor[i].y-=snake.speed;break;case DOWN:snake.coor[i].y+=snake.speed;break;case LEFT:snake.coor[i].x-=snake.speed;break;case RIGHT:snake.coor[i].x+=snake.speed;break;}} } //通过按键改变蛇的方向(上下左右),需要头文件#include<conio.h>//控制键盘操作 //72 80 75 77上下左右键对应的数字,可以通过这些数字确定键 //_getch()是一个阻塞函数,我们通过函数_kbhit()判断有没有按键来解决,有按键就返回真,就移动 void keyControl() {if (_kbhit()){switch (_getch()){case 'W':case'w':case 72://移动上面已经写好了,在这就直接用snake.dir = UP;break;case 'S':case's':case 80:snake.dir = DOWN;break;case 'a':case'A':case 75:snake.dir = LEFT;break;case 'D':case'd':case 77:snake.dir = RIGHT;break;}} } int main() {Gameinit();while (1)//卡死{Gamedraw();snakeMove();keyControl();Sleep(10);}return 0; }

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135

实现效果:
在这里插入图片描述
可以看到这……遇到Bug了。
分析了一下,你看它能左右能上下,什么怪物,所以,先让身体跟着头移动

//移动 void snakeMove() {//-1防止数组越界for (int i = snake.size-1; i > 0; i--){//身体连接到头上snake.coor[i] = snake.coor[i - 1];}switch (snake.dir){case UP:snake.coor[0].y-= snake.speed;break;case DOWN:snake.coor[0].y+= snake.speed;break;case LEFT:snake.coor[0].x-= snake.speed;break;case RIGHT:snake.coor[0].x+= snake.speed;break;} }

12345678910111213141516171819202122232425

在这里插入图片描述
果然,现在还有问题,发现它是没有头的开了挂的,向上直接能变成向下,左右也是
这时候再用 if 判断语句轻松实现上了不能下,左了不能右,试一下:

//如果不那就,乖乖听话if (snake.dir != DOWN){snake.dir = UP;}break;case 'S':case's':case 80://如果不那就,乖乖听话if (snake.dir != UP){snake.dir = DOWN;}break;case 'a':case'A':case 75://如果不那就,乖乖听话if (snake.dir != RIGHT){snake.dir = LEFT;}break;case 'D':case'd':case 77://如果不那就,乖乖听话if (snake.dir != LEFT){snake.dir = RIGHT;}break;}

1234567891011121314151617181920212223242526272829303132333435363738

好,啊,简简单单。看下效果:

在这里插入图片描述
Good,好像有点样了
但是这个一出墙就不见了,我技术菜,我想让它无敌,上边进下边出,坐进又出。怎么实现?思考一下……

对移动部分的部分的函数做以下判断即可

普通模式: 如果蛇头在y轴坐标小于等于0,就说明已经碰到墙,可以直接结束游戏(不适合我)开挂模式:如果撞墙把它坐标修改一下就实现了(适合我)

switch (snake.dir){case UP:snake.coor[0].y-= snake.speed;//蛇头在y轴<等你0了,说明撞到墙了if (snake.coor[0].y -5 <= 0){snake.coor[0].y = 480;}break;case DOWN:snake.coor[0].y+= snake.speed;if (snake.coor[0].y +5>= 480){snake.coor[0].y = 0;}break;case LEFT:snake.coor[0].x-= snake.speed;if (snake.coor[0].x +5 <=0){snake.coor[0].x = 640;}break;case RIGHT:snake.coor[0].x+= snake.speed;if (snake.coor[0].x-5>= 640){snake.coor[0].x = 0;}break;}

1234567891011121314151617181920212223242526272829303132333435

在这里插入图片描述

4.绘制球球

首先定义食物的结构体

//结构体定义食物的结构 struct food {int x;//食物坐标xint y;//食物坐标yint r;//食物半径rbool flag;//布尔类型,1没有吃 0吃了DWORD color;//color }food; 123456789

然后进行初始化(随机数终于派上用场了)

//food初始化(用到随机函数)虚拟随机(如果没有随机数种子则产生的一样)//设置种子需要头文件stdlib.hfood.x = rand() % 640;//初始化xfood.y = rand() % 480;//初始化yfood.color = RGB(rand() % 256, rand() % 256, rand() % 256);//分别初始化rgb的三个元素food.r = rand() % 10 + 2;//半径随机food.flag = true;//开局就生成食物 1234567

然后绘制,很简单,只需要判断是1就画

//绘制食物if (food.flag){solidcircle(food.x, food.y, food.r);} 12345

好,
在这里插入图片描述
在这里插入图片描述

5.吃球球

//判断吃食物 void eat() {if (food.flag && snake.coor[0].x >= food.x - food.r && snake.coor[0].x <= food.x + food.r && snake.coor[0].y >= food.y - food.r && snake.coor[0].y <= food.y + food.r){food.flag = false;snake.size++;} 123456789

吃完再生成

if (!food.flag){food.x = rand() % 640;//随机生成一个整数,如果没有随机数种子,每次都是固定的。food.y = rand() % 480;//设置种子需要头文件stdlib.hfood.color = RGB(rand() % 256, rand() % 256, rand() % 256);food.r = rand() % 10 + 5;food.flag = true;} } 123456789

6.加上音乐(灵魂)

头文件

#include<mmstream.h> #pragma comment(lib ,"winmm.lib")//多媒体设备接口 12

这些都是固定的,是不是很简单呢

//播放贪吃蛇MP3,固定格式mciSendString("open 贪吃蛇.mp3 alias BEIJING", 0, 0, 0);mciSendString("play BEIJING repeat", 0, 0, 0); 123

7.主函数

int main() {Gameinit();while (1) {Gamedraw();snakeMove();keyControl();eat();Sleep(60);} return 0; 123456789101112

8.完整代码

/* =====贪====吃============小=======游======戏====== @author:周棋洛 @版本号:1.0 @date:2021.7.9 */ #include<stdio.h> #include<conio.h>//控制键盘操作 #include<graphics.h>//引入图形界面的头文件 #include<stdlib.h> #include<Windows.h> #include<mmstream.h> #pragma comment(lib ,"winmm.lib")//多媒体设备接口 //需要知识:结构体,循环,函数,easyx图形库,结构体数组 //宏定义的最大节数,宏定义建议大写,好的编码习惯 #define SNAKE_MAX 400 //的方向通过枚举实现 enum DIR {UP,DOWN,LEFT,RIGHT, }; //结构体定义的结构 struct Snake {int size;//节数int speed;//速度int dir;//方向//坐标,定义好的结构体(x,y)POINT coor[SNAKE_MAX];//通过宏定义定义的最大400节,想开挂,直接去修改宏定义 }snake; //结构体定义食物的结构 struct food {int x;//食物坐标xint y;//食物坐标yint r;//食物半径rbool flag;//布尔类型,1没有吃 0吃了DWORD color;//color }food; //数据初始化,用函数模块化编程思想 void Gameinit() {//播放贪吃蛇MP3,固定格式mciSendString("open 贪吃蛇.mp3 alias BEIJING", 0, 0, 0);mciSendString("play BEIJING repeat", 0, 0, 0);//init graph 初始化 图形窗口initgraph(640, 480);//设置随机数种子(开机到目前的时间的毫秒)srand(GetTickCount());//初始化,开始游戏有3节snake.size = 3;snake.speed = 10;//默认往右走snake.dir=RIGHT;//通过循环初始化出3段for (int i = snake.size; i >= 0; i--){snake.coor[i].x = 10*i+40;//x坐标慢慢调试,合适位置snake.coor[i].y = 30;}//food初始化(用到随机函数)虚拟随机(如果没有随机数种子则产生的一样)//设置种子需要头文件stdlib.hfood.x = rand() % 600;//初始化xfood.y = rand() % 440;//初始化yfood.color = RGB(rand() % 256, rand() % 256, rand() % 256);//分别初始化rgb的三个元素food.r = rand() % 15 + 20;//半径随机food.flag = true;//开局就生成食物 } //绘制,也单独写一个函数 void Gamedraw() {//设置背景颜色setbkcolor(RGB(193, 205, 193));cleardevice();//循环绘制3段setfillcolor(GREEN);for (int i = 0; i < snake.size; i++){solidcircle(snake.coor[i].x, snake.coor[i].y, 5);//三个参数,x坐标,y坐标,半径}//绘制食物if (food.flag){solidcircle(food.x, food.y, food.r);}EndBatchDraw(); } //移动 void snakeMove() {//-1防止数组越界for (int i = snake.size-1; i > 0; i--){//身体连接到头上snake.coor[i] = snake.coor[i - 1];}switch (snake.dir){case UP:snake.coor[0].y-= snake.speed;//蛇头在y轴<等你0了,说明撞到墙了if (snake.coor[0].y -5 <= 0){snake.coor[0].y = 480;}break;case DOWN:snake.coor[0].y+= snake.speed;if (snake.coor[0].y +5>= 480){snake.coor[0].y = 0;}break;case LEFT:snake.coor[0].x-= snake.speed;if (snake.coor[0].x +5 <=0){snake.coor[0].x = 640;}break;case RIGHT:snake.coor[0].x+= snake.speed;if (snake.coor[0].x-5>= 640){snake.coor[0].x = 0;}break;} } //通过按键改变蛇的方向(上下左右),需要头文件#include<conio.h>//控制键盘操作 //72 80 75 77上下左右键对应的数字,可以通过这些数字确定键 //_getch()是一个阻塞函数,我们通过函数_kbhit()判断有没有按键来解决,有按键就返回真,就移动 void keyControl() {if (_kbhit()){switch (_getch()){case 'W':case'w':case 72://移动上面已经写好了,在这就直接用//如果不那就,乖乖听话if (snake.dir != DOWN){snake.dir = UP;}break;case 'S':case's':case 80://如果不那就,乖乖听话if (snake.dir != UP){snake.dir = DOWN;}break;case 'a':case'A':case 75://如果不那就,乖乖听话if (snake.dir != RIGHT){snake.dir = LEFT;}break;case 'D':case'd':case 77://如果不那就,乖乖听话if (snake.dir != LEFT){snake.dir = RIGHT;}break;//游戏暂停⏸case ' ':while (1){if (_getch() == ' ')return;}break;}} } //判断吃食物 void eat() {if (food.flag && snake.coor[0].x >= food.x - food.r && snake.coor[0].x <= food.x + food.r && snake.coor[0].y >= food.y - food.r && snake.coor[0].y <= food.y + food.r){food.flag = false;snake.size++;}if (!food.flag){food.x = rand() % 640;//随机生成一个整数,如果没有随机数种子,每次都是固定的。food.y = rand() % 480;//设置种子需要头文件stdlib.hfood.color = RGB(rand() % 256, rand() % 256, rand() % 256);food.r = rand() % 10 + 5;food.flag = true;} } int main() {Gameinit();while (1) {Gamedraw();snakeMove();keyControl();eat();Sleep(60);}return 0; }

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245

好,到这里呢,一个简单的小游戏就完成了。实践之后才发现原来你觉得很简单的东西也是一点一点实现的。还是那句话,不积小流无以成江海小流,不积跬步无以至千里。加油吧,总之这个实战的逻辑很简单。可以试着来自己体验一下,后续可以自己做优化。你会有很多感悟和收获。撒花★,°:.☆( ̄▽ ̄)/$:.°★ 。

在这里插入图片描述

小结

对与C又有了新的理解,封装函数,模块化设计,化繁为简,一步步实现简单的最后复杂问题就迎刃而解。感觉C特别强,一个字,牛,虽然我现在学的浅,随着深入学习,我觉得C很棒,感觉你随便给一些合理的需求,C都可以满足你,呃~~,图形化啊,这个,这个,可以借助库嘛,哈哈编写程序前,弄清你的需求,不盲目,有需求后,弄清逻辑关系,想到代码的封装以及重要的逻辑处理和编写,锻炼思维,秃头警告⚠编码过程中,多多少少碰到Bug,这就是修炼之路,先自己想实践看看可不可以解决,不行借助外力干掉bug(我们既是bug的生产者,也是bug的终结者),对代码负责,对自己负责。哈哈通过有趣的栗子激发自己,促进学习。生活很苦,但你很甜。,不bb了,打( ̄o ̄) . z Z

网址:耗时三小时写了一个图形化的贪吃蛇,第一次使用easyx图形库,算是小小实战吧 https://www.yuejiaxmz.com/news/view/513452

相关内容

JAVA贪吃蛇小游戏分论(一)
基于C++的简易版《球球大作战》游戏设计
teddyisland是什么牌子 IP化发展形象图库再创造
图14是一列简谐横波的图像,实线表示t1=1s时的波形,虚线表示t2=3s时的波
形容每天过的很充实的说说
用「衣二三」的逻辑做图书租赁,「小木屋图书」会是一门好生意么?
时间管理图书:超级时间整理术:每天多出一小时
预防“生蛇”大作战,“蛇”缠腰一圈会死吗?
在图书馆修补图书,我一生的巅峰
C语言小项目实践——日历程序

随便看看