c语言贪吃蛇最简单代码教程,c语言编程贪吃蛇教程,C语言实现贪吃蛇超详细教程

c语言贪吃蛇最简单代码教程,c语言编程贪吃蛇教程,C语言实现贪吃蛇超详细教程

本文详细说明了用C语言实现Snake的方法,并通过实例代码进行了详细介绍。对大家的学习或工作都有一定的参考价值。让我们和边肖一起为有需要的朋友学习吧。

目录

一、游戏说明1.1游戏按钮说明1.2评分系统二。游戏运行2.1游戏效果显示2.2纠错2.3游戏代码三, 游戏框架构建3.1游戏界面的大小3.2蛇头和蛇身3.2.1蛇头3.2.2蛇身3.3标记游戏区域3.3.1游戏区域存储的位置有哪些3.3.2使用宏使某些数字具有特殊含义3.4菜单栏的设置4.1隐藏光标的设置4.1光标信息的结构成员4.2隐藏光标的实现4.3GetStdHandle函数4.4 SetCo NsoleCursorInfo函数五、光标跳转的设置5.1光标的结构类型初始化界面6.1代码6.2系统函数6.3 SetConsoleTextAttribute函数VII。初始化蛇八号。打印蛇和盖蛇九、生成随机食物9.1效果显示9.2 srand和rand函数10、移动蛇11、游戏主逻辑函数11.1主逻辑函数11.2执行关键函数11.3判断比分并结束11.4从文件中读取历史数据11.5更新数据到文件11.6主函数11.7游戏背景音乐

一、游戏说明

1.1游戏按键说明

按上下左右箭头键改变蛇的移动方向。

短时间按下上、下、左、右其中一个箭头键,实现蛇向这个方向的短时加速运动。

按空格键暂停,然后按任意键继续游戏。

按Esc直接退出游戏。按R键重新开始游戏。

1.2计分系统

保存玩家的最高历史记录。

二、游戏运行

2.1游戏效果展示

2.2一个报错的纠正

如果出现这种情况,请相信这是编译器的问题。

(为了避免本文篇幅过长,部分不影响游戏逻辑的知识点以链接的形式展示)

解决办法

2.3游戏代码

描述:代码测试环境为visual studio 2017。

音乐文件(提取代码6666)

#包含stdio.h

#包含Windows.h

#包含stdlib.h

#包含时间. h

#包含conio.h

#includemmsystem.h

#pragma注释(lib,' Winmm.lib ')

//首先定义游戏界面的大小和游戏区域的行数和列数。

#定义第22行//游戏区域中的行数

#define COL 42 //游戏区域中的列数

#define KONG 0 //标签为空(nothing)

#定义1//在墙上做标记

#定义食物2 //标记食物

#定义头部3 //标记蛇头

#定义身体4 //标记蛇的身体

#定义向上72 //箭头键:向上

#定义向下80 //箭头键:向下

#定义左75 //箭头键:左

#定义右77 //箭头键:右

#定义空间32 //暂停

#定义ESC 27 //退出

//蛇头

结构蛇

{

int len//记录蛇的身体长度

int x;//蛇头横坐标

int y;//蛇头纵坐标

}蛇;

//蛇身

结构体

{

int x;//蛇身横坐标

int y;//蛇身纵坐标

} body[ROW * COL];//打开一个足以存储蛇体的结构数组

int face[ROW][COL];游戏区域的位置是什么,比如墙还是空,蛇身还是蛇头,都可以通过存储不同的数字来实现。

//菜单栏

void menu();

//隐藏光标

void hide cursor();

//光标跳转

void CursorJump(int x,int y);

//初始化接口

void init interface();

//颜色设置

空颜色(int c);

//从文件中读取最高分

void read grade();

//将最高分更新到文件中

void write grade();

//初始化蛇

void init snake();

//随机生成食物

void RandFood();

//判断比分和结局

void JudgeFunc(int x,int y);

//打印蛇和覆盖蛇

void DrawSnake(int标志);

//移动蛇

void MoveSnake(int x,int y);

//执行键

void run(int x,int y);

//游戏主体的逻辑功能

void游戏();

int max,grade//全局变量

int main()

{

//#pragma warning(disable: n)将报警设置为无效。

#pragma warning (disable:4996) //可以使用标准C语言提供的库函数。

menu();

max=0,grade=0;//初始化变量

srand((size _ t)time(NULL));//根据当前时间生成随机种子

系统(‘题蛇’);//设置cmd窗口的名称

系统('模式控制列=84行=23行');//设置cmd窗口的大小

hide cursor();//隐藏光标

read grade();//从文件中读取最高分到max变量

init interface();//初始化接口

init snake();//初始化蛇

RandFood();//随机生成食物

draw snake(1);//打印蛇

PlaySound(TEXT('bgmusic.wav '),NULL,SND _ FILENAME | SND _ ASYNC | SND _ LOOP);

game();//开始游戏

返回0;

}

