C语言实现贪吃蛇(简易)
文章目录
目录
文章目录
前言
一、游戏功能和效果
1.游戏功能
2.游戏效果
二. 游戏初步实现
1.确定地图大小
2.创建蛇对象,食物对象
3.初始化蛇
4.生成随机食物
5.画蛇
6.画食物
7. 游戏内移动控制
1.当按上下左右时移动方向改变 。
2.开始游戏时的默认方向
8.判断蛇撞墙,撞身体,撞食物3种情况
1.蛇撞墙:判断蛇头坐标是否和行和列相等,如果相等游戏结束!
2.蛇撞身体:判断蛇头坐标是否和蛇身坐标相等,如果相等游戏结束!
3.蛇撞食物:撞到食物后当前长度增加,再重新生成食物,移动速度变快,分数增加!
4.和蛇移动结合
9.画墙和初步实现
1.画墙
2.初步实现
三.游戏的改进与完善
1.解决频闪
2.去掉蛇尾
3.去除光标
四、完整游戏代码
1.game.h文件
2.test.c文件
总结
前言
本文使用C语言做出简易的贪吃蛇程序,此程序比较简单,适合新手入门或小白。
在这里主要实现一个简易蛇的移动和方向的控制。以及当蛇撞到墙壁,身体,食物这几种情况的判断。
一、游戏功能和效果
1.游戏功能
1.wasd,控制蛇移动的方向。
2.每吃到一个食物移动速度变快。
3.游戏结束显示游戏分数(吃到食物+10分)
2.游戏效果
二. 游戏初步实现
根据上图可以看到游戏界面大致可以分为3个:1.蛇的图形 2.产生的食物 3.周围的墙壁。(这里‘#’代表食物,‘*’代表蛇身,‘@’代表蛇头)
再细分的话:1.创建蛇的结构体,初始化,改变光标位置,画蛇。2.创建食物结构体,在地图中随机放食物。3.让蛇动起来,用4个键控制蛇的方向,撞到食物身体增长,碰到墙壁结束。4.画墙。
1.确定地图大小
实现程序要有一个适当的范围,行和列可以使用两层for循环来确定:例如20行80列
确定后在头文件定义row和col为20,80就可以了。
2.创建蛇对象,食物对象
//蛇身对象
struct BODY
{
int X;
int Y;
};
//蛇对象
struct SNAKE
{
struct BODY body[ROW*COL];//蛇身最大长度
int size;//当前长度
}snake;//食物对象
struct FOOD
{
int X;
int Y;
}food;
3.初始化蛇
这里根据效果图,蛇要居中,那么x,y坐标是行和列的1半。
蛇头是正中间,坐标是第一个:snake.body[0]。
蛇身就是从1开始的下标,第1个下标减1:snake.body[1].X = COL / 2 - 1;是第一节蛇身,第2个下标减2是第二节蛇身,那么使用for循环控制蛇身的长度。
void Initsnake()
{//初始化蛇头snake.size = 4;snake.body[0].X = COL / 2;snake.body[0].Y = ROW / 2;//初始化蛇身int i = 0;for (i = 1; i <= snake.size; i++){snake.body[i].X = COL / 2 - i;snake.body[i].Y = ROW / 2;}
}
4.生成随机食物
将生成的随机数%上行和列,控制在范围内,赋值到food的X,Y坐标上。
void Initfood()//生成食物
{food.X = rand() % COL;food.Y = rand() % ROW;
}
5.画蛇
在画蛇时我们要在地图的中间进行画蛇,那么怎么才能在中间呢?
一般在我们打字时,后面都有一个光标,光标在哪字就打在哪。所以在这里需要设置光标的位置,使他在中间就可以了。这里要用到光标修改函数:我们把相应的坐标给这个函数,就会定位到相应的位置。
void InitUI()
{//画蛇COORD coord = { 0 };int i = 0;for (i = 0; i < snake.size; i++)//改变光标位置{coord.X = snake.body[i].X;coord.Y = snake.body[i].Y;SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);if (i == 0){putchar('@');}else{putchar('*');}}
在这里我们直接使用就可以,当i==0时,就画蛇头,其他情况就是蛇尾,画‘*’号。
6.画食物
和画蛇相同
//画食物
coord.X = food.X;
coord.Y = food.Y;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
putchar('#');
7. 游戏内移动控制
1.当按上下左右时移动方向改变 。
这里可以看图:这里蛇头的坐标是(6,4),当按下上键坐标为(6,3),按下键为(6,5)当按左键右键时,坐标为(5,4),(7,4)。
那么改变方向只需要将X与Y坐标进行+1,-1就可以实现,这里我们定义两个全局变量kx,ky。
2.开始游戏时的默认方向
当我们打开游戏,如果不按方向键,蛇也会默认向一个方向移动,这里我们要使用非阻塞方式检测是否有输入:kbhit()函数和无回显的取一个字符:getch()函数。
具体写法如下:默认向右移动,当有键盘输入时改变方向。
8.判断蛇撞墙,撞身体,撞食物3种情况
这里可以使用while()来将这3种情况和蛇移动放在一起,进行实现。
1.蛇撞墙:判断蛇头坐标是否和行和列相等,如果相等游戏结束!
while (snake.body[0].X >= 0 && snake.body[0].X < COL&&
snake.body[0].Y >= 0 && snake.body[0].Y < ROW)
{
2.蛇撞身体:判断蛇头坐标是否和蛇身坐标相等,如果相等游戏结束!
//蛇头撞身体
int i = 0;
for (i = 1; i < snake.size; i++)
{
if (snake.body[0].X == snake.body[i].X&&snake.body[0].Y == snake.body[i].Y)
{
return;
}
}
3.蛇撞食物:撞到食物后当前长度增加,再重新生成食物,移动速度变快,分数增加!
//蛇头撞食物
if (snake.body[0].X == food.X&&snake.body[0].Y == food.Y)
{
snake.size++;//身体增长
Initfood();//食物消失
result += 10;//加分
if (speed != 60)
{
speed -= 30;//速度增加,到最大速度时停止
}
}
4.和蛇移动结合
void Playgame()//游戏控制
{
char key = 'd';
//蛇撞墙
while (snake.body[0].X >= 0 && snake.body[0].X < COL&&
snake.body[0].Y >= 0 && snake.body[0].Y < ROW)
{
//接收按键输入
if (_kbhit())
{
key = _getch();
}
switch (key)
{
case 'w':kx = 0; ky = -1; break;
case 's':kx = 0; ky = +1; break;
case 'd':kx = +1; ky = 0; break;
case 'a':kx = -1; ky = 0; break;
default:
break;
}
//蛇头撞身体
int i = 0;
for (i = 1; i < snake.size; i++)
{
if (snake.body[0].X == snake.body[i].X&&snake.body[0].Y == snake.body[i].Y)
{
return;
}
}
//蛇头撞食物
if (snake.body[0].X == food.X&&snake.body[0].Y == food.Y)
{
snake.size++;//身体增长
Initfood();//食物消失
result += 10;//加分
if (speed != 60)
{
speed -= 30;//速度增加,到最大速度时停止
}
}
9.画墙和初步实现
1.画墙
void Initwall()//画墙
{int i = 0;int j = 0;for (i = 0; i <= ROW; i++){for (j = 0; j <= COL; j++){if (i == 0){printf("-");}else if (i == ROW){printf("-");}else if (j == 0){printf("|");}else if (j == COL){printf("|");}else{printf(" ");}}printf("\n");}
}
2.初步实现
将墙画好后,蛇还不能移动,我们先看图:
蛇原来的坐标是(6,5)(6,4)6,3)(6,2),当向前走1格后是(6,6)(6,5)(6,4)(6,3)。
原来蛇头的坐标(6,5)给第一节蛇身,第一节蛇身给第2节,以此类推。也就是蛇头的坐标根据方向进行+1或-1,蛇身由上一节的进行赋值。
写好后再用清屏函数system("cls")进行更新,就可以初步实现!
但是运行后发现不断清屏会出现频闪,游戏效果非常不好!
三.游戏的改进与完善
1.解决频闪
初步完成后,蛇确实可以跑起来,但游戏体验太差!下面解决频闪问题!
这里第一想到的便是将清屏函数去掉换成延时函数:Sleep(),这样不需要一直更新,但又会出现新的问题:后面蛇尾会一直在,不会消失!那么就需要将最后一节蛇尾去掉。
2.去掉蛇尾
首先我们将蛇尾的坐标存起来:
//存储蛇尾的坐标
lastX = snake.body[snake.size - 1].X;
lastY = snake.body[snake.size - 1].Y;
然后我们在画蛇的函数中InitUI() ,将蛇尾坐标变成空格:
//去除蛇尾
coord.X = lastX;
coord.Y = lastY;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
putchar(' ');
到这里我们就完美的解决掉问题了! 最后将光标去除就好了!!
3.去除光标
这里直接使用此函数就可以!
四、完整游戏代码
1.game.h文件
#ifndef __GAME_H__
#define __GAME_H__
//定义行和列
#define ROW 20
#define COL 80
//头文件
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<conio.h>
#include<string.h>
#include<windows.h>void Initsnake();//初始化蛇
void Initfood();//初始化食物
void InitUI();//画蛇
void Initwall();//画墙
void Playgame();//游戏:控制int speed = 300;//初始速度
int result = 0;//游戏分数
lastX = 0;//存放蛇尾坐标
lastY = 0;
int kx = 0;//方向控制
int ky = 0;//蛇身结构体
struct BODY
{int X;int Y;
};//创建蛇结构体
struct SNAKE
{struct BODY body[ROW*COL];//蛇身最大长度int size;//长度
}snake;//创建食物结构体
struct FOOD
{int X;int Y;
}food;#endif
2.test.c文件
#define _CRT_SECURE_NO_WARNINGS 1#include"game.h"void Initsnake()
{//初始化蛇头snake.size = 4;snake.body[0].X = COL / 2;snake.body[0].Y = ROW / 2;//初始化蛇身int i = 0;for (i = 1; i <= snake.size; i++){snake.body[i].X = COL / 2 - i;snake.body[i].Y = ROW / 2;}
}void Initfood()//生成食物
{food.X = rand() % COL;food.Y = rand() % ROW;
}void InitUI()
{//画蛇COORD coord = { 0 };int i = 0;for (i = 0; i < snake.size; i++)//改变光标位置{coord.X = snake.body[i].X;coord.Y = snake.body[i].Y;SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);if (i == 0){putchar('@');}else{putchar('*');}}//去除蛇尾coord.X = lastX;coord.Y = lastY;SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);putchar(' ');//画食物 coord.X = food.X;coord.Y = food.Y;SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);putchar('#');//结束时,改变位置coord.X = 0;coord.Y = ROW + 2;SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
}
void Initwall()//画墙
{int i = 0;int j = 0;for (i = 0; i <= ROW; i++){for (j = 0; j <= COL; j++){if (i == 0){printf("-");}else if (i == ROW){printf("-");}else if (j == 0){printf("|");}else if (j == COL){printf("|");}else{printf(" ");}}printf("\n");}
}void Playgame()//游戏控制
{char key = 'd';//蛇撞墙 while (snake.body[0].X >= 0 && snake.body[0].X < COL&&snake.body[0].Y >= 0 && snake.body[0].Y < ROW){InitUI();//更新蛇//接收按键输入if (_kbhit()){key = _getch();}switch (key){case 'w':kx = 0; ky = -1; break;case 's':kx = 0; ky = +1; break;case 'd':kx = +1; ky = 0; break;case 'a':kx = -1; ky = 0; break;default:break;}//蛇头撞身体int i = 0;for (i = 1; i < snake.size; i++){if (snake.body[0].X == snake.body[i].X&&snake.body[0].Y == snake.body[i].Y){return;}}//蛇头撞食物if (snake.body[0].X == food.X&&snake.body[0].Y == food.Y){snake.size++;//身体增长Initfood();//食物消失result += 10;//加分if (speed != 60){speed -= 30;//速度增加,到最大速度时停止}}//存储蛇尾的坐标lastX = snake.body[snake.size - 1].X;lastY = snake.body[snake.size - 1].Y;//蛇移动,前一节身体给后一节身体赋值for (i = snake.size - 1; i > 0; i--){snake.body[i].X = snake.body[i - 1].X;snake.body[i].Y = snake.body[i - 1].Y;}snake.body[0].X += kx;snake.body[0].Y += ky;Sleep(speed);}return;
}void game()//游戏函数
{ //去除光标CONSOLE_CURSOR_INFO cci;cci.dwSize = sizeof(cci);cci.bVisible = FALSE;SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cci);//初始化蛇Initsnake();//初始化食物Initfood();//画墙Initwall();//画蛇InitUI();//游戏控制Playgame();//成绩printf("Game over!游戏结束!\n");printf("游戏分数:%d\n", result);
}int main()
{srand((unsigned int)time(NULL));game();//游戏函数return 0;
}
总结
以上就是今天贪吃蛇的内容,主要就是蛇移动的实现比较难。这里就是比较简单实现方法,230行左右就可以实现,还是比较容易理解的!可以根居其他的加一些功能来进行完善!
C语言实现贪吃蛇(简易)相关推荐
- 安卓c语言自动补全软件吾爱,C语言实现贪吃蛇小游戏
本文实例为大家分享了C语言实现贪吃蛇小游戏的具体代码,供大家参考,具体内容如下 一.程序实现的原理: 1.构造蛇身:定义一个坐标数组,存放的是蛇的每一节蛇身所在的坐标位置.这样就将移动蛇身的操作转换为 ...
- linux贪吃蛇c程序,Linux环境下C语言实现贪吃蛇游戏
Linux环境下C语言实现贪吃蛇游戏 [liul@test snake]$ more snake.c #include #include #include #include #include #def ...
- c语言安卓贪吃蛇代码下载,C语言贪吃蛇代码
c语言编写贪吃蛇源代码,简单易懂,文件为VC源代码.如果你正在学习c语言,就来下载吧.很经典的 C语言贪吃蛇代码部分 #include #include #include#include #defin ...
- c语言-链表-贪吃蛇
1. c语言-链表-贪吃蛇 坐标的结构体-COORD COORD c;c.X = x;c.Y = y;SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_ ...
- C语言实现贪吃蛇代码
C语言实现贪吃蛇,有点难写啊. 我是用VS写的 代码里有注释 我就不多说了 大家也可以直接去下载我的可执行文件 #include<stdio.h> #include<time.h&g ...
- 贪吃蛇c语言经典程序下载,C语言实现贪吃蛇游戏(单人版)
本文实例为大家分享了C语言实现贪吃蛇游戏的具体代码,供大家参考,具体内容如下 相比于第一个:贪吃蛇游戏,功能更加丰富 #include"snake.h" //蛇的移动 void m ...
- C语言实现贪吃蛇小游戏1.0
C语言实现贪吃蛇小游戏1.0 贪吃蛇游戏要有三个东西:边框.蛇.食物 还有两个灵魂的东西:光标的移动与按键监控 一.光标的移动 在我看来在控制台上移动光标画图是实现这个小游戏的灵魂了,在这之前我一直以 ...
- 【笔记】用vs2017 c语言写 贪吃蛇 小游戏
目录 文章目录 前言 一.贪吃蛇游戏 设计逻辑 二.详细介绍 1.设置界面(界面大小,背景颜色) 2.设置贪吃蛇的身体并显示 3.使之能够移动并能够穿墙 4.添加食物并让蛇吃掉 5.设置背景音乐 完整 ...
- c语言贪吃蛇游戏的论文,基于c语言的贪吃蛇游戏论文.doc
基于c语言的贪吃蛇游戏论文 第 PAGE \* Arabic \* MERGEFORMAT 15 页第 PAGE \* Arabic \* MERGEFORMAT 15 页 学校代码 学号 分 类 号 ...
- 贪吃蛇简易版(C++)
导航 下一篇:贪吃蛇升级版(C++) 目录 一. 贪吃蛇简易版的实现 1. 贪吃蛇如何存储? 2. 贪吃蛇如何移动? 3. 食物如何生成? 4. 如何判断游戏结束? 二. 贪吃蛇简易版的优化 1. 添 ...
最新文章
- 一份完全解读:是什么使神经网络变成图神经网络?
- 关于MySQL count(distinct) 逻辑的另一个bug
- EOJ_1020_铁路调度
- c语言将十进制转化为二进制算法_base64算法初探即逆向分析
- dart 乘方运算符_Dart系列-运算符
- 浅谈项目开发现状(一)
- 3dmax物体轴心点坐标和unity3d不一样_Unity3D新手必看:几个让你相见恨晚的小技巧...
- 最短路算法floyd
- ad 单点登录 java 访问权限_如何配置Portal 基于AD的单点登录配置
- hdu4746 Mophues
- 图表位置下移_excel图表技能:如何更准确的表现营业额的变化趋势
- 删除专利模板文件的最后一页(WPS亲测可用)
- 关于判断单峰数组的几种方法
- 量子力学之电子自旋与四个量子数
- 关于centos安装最新的firefox出现的问题GLib-GObject-CRITICAL **
- 3D软件开发工具HOOPS全套产品开发介绍 | HOOPS Visualize、HOOPS Publish
- java解析xml文件练习——通过应用包名获取应用图标即其他信息(基于魅族应用商店)...
- 为什么黑客都用Linux系统?原来是这四大原因
- 两台主机的vmware虚拟机相互连通
- 【韩顺平】Java线程(基础)知识点总结