void菜单(){

系统(‘题蛇’);

系统('模式控制列=84行=23行');//设置cmd窗口的大小

颜色(14);//将文本设置为浅黄色

printf(' * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * \ n ');

printf(' * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *!* * * * * * * * * * * * * * * * * * * \ n’);

printf(' * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * \ n ');

printf(' * * * * * * * * * *上下左右按箭头键,可以改变蛇的移动方向* * * * * * * * * \ n ');

printf(' * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * \ n ');

printf(' * * * * * * * * * *按空格键暂停,再按任意键继续游戏* * * * * * * * * * * \ n ');

printf(' * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * \ n ');

printf(' * * * * * * * * * * * * * * * * * *按Esc键直接退出游戏* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * \ n ');

printf(' * * * * * * * * * * * * * * * * * * * *按R键重新开始游戏* * * * * * * * * * * * * * * * * * * * * * * * * * * * \ n ');

printf(' * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * \ n ');

系统(“暂停”);

}

//用C语言开发游戏程序时,可以通过隐藏光标函数来解决光标闪烁的问题。

void HideCursor()

{

CONSOLE _ CURSOR _ INFO curInfo//定义光标信息的结构变量,头文件是windows.h

curinfo . dwsize=1;//如果没有赋值,光标隐藏无效。

//curinfo . b visible=TRUE;//将光标设置为可见

curinfo . b visible=FALSE;//将光标设置为不可见

HANDLE HANDLE=GetStdHandle(STD _ OUTPUT _ HANDLE);//获取控制台句柄

SetConsoleCursorInfo(handle,curInfo);//设置光标信息

}

//光标跳转

void CursorJump(int x,int y)

{

坐标位置;//定义光标位置的结构变量

位置。X=x//横坐标

位置。Y=y//纵坐标

HANDLE HANDLE=GetStdHandle(STD _ OUTPUT _ HANDLE);//获取控制台句柄

SetConsoleCursorPosition(handle,pos);//设置光标位置

}

//初始化接口

void初始接口()

{

颜色(3);//颜色设置为湖蓝色

for(int I=0;我划船;我)

{

for(int j=0;j COLj)

{

if (j==0 || j==COL - 1)

{

face[I][j]=WALL;//将此位置标记为墙

CursorJump(2 * j,I);

printf('');

}

else if (i==0 || i==ROW - 1)

{

face[I][j]=WALL;//将此位置标记为墙

printf('');

}

其他

{

face[i][j]=孔;//将此位置标记为空

}

}

}

颜色(4);//颜色设置为红色

CursorJump(0,ROW);

Printf('当前分数:%d ',等级);

CursorJump(COL,ROW);

Printf('历史最高分:%d ',max);

}

//颜色设置

空心颜色(中间)

{

SetConsoleTextAttribute(GetStdHandle(STD _ OUTPUT _ HANDLE),c);//颜色设置

//注意:SetConsoleTextAttribute是一个API(应用程序编程接口)

}

//从文件中读取最高分

void ReadGrade()

{

FILE* pf=fopen('贪吃蛇最高分记录。txt ',' r ');//以只读方式打开文件

If (pf==NULL) //无法打开文件

{

pf=fopen(‘贪吃蛇最高分记录。txt ',' w ');//以只写方式打开文件。

fwrite(max,sizeof(int),1,pf);//将max写入一个文件(此时max为0),即将最高分初始化为0。

}

fseek(pf,0,SEEK _ SET);//使文件指针pf指向文件的开头

fread(max,sizeof(int),1,pf);//将文件中的最高分读给max

fclose(pf);//关闭文件

pf=NULL//文件指针及时设置为空。

}

//将最高分更新到文件中

void WriteGrade()

{

FILE* pf=fopen('贪吃蛇最高分记录。txt ',' w ');//以只写方式打开文件。

If (pf==NULL) //无法打开文件

{

Printf('未能保存最高分记录\ n ');

退出(0);

}

fwrite(grade,sizeof(int),1,pf);//将此局的游戏分数写入文件。

fclose(pf);//关闭文件

pf=NULL//文件指针及时设置为空。

}

//初始化蛇

void InitSnake()

{

snake . len=2;//蛇的体长初始化为2

snake . x=COL/2;//蛇头位置的横坐标

snake . y=ROW/2;//蛇头位置的纵坐标

//初始化蛇体坐标

正文[0]。x=COL/2-1;

正文[0]。y=行/2;

正文[1]。x=COL/2-2;

正文[1]。y=行/2;

//标出蛇头和蛇身的位置。

face[snake . y][snake . x]=HEAD;

脸[体[0]。y][body[0]。x]=BODY;

脸[体[1]。y][body[1]。x]=BODY;

}

//随机生成食物

int my _ time=1;

void RandFood()

{

int i,j;

{

//随机生成食物的横坐标和纵坐标

I=rand()% ROW;

j=rand()% COL;

} while (face[i][j]!=孔);//确保生成食物的位置是空的,如果不是,重新生成。

face[I][j]=FOOD;//标记食物位置

颜色(12);//颜色设置为红色

CursorJump(2 * j,I);//光标跳转到生成的随机位置

printf('');//打印食物

}

//判断比分和结局

void JudgeFunc(int x,int y)

{

//如果蛇头即将到达的位置是食物,得分。

if(face[snake . y y][snake . x x]==FOOD)

{

snake.len//蛇身变长

等级=10;//更新当前分数

颜色(7);//颜色设置为白色

CursorJump(0,ROW);

Printf('当前分数:%d ',等级);//重新打印当前分数

RandFood();//重新随机生成食物

}

//如果蛇头即将到达的位置是墙壁或者蛇身,游戏结束。

else if(face[snake . y y][snake . x x]==WALL | | face[snake . y y][snake . x x]==BODY)

{

睡眠(1000);//留给玩家反应时间

系统(“cls”);//清除屏幕

颜色(7);//颜色设置为白色

CursorJump(2 * (COL/3),ROW/2-3);

if(最大等级)

{

Printf('恭喜打破最高纪录,最高纪录更新为%d ',成绩);

write grade();

}

else if (grade==max)

{

Printf('即使最高纪录:%d,加油,取得更好的成绩',成绩);

}

其他

{

Printf('请继续加油,目前与最高纪录相差%d ',max-grade);

}

CursorJump(2 * (COL/3),ROW/2);

printf('游戏结束');

While (1) //询问玩家是否想要另一个游戏。

{

char ch

CursorJump(2 * (COL/3),ROW/2 3);

printf(‘再来一局?(是/否):');

scanf('%c ',ch);

if (ch=='y' || ch=='Y ')

{

系统(“cls”);

main();

}

else if (ch=='n' || ch=='N ')

{

CursorJump(2 * (COL/3),ROW/2 5);

退出(0);

}

其他

{

CursorJump(2 * (COL/3),ROW/2 5);

Printf('选择错误,请重新选择');

}

}

}

}

//打印蛇和覆盖蛇

void DrawSnake(int标志)

{

If (flag==1) //打印蛇

{

颜色(10);//颜色设置为绿色

CursorJump(2 * snake.x,snake . y);

printf('');//打印蛇头

for(int I=0;i snake.len我)

{

CursorJump(2 * body[i]。x,体[i]。y);

printf('');//打印蛇体

}

}

Else //覆盖蛇

{

if (body[snake.len - 1]。x!=0) //防止len(也就是蛇变长)在(0,0)位置覆盖墙壁。

{

//用空格盖住蛇尾。

CursorJump(2 * body[snake.len - 1]。x,body[snake.len - 1]。y);

printf(“”);

}

}

}

//移动蛇

void MoveSnake(int x,int y)

{

draw snake(0);//先覆盖当前显示的蛇。

face[body[snake.len - 1]。y][body[snake.len - 1]。x]=孔;//蛇移动后,蛇的尾巴被重新标记为空

face[snake . y][snake . x]=BODY;//蛇移动后,蛇头的位置就变成了蛇身。

//蛇移动后需要更新每条蛇体的位置坐标。

for(int I=snake . len-1;I 0;我-)

{

正文[我]。x=body[i - 1]。x;

正文[我]。y=body[i - 1]。y;

}

//蛇移动后,蛇头的位置信息成为第一个蛇身的位置信息。

正文[0]。x=snake.x

正文[0]。y=snake.y

//蛇头的位置改变

snake . x=snake . x x;

snake . y=snake . y y;

draw snake(1);//在蛇移动后打印蛇

}

//执行键

空行程(整数x,整数y)

{

int t=0;

while (1)

{

如果(t==0)

t=3000//这里T越小,蛇移动越快(可以根据次数设置游戏难度)

而(-t)//如果控制移动速度,循环3000次需要一点时间。

{

if (kbhit()!=0) //如果敲击键盘,则退出循环。

打破;

}

If (t==0) //键盘没有被敲击。

{

JudgeFunc(x,y);//到达这个位置后判断游戏是否结束。

MoveSnake(x,y);//移动蛇

}

否则//敲击键盘。

{

打破;//返回游戏函数读取的键值

}

}

}

//游戏主体的逻辑功能

无效游戏()

{

int n=RIGHT//当你开始游戏时,你默认向后移动

int tmp=0;//记录蛇的移动方向

先去;//第一次进入循环,往默认方向走。

while (1)

{

n=getch();//读取键值

//在执行之前,需要调整读取的键。

开关(n)

{

案例向上:

case://如果你点击“上”或“下”

如果(tmp!=左tmp!=右)//而最后一条蛇的移动方向不是“左”也不是“右”

{

n=tmp//然后将下一条蛇的移动方向设置为上一条蛇的移动方向。

}

打破;

案例左侧:

case://如果你按“左”或“右”

如果(tmp!=UP tmp!=向下)//而最后一条蛇的移动方向不是“向上”也不是“向下”

{

n=tmp//然后将下一条蛇的移动方向设置为上一条蛇的移动方向。

}

案例空间:

案例ESC:

案例“r”:

案例“R”:

打破;//这四个不需要调整

默认值:

n=tmp//其他键无效,默认为最后一条蛇移动的方向。

打破;

}

第一次://第一次进入循环,往默认方向走。

开关(n)

{

向上://箭头键:向上

run(0,-1);//上移(横坐标偏移量为0,纵坐标偏移量为-1)

tmp=UP//记录当前蛇的移动方向

打破;

向下://箭头键:向下

run(0,1);//下移(横坐标偏移量为0,纵坐标偏移量为1)

tmp=DOWN//记录当前蛇的移动方向

打破;

Left://箭头键:left

运行(-1,0);//向左移动(横坐标偏移量为-1,纵坐标偏移量为0)

tmp=左;//记录当前蛇的移动方向

打破;

右://箭头键:右

run(1,0);//向右移动(横坐标偏移量为1,纵坐标偏移量为0)

tmp=右;//记录当前蛇的移动方向

打破;

案例空间://暂停

system(' pausenul ');//暂停后按任意键继续

打破;

案例退出://退出

系统(“cls”);//清除屏幕

颜色(7);//颜色设置为白色

CursorJump(第8列,第2行);

Printf('游戏结束');

CursorJump(COL - 8,ROW/2 2);

退出(0);

案例“r”:

案例“R”://重新开始

系统(“cls”);//清除屏幕

main();//重新执行主函数

}

}

}

三、游戏框架构建

3.1游戏界面的大小

首先定义游戏界面的大小,定义游戏区域的行数和列数。

#定义第22行//游戏区域中的行数

#define COL 42 //游戏区域中的列数

这里,蛇移动的区域称为游戏区,提示得分的区域称为提示区(提示区占一行)。

3.2蛇头和蛇身

此外,我们需要两个结构来表示蛇头和蛇身。蛇头结构存储当前蛇身的长度和蛇头的位置坐标。

3.2.1蛇头

结构蛇

{

int len//记录蛇的身体长度

int x;//蛇头横坐标

int y;//蛇头纵坐标

}蛇;

3.2.2蛇身

蛇身的位置坐标存储在蛇身结构中。

结构体

{

int x;//蛇身横坐标

int y;//蛇身纵坐标

} body[ROW * COL];//打开一个足以存储蛇体的结构数组

3.3标记游戏区

3.3.1存储游戏区的各个位置是什么

同时我们需要一个二维数组来存储游戏区域中每个位置是什么(位置是空的,墙,食物,蛇头,蛇身)。

int face[ROW][COL];//存储游戏区域的每个位置是什么,存储不同的数字就可以达到目的。

3.3.2 用宏来使某些数字具有特殊意义

为了提高代码的可读性,最好使用宏来定义空、墙、食物、蛇头和蛇身。

#define KONG 0 //标签为空(nothing)

#定义1//在墙上做标记

#定义食物2 //标记食物

#定义头部3 //标记蛇头

#定义身体4 //标记蛇的身体

当然,为了代码的可读性,我们最好也定义宏使用的键的键值。

#定义向上72 //箭头键:向上

#定义向下80 //箭头键:向下

#定义左75 //箭头键:左

#定义右77 //箭头键:右

#定义空间32 //暂停

#定义ESC 27 //退出

3.4菜单栏的设置

void菜单(){

系统(‘题蛇’);//设置窗口标题

系统('模式控制列=84行=23行');//设置cmd窗口的大小

颜色(14);//将文本设置为浅黄色

printf(' * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * \ n ');

printf(' * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *!* * * * * * * * * * * * * * * * * * * \ n’);

printf(' * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * \ n ');

printf(' * * * * * * * * * *上下左右按箭头键,可以改变蛇的移动方向* * * * * * * * * \ n ');

printf(' * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * \ n ');

printf(' * * * * * * * * * *按空格键暂停,再按任意键继续游戏* * * * * * * * * * * \ n ');

printf(' * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * \ n ');

printf(' * * * * * * * * * * * * * * * * * *按Esc直接退出游戏* * * * * * * * * * * * * * * * * * * * * * * * * * * * \ n ');

printf(' * * * * * * * * * * * * * * * * * * * *按R键重新开始游戏* * * * * * * * * * * * * * * * * * * * * * * * * * * * \ n ');

printf(' * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * \ n ');

系统(“暂停”);//暂停程序,按任意键继续

}

下面会对这里出现的函数进行解释,以保证大家不会混淆!

四.隐藏光标的设置

隐藏光标很简单。定义一个光标信息的结构变量(结构类型系统已经定义好了),然后给光标信息赋值,最后用光标信息的结构变量设置光标信息。

4.1光标信息的结构体成员

成员的详细说明

4.2隐藏光标的实现

void HideCursor(){

CONSOLE _ CURSOR _ INFO curInfo//定义光标信息的结构变量,头文件是windows.h

curinfo . dwsize=1;//如果没有赋值,就是随机值,光标无效。

curinfo . b visible=FALSE;//将光标设置为不可见

HANDLE HANDLE=GetStdHandle(STD _ OUTPUT _ HANDLE);//获取控制台句柄

SetConsoleCursorInfo(handle,curInfo);//设置光标信息

}

4.3GetStdHandle函数

使用介绍

4.4 SetConsoleCursorInfo函数

使用介绍

五.光标跳转的设置

光标跳转,即让光标跳转到指定位置输出。类似隐藏光标的操作步骤,先定义一个光标位置的结构变量,然后设置光标的横坐标和纵坐标,最后用这个光标位置的结构变量设置光标位置。

5.1 光标位置的结构体类型

typedef struct _COORD {

短X;

短Y;

} COORD,* PCOORD

Typedef short SHORT

5.2 SetConsoleCursorPosition函数

使用介绍

5.3 光标跳转的实现

void CursorJump(int x,int y){

坐标位置;//定义光标位置的结构变量

位置。X=x//横坐标

位置。Y=y//纵坐标

HANDLE HANDLE=GetStdHandle(STD _ OUTPUT _ HANDLE);//获取控制台句柄

SetConsoleCursorPosition(handle,pos);//设置光标位置

}

六.初始化界面

初始化界面打印游戏区和提示区的“墙”。

6.1代码

int main()

{

//#pragma warning(disable: n)将报警设置为无效。

#pragma warning (disable:4996) //可以使用标准C语言提供的库函数。

系统(‘题蛇’);//设置cmd窗口的名称

系统('模式控制列=84行=23行');//设置cmd窗口的大小

hide cursor();//隐藏光标

init interface();//初始化接口

睡眠(10000);//暂停10000ms,头文件是Windows.h

返回0;

}

//初始化接口

void初始接口()

{

颜色(6);//颜色设置为卡其色

for(int I=0;我划船;我)

{

for(int j=0;j COLj)

{

if (j==0 || j==COL - 1)

{

face[I][j]=WALL;//将此位置标记为墙

CursorJump(2 * j,I);

printf('');

}

else if (i==0 || i==ROW - 1)

{

face[I][j]=WALL;//将此位置标记为墙

printf('');

}

其他

{

face[i][j]=孔;//将此位置标记为空

}

}

}

颜色(4);//颜色设置为红色

CursorJump(0,ROW);

Printf('当前分数:%d ',等级);

CursorJump(COL,ROW);

Printf('历史最高分:%d ',max);

}

//颜色设置

空心颜色(中间)

{

SetConsoleTextAttribute(GetStdHandle(STD _ OUTPUT _ HANDLE),c);//颜色设置

//注意:SetConsoleTextAttribute是一个API(应用程序编程接口)

}

6.2 system函数

使用介绍

注意:它总是程序中工作的最后一个系统(“颜色xx”)。

所以在这个游戏中没有使用system ("colorxx ")来控制游戏界面的颜色,而是使用了SetConsoleTextAttribute函数。

6.3 SetConsoleTextAttribute函数

使用介绍

七.初始化蛇

初始化一条蛇时,蛇身的长度初始化为2,蛇头的起始位置在游戏区域的中央,蛇头是第0条蛇身和左边第1条蛇身。

//初始化蛇

void InitSnake(){

snake . len=2;//蛇的体长初始化为2

snake . x=COL/2;//蛇头位置的横坐标

snake . y=ROW/2;//蛇头位置的纵坐标

//初始化蛇体坐标

正文[0]。x=COL/2-1;

正文[0]。y=行/2;

正文[1]。x=COL/2-2;

正文[1]。y=行/2;

//标出蛇头和蛇身的位置。

face[snake . y][snake . x]=HEAD;

脸[体[0]。y][body[0]。x]=BODY;

脸[体[1]。y][body[1]。x]=BODY;

}

八.打印蛇与覆盖蛇

Print snake和cover snake在这里是通过一个函数直接实现的。如果传入参数标志为1,则打印snake如果传入的参数为0,则蛇被一个空格覆盖。

印花蛇:

首先根据结构变量snake得到蛇头的坐标,在相应的位置打印蛇头。然后根据结构数组体依次得到蛇体的坐标,在相应的位置打印出来。

覆盖蛇(移动蛇后请回到这一部分):

用空格盖住最后一个蛇身就行了。

但在覆盖之前要注意判断被覆盖的位置是否为(0,0),因为当评分后蛇长增加,但新的蛇尾还没有赋值(编译器一般默认初始化为0)时,就不需要覆盖当前新的蛇尾(只需赋值新的蛇尾并打印蛇即可),我们根据最后一个蛇身得到的坐标为(0,0)。如果覆盖,将使用空格。

去掉这个判断,观察蛇吃掉食物后(0,0)位置的壁的变化,然后分析。

//打印蛇和覆盖蛇

void DrawSnake(int标志)

{

If (flag==1) //打印蛇

{

颜色(10);//颜色设置为绿色

CursorJump(2 * snake.x,snake . y);

printf('');//打印蛇头

for(int I=0;i snake.len我)

{

CursorJump(2 * body[i]。x,体[i]。y);

printf('');//打印蛇体

}

}

Else //覆盖蛇

{

if (body[snake.len - 1]。x!=0) //防止len(也就是蛇变长)在(0,0)位置覆盖墙壁。

{

//用空格盖住蛇尾。

CursorJump(2 * body[snake.len - 1]。x,body[snake.len - 1]。y);

printf(“”);

}

}

}

九、随机生成食物

//随机生成食物

void RandFood()

{

int i,j;

{

//随机生成食物的横坐标和纵坐标

I=rand()% ROW;

j=rand()% COL;

} while (face[i][j]!=孔);//确保生成食物的位置是空的,如果不是,重新生成。

face[I][j]=FOOD;//标记食物位置

颜色(12);//颜色设置为红色

CursorJump(2 * j,I);//光标跳转到生成的随机位置

printf('');//打印食物

}

9.1效果展示

int main(){

//#pragma warning(disable: n)将报警设置为无效。

#pragma warning (disable:4996) //可以使用标准C语言提供的库函数。

srand((size _ t)time(NULL));//根据当前时间生成一个随机种子

系统(‘题蛇’);//设置cmd窗口的名称

系统('模式控制列=84行=23行');//设置cmd窗口的大小

hide cursor();//隐藏光标

init interface();//初始化接口

init snake();//初始化蛇

draw snake(1);//打印蛇

RandFood();//随机生成食物

睡眠(10000);

返回0;

}

9.2 srand与rand函数

说明

十、移动蛇

移动蛇的作用是先覆盖当前显示的蛇,然后打印移动的蛇。

参数描述:

x:蛇相对于当前蛇移动后横坐标的变化。

y:相对于当前蛇的纵坐标移动后,蛇的纵坐标的变化。

蛇动了之后,各种信息都需要改变:

最后一条蛇的身体需要在游戏区重新标记为空。蛇头的位置需要在游戏区重新标记为蛇身。在存储蛇身坐标信息的结构数组体中,I段蛇身的坐标信息需要更新为i-1段蛇身的坐标信息,而0段即第一段蛇身的坐标信息需要更新为当前蛇头的坐标信息。蛇头的坐标信息需要根据传入的参数X和y重新计算,(请想象蛇在上述过程中移动)

//移动蛇

void MoveSnake(int x,int y){

draw snake(0);//先覆盖当前显示的蛇。

face[body[snake.len - 1]。y][body[snake.len - 1]。x]=孔;//蛇移动后,蛇的尾巴被重新标记为空

face[snake . y][snake . x]=BODY;//蛇移动后,蛇头的位置就变成了蛇身。

//蛇移动后需要更新每条蛇体的位置坐标。

for(int I=snake . len-1;I 0;我-)

{

正文[我]。x=body[i - 1]。x;

正文[我]。y=body[i - 1]。y;

}

//蛇移动后,蛇头的位置信息变成第0个蛇身的位置信息。

正文[0]。x=snake.x

正文[0]。y=snake.y

//蛇头的位置改变

snake . x=snake . x x;

snake . y=snake . y y;

draw snake(1);//在蛇移动后打印蛇

}

十一、游戏主体逻辑函数

11.1主体逻辑函数

第一次进入功能游戏,默认蛇向右移动,然后执行run功能。直到键盘被敲击,然后从运行功能返回游戏功能进行按键读取。读取键值后,需要调整读取键。调整后,按键执行,再按键读取,以此类推。

//游戏主体的逻辑功能

void Game(){

int n=RIGHT//当你开始游戏时,你默认向后移动

int tmp=0;//记录蛇的移动方向

先去;//第一次进入循环,往默认方向走。

while (1){

n=getch();//读取键值

//在执行之前,需要调整读取的键。

开关(n){

案例向上:

case://如果你点击“上”或“下”

如果(tmp!=左tmp!=RIGHT) {//而最后一条蛇的移动方向不是“左”也不是“右”

n=tmp//然后将下一条蛇的移动方向设置为上一条蛇的移动方向。

}

打破;

案例左侧:

case://如果你按“左”或“右”

如果(tmp!=UP tmp!=DOWN) {//而最后一条蛇的移动方向不是“上”也不是“下”

n=tmp//然后将下一条蛇的移动方向设置为上一条蛇的移动方向。

}

案例空间:

案例ESC:

案例“r”:

案例“R”:

打破;//这四个不需要调整

默认值:

n=tmp//其他键无效,默认为最后一条蛇移动的方向。

打破;

}

第一次://第一次进入循环,往默认方向走。

开关(n){

向上://箭头键:向上

run(0,-1);//上移(横坐标偏移量为0,纵坐标偏移量为-1)

tmp=UP//记录当前蛇的移动方向

打破;

向下://箭头键:向下

run(0,1);//下移(横坐标偏移量为0,纵坐标偏移量为1)

tmp=DOWN//记录当前蛇的移动方向

打破;

Left://箭头键:left

运行(-1,0);//向左移动(横坐标偏移量为-1,纵坐标偏移量为0)

tmp=左;//记录当前蛇的移动方向

打破;

右://箭头键:右

run(1,0);//向右移动(横坐标偏移量为1,纵坐标偏移量为0)

tmp=右;//记录当前蛇的移动方向

打破;

案例空间://暂停

system(' pausenul ');//暂停后按任意键继续

打破;

案例退出://退出

系统(“cls”);//清除屏幕

颜色(7);//颜色设置为白色

CursorJump(第8列,第2行);

Printf('游戏结束');

CursorJump(COL - 8,ROW/2 2);

退出(0);

案例“r”:

案例“R”://重新开始

系统(“cls”);//清除屏幕

main();//重新执行主函数

}

}

}

11.2执行按键函数

关键调整机制:

如果“向上”或“向下”键被按下,并且最后一条蛇的移动方向不是“左”或“右”,那么下一条蛇的移动方向被设置为最后一条蛇的移动方向,

即移动方向不变。如果敲击的是“左”或“右”键,并且上一次蛇的移动方向不是“上”或“下”,那么将下一次蛇的移动方向设置为上一次蛇的移动方向,即移动方向不变。如果敲击的按键是空格、Esc、r或是R,则不作调整。其余按键无效,下一次蛇的移动方向设置为上一次蛇的移动方向,即移动方向不变。

//执行按键 void run(int x, int y){ int t = 0; while (1){ if (t == 0) t = 3000; //这里t越小,蛇移动速度越快(可以根据次设置游戏难度) while (--t){ //控制移动速度的,循环3000次会占用一点时间 if (kbhit() != 0) //若键盘被敲击,则退出循环 break; } if (t == 0) //键盘未被敲击{ JudgeFunc(x, y); //判断到达该位置后,是否得分与游戏结束 MoveSnake(x, y); //移动蛇 } else //键盘被敲击{ break; //返回Game函数读取键值 } } }

kbhit()函数

Return Value

kbhit returns a nonzero value if a key has been pressed. Otherwise, it returns 0.

执行按键

参数说明:

x:蛇移动后的横坐标相对于当前蛇的横坐标的变化。

y:蛇移动后的纵坐标相对于当前蛇的纵坐标的变化。

给定一定的时间间隔,若在该时间间隔内键盘被敲击,则退出run函数,返回Game函数进行按键读取。若未被敲击,则先判断蛇到达移动后的位置后是否得分或是游戏结束,然后再移动蛇的位置。 若键盘一直未被敲击,则就会一直执行run函数当中的while函数,蛇就会一直朝一个方向移动,直到游戏结束

11.3判断得分与结束

判断得分: 若蛇头即将到达的位置是食物,则得分。得分后需要将蛇身加长,并且更新当前得分,除此之外,还需要重新生成食物。

判断结束: 若蛇头即将到达的位置是墙或者蛇身,则游戏结束。游戏结束后比较本局得分和历史最高得分,给出相应的提示语句,并且询问玩家是否再来一局,可自由发挥。

void JudgeFunc(int x, int y){ //若蛇头即将到达的位置是食物,则得分 if (face[snake.y + y][snake.x + x] == FOOD){ snake.len++; //蛇身加长 grade += 10; //更新当前得分 color(7); //颜色设置为白色 CursorJump(0, ROW); printf("当前得分:%d", grade); //重新打印当前得分 RandFood(); //重新随机生成食物 } //若蛇头即将到达的位置是墙或者蛇身,则游戏结束 else if (face[snake.y + y][snake.x + x] == WALL || face[snake.y + y][snake.x + x] == BODY){ Sleep(1000); //留给玩家反应时间 system("cls"); //清空屏幕 color(7); //颜色设置为白色 CursorJump(2 * (COL / 3), ROW / 2 - 3); if (grade > max){ printf("恭喜你打破最高记录,最高记录更新为%d", grade); WriteGrade(); } else if (grade == max){ printf("与最高记录:%d持平,加油再创佳绩", grade); } else{ printf("请继续加油,当前与最高记录相差%d", max - grade); } CursorJump(2 * (COL / 3), ROW / 2); printf("GAME OVER"); while (1) {//询问玩家是否再来一局 char ch; CursorJump(2 * (COL / 3), ROW / 2 + 3); printf("再来一局?(y/n):"); scanf("%c", &ch); if (ch == 'y' || ch == 'Y'){ system("cls"); main(); } else if (ch == 'n' || ch == 'N'){ CursorJump(2 * (COL / 3), ROW / 2 + 5); exit(0); } else{ CursorJump(2 * (COL / 3), ROW / 2 + 5); printf("选择错误,请再次选择"); } } } }

11.4从文件读取历史数据

首先需要使用fopen函数打开“贪吃蛇最高得分记录.txt”文件,若是第一次运行该代码,则会自动创建该文件,并将历史最高记录设置为0,之后再读取文件当中的历史最高记录存储在max变量当中,并关闭文件即可。

11.5更新数据到文件

首先使用fopen函数打开“贪吃蛇最高得分记录.txt”,然后将本局游戏的分数grade写入文件当中即可(覆盖式)。

//更新最高分到文件 void WriteGrade() { FILE* pf = fopen("贪吃蛇最高得分记录.txt", "w"); //以只写的方式打开文件 if (pf == NULL) //打开文件失败 { printf("保存最高得分记录失败\n"); exit(0); } fwrite(&grade, sizeof(int), 1, pf); //将本局游戏得分写入文件当中 fclose(pf); //关闭文件 pf = NULL; //文件指针及时置空 }

11.6 主函数

int main() { //#pragma warning(disable: n)将某个警报置为失效 #pragma warning (disable:4996) //可以使用标准C语言提供的库函数 menu(); max = 0, grade = 0; //初始化变量 srand((size_t)time(NULL));//根据当前时间生成随机种子 system("title 贪吃蛇"); //设置cmd窗口的名字 system("mode con cols=84 lines=23"); //设置cmd窗口的大小 HideCursor(); //隐藏光标 ReadGrade(); //从文件读取最高分到max变量 InitInterface(); //初始化界面 InitSnake(); //初始化蛇 RandFood(); //随机生成食物 DrawSnake(1); //打印蛇 PlaySound(TEXT("bgmusic.wav"), NULL, SND_FILENAME | SND_ASYNC | SND_LOOP); Game(); //开始游戏 return 0; }

11.7 游戏背景音乐

PlaySound函数介绍

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

相关文章阅读

  • c语言调用退出函数 c语言退出整个程序怎么写
  • c语言中怎么给函数初始化 c语言的初始化语句
  • c语言编写函数计算平均值 c语言求平均函数
  • 详解c语言中的字符串数组是什么,详解c语言中的字符串数组结构,详解C语言中的字符串数组
  • 表达式求值c++实现,c语言实现表达式求值
  • 看懂c语言基本语法,C语言详解,C语言的基本语法详解
  • 用c语言实现快速排序算法,排序算法设计与实现快速排序C语言,C语言实现快速排序算法实例
  • 深入解析c语言中函数指针的定义与使用方法,深入解析c语言中函数指针的定义与使用情况,深入解析C语言中函数指针的定义与使用
  • 描述E-R图,E-R图举例,关于C语言中E-R图的详解
  • 折半查找法C语言,折半查找算法(算法设计题)
  • 折半查找法C语言,c语言折半法查找数据,C语言实现折半查找法(二分法)
  • 扫雷小游戏c++代码设计,c语言扫雷游戏源代码,C语言实现扫雷小游戏详细代码
  • 怎样统计程序代码行数,C语言统计行数,C#程序员统计自己的代码行数
  • 基于c语言的贪吃蛇游戏程序设计,用c语言编写贪吃蛇游戏程序,C语言实现简单的贪吃蛇游戏
  • 图的两种遍历算法,图的遍历算法代码c语言,Python算法之图的遍历
  • 留言与评论(共有 条评论)
       
    验证码: