C语言实现贪吃蛇小游戏

通过C语言实现小游戏贪吃蛇,代码如下:

#include<stdio.h> //标准输入输出函数库

#include<time.h> //用于获得随机数

#include<windows.h> //控制dos界面

#include<stdlib.h> //即standard library标志库头文件,里面定义了一些宏和通用工具函数

#include<conio.h> //接收键盘输入输出

/*******宏 定 义*******/

#define U 1

#define D 2

#define L 3

#define R 4 //蛇的状态,U:上 ;D:下;L:左 R:右

/*******定 义 全 局 变 量 *******/

typedef struct snake //蛇身的一个节点

{

int x;

int y;

struct snake *next;

}snake;

int score=0,add=10; //总得分与每次吃食物得分

int HighScore = 0; //最高分

int status,sleeptime=200; //蛇前进状态,每次运行的时间间隔

snake *head, *food; //蛇头指针,食物指针

snake *q; //遍历蛇的时候用到的指针

int endgamestatus=0; //游戏结束的情况,1:撞到墙;2:咬到自己;3:主动退出游戏。

HANDLE hOut; //控制台句柄

/*******函 数 声 明 *******/

void gotoxy(int x,int y); //设置光标位置

int color(int c); //更改文字颜色

void printsnake(); //字符画---蛇

void welcometogame(); //开始界面

void createMap(); //绘制地图

void scoreandtips(); //游戏界面右侧的得分和小提示

void initsnake(); //初始化蛇身,画蛇身

void createfood(); //创建并随机出现食物

int biteself(); //判断是否咬到了自己

void cantcrosswall(); //设置蛇撞墙的情况

void speedup(); //加速

void speeddown(); //减速

void snakemove(); //控制蛇前进方向

void keyboardControl(); //控制键盘按键

void Lostdraw(); //游戏结束界面

void endgame(); //游戏结束

void choose(); //游戏失败之后的选择

void File_out(); //在文件中读取最高分

void File_in(); //储存最高分进文件

void explation(); //游戏说明

/**

* 设置光标位置

*/

void gotoxy(int x,int y)

{

COORD c;

c.X=x;

c.Y=y;

SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),c);

}

/**

* 文字颜色函数 此函数的局限性:1、只能Windows系统下使用 2、不能改变背景颜色

*/

int color(int c)

{

SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), c); //更改文字颜色

return 0;

}

/*

* 字符画---蛇

*/

void printsnake()

{

gotoxy(35,1);

color(6);

printf("/^\\/^\\"); //蛇眼睛

gotoxy(34,2);

printf("|__| O|"); //蛇眼睛

gotoxy(33,2);

color(2);

printf("_");

gotoxy(25,3);

color(12);

printf("\\/"); //蛇信

gotoxy(31,3);

color(2);

printf("/");

gotoxy(37,3);

color(6);

printf(" \\_/"); //蛇眼睛

gotoxy(41,3);

color(10);

printf(" \\");

gotoxy(26,4);

color(12);

printf("\\____"); //舌头

gotoxy(32,4);

printf("_________/");

gotoxy(31,4);

color(2);

printf("|");

gotoxy(43,4);

color(10);

printf("\\");

gotoxy(32,5);

color(2);

printf("\\_______"); //蛇嘴

gotoxy(44,5);

color(10);

printf("\\");

gotoxy(39,6);

printf("| | \\"); //下面都是画蛇身

gotoxy(38,7);

printf("/ / \\");

gotoxy(37,8);

printf("/ / \\ \\");

gotoxy(35,9);

printf("/ / \\ \\");

gotoxy(34,10);

printf("/ / \\ \\");

gotoxy(33,11);

printf("/ / ---- \\ \\");

gotoxy(32,12);

printf("/ / -~ ~- | |");

gotoxy(31,13);

printf("( ( -~ -- ~- _/ |");

gotoxy(32,14);

printf("\\ ~-___-~ -~ ~- ~--~ /");

gotoxy(33,15);

printf("~-_ -~ ~- _-~");

gotoxy(35,16);

printf("~--___-~ ~--~");

}

/**

* 开始界面

*/

void welcometogame()

{

int n;

int i,j = 1;

gotoxy(43,18);

color(11);

printf("贪 吃 蛇 大 作 战");

color(14); //黄色边框

for (i = 20; i <= 26; i++) //输出上下边框┅

{

for (j = 27; j <= 74; j++) //输出左右边框┇

{

gotoxy(j, i);

if (i == 20 || i == 26)

{

printf("-");

}

else if (j == 27 || j == 74)

{

printf("|");

}

}

}

color(12);

gotoxy(35, 22);

printf("1.开始游戏");

gotoxy(55, 22);

printf("2.游戏说明");

gotoxy(35, 24);

printf("3.退出游戏");

gotoxy(29,27);

color(3);

printf("请选择[1 2 3]:[ ]\b\b"); //\b为退格,使得光标处于[]中间

color(14);

scanf("%d", &n); //输入选项

switch (n)

{

case 1:

system("cls");

createMap(); //创建地图

initsnake(); //初始化蛇身

createfood(); //创建食物

keyboardControl(); //按键控制

break;

case 2:

explation(); //游戏说明函数

break;

case 3:

exit(0); //退出游戏

break;

default: //输入非1~3之间的选项

color(12);

gotoxy(40,28);

printf("请输入1~3之间的数!");

getch(); //输入任意键

system("cls"); //清屏

printsnake();

welcometogame();

}

}

/**

* 创建地图

*/

void createMap()

{

int i,j;

for(i=0;i<58;i+=2) //打印上下边框

{

gotoxy(i,0);

color(5); //深紫色的边框

printf("□");

gotoxy(i,26);

printf("□");

}

for(i=1;i<26;i++) //打印左右边框

{

gotoxy(0,i);

printf("□");

gotoxy(56,i);

printf("□");

}

for(i = 2;i<56;i+=2) //打印中间网格

{

for(j = 1;j<26;j++)

{

gotoxy(i,j);

color(3);

printf("■");

}

}

}

/**

* 游戏界面右侧的得分和小提示

*/

void scoreandtips()

{

File_out();

gotoxy(64,4);

color(11);

printf("☆最高记录☆:%d",HighScore);

gotoxy(64,8);

color(14);

printf("得分:%d ",score);

color(13);

gotoxy(73,11);

printf("小 提 示");

gotoxy(60,13);

color(6);

printf("╬ ┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅ ╬");

gotoxy(60,25);

printf("╬ ┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅ ╬");

color(3);

gotoxy(64,14);

printf("每个食物得分:%d分",add);

gotoxy(64,16);

printf("不能穿墙,不能咬到自己");

gotoxy(64,18);

printf("用↑ ↓ ← →分别控制蛇的移动");

gotoxy(64,20);

printf("F1 为加速,F2 为减速");

gotoxy(64,22);

printf("space:暂停游戏");

gotoxy(64,24);

printf("ESC :退出游戏");

}

/**

* 初始化蛇身,画蛇身

*/

void initsnake()

{

snake *tail;

int i;

tail=(snake*)malloc(sizeof(snake));//从蛇尾开始,头插法,以x,y设定开始的位置//

tail->x=24; //蛇的初始位置(24,5)

tail->y=5;

tail->next=NULL;

for(i=1;i<=4;i++) //设置蛇身,长度为5

{

head=(snake*)malloc(sizeof(snake)); //初始化蛇头

head->next=tail; //蛇头的下一位为蛇尾

head->x=24+2*i; //设置蛇头位置

head->y=5;

tail=head; //蛇头变成蛇尾,然后重复循环

}

while(tail!=NULL) //从头到尾,输出蛇身

{

gotoxy(tail->x,tail->y);

color(14);

printf("★"); //输出蛇身,蛇身使用★组成

tail=tail->next; //蛇头输出完毕,输出蛇头的下一位,一直输出到蛇尾

}

}

/**

* 随机出现食物

*/

void createfood()

{

snake *food_1;

srand((unsigned)time(NULL)); //初始化随机数

food_1=(snake*)malloc(sizeof(snake)); //初始化food_1

while((food_1->x%2)!=0) //保证其为偶数,使得食物能与蛇头对其,然后食物会出现在网格线上

{

food_1->x=rand()%52+2; //食物随机出现

}

food_1->y=rand()%24+1;

q=head;

while(q->next==NULL)

{

if(q->x==food_1->x && q->y==food_1->y) //判断蛇身是否与食物重合

{

free(food_1); //如果蛇身和食物重合,那么释放食物指针

createfood(); //重新创建食物

}

q=q->next;

}

gotoxy(food_1->x,food_1->y);

food=food_1;

color(12);

printf("●"); //输出食物

}

/**

* 判断是否咬到了自己

*/

int biteself()

{

snake *self; //定义self为蛇身上的一个节点

self=head->next; //self是蛇头之外的蛇身上的节点

while(self!=NULL)

{

if(self->x==head->x && self->y==head->y) //如果self和蛇身上的节点重合

{

return 1; //返回1

}

self=self->next;

}

return 0;

}

/**

* 设置蛇撞墙的情况

*/

void cantcrosswall()

{

if(head->x==0 || head->x==56 ||head->y==0 || head->y==26) //如果蛇头碰到了墙壁

{

endgamestatus=1; //返回第一种情况

endgame(); //出现游戏结束界面

}

}

/**

* 加速,蛇吃到食物会自动提速,并且按F1会加速

*/

void speedup()

{

if(sleeptime>=50)

{

sleeptime=sleeptime-10;

add=add+2;

}

}

/**

* 加速,按F2会减速

*/

void speeddown()

{

if(sleeptime<350) //如果时间间隔小于350

{

sleeptime=sleeptime+30; //时间间隔加上30

add=add-2; //每吃一次食物的得分减2

}

}

/**

* 控制方向 问题:为什么要设置status,而不使用前两章中接收键盘按键的方法

*/

void snakemove() //蛇前进,上U,下D,左L,右R

{

snake * nexthead;

cantcrosswall();

nexthead=(snake*)malloc(sizeof(snake)); //为下一步开辟空间

if(status==U)

{

nexthead->x=head->x; //向上前进时,x坐标不动,y坐标-1

nexthead->y=head->y-1;

nexthead->next=head;

head=nexthead;

q=head; //指针q指向蛇头

if(nexthead->x==food->x && nexthead->y==food->y) //如果下一个有食物 下一个位置的坐标和食物的坐标相同

{

while(q!=NULL)

{

gotoxy(q->x,q->y);

color(14);

printf("★"); //原来食物的位置,从●换成★

q=q->next; //指针q指向的蛇身的下一位也执行循环里的操作

}

score=score+add; //吃了一个食物,在总分上加上食物的分

speedup();

createfood(); //创建食物

}

else

{

while(q->next->next!=NULL) //如果没遇到食物

{

gotoxy(q->x,q->y);

color(14);

printf("★"); //蛇正常往前走,输出当前位置的蛇身

q=q->next; //继续输出整个蛇身

}

gotoxy(q->next->x,q->next->y); //经过上面的循环,q指向蛇尾,蛇尾的下一位,就是蛇走过去的位置

color(3);

printf("■");

free(q->next); //进行输出■之后,释放指向下一位的指针

q->next=NULL; //指针下一位指向空

}

}

if(status==D)

{

nexthead->x=head->x; //向下前进时,x坐标不动,y坐标+1

nexthead->y=head->y+1;

nexthead->next=head;

head=nexthead;

q=head;

if(nexthead->x==food->x && nexthead->y==food->y) //有食物

{

while(q!=NULL)

{

gotoxy(q->x,q->y);

color(14);

printf("★");

q=q->next;

}

score=score+add;

speedup();

createfood();

}

else //没有食物

{

while(q->next->next!=NULL)

{

gotoxy(q->x,q->y);

color(14);

printf("★");

q=q->next;

}

gotoxy(q->next->x,q->next->y);

color(3);

printf("■");

free(q->next);

q->next=NULL;

}

}

if(status==L)

{

nexthead->x=head->x-2; //向左前进时,x坐标向左移动-2,y坐标不动

nexthead->y=head->y;

nexthead->next=head;

head=nexthead;

q=head;

if(nexthead->x==food->x && nexthead->y==food->y)//有食物

{

while(q!=NULL)

{

gotoxy(q->x,q->y);

color(14);

printf("★");

q=q->next;

}

score=score+add;

speedup();

createfood();

}

else //没有食物

{

while(q->next->next!=NULL)

{

gotoxy(q->x,q->y);

color(14);

printf("★");

q=q->next;

}

gotoxy(q->next->x,q->next->y);

color(3);

printf("■");

free(q->next);

q->next=NULL;

}

}

if(status==R)

{

nexthead->x=head->x+2; //向右前进时,x坐标向右移动+2,y坐标不动

nexthead->y=head->y;

nexthead->next=head;

head=nexthead;

q=head;

if(nexthead->x==food->x && nexthead->y==food->y)//有食物

{

while(q!=NULL)

{

gotoxy(q->x,q->y);

color(14);

printf("★");

q=q->next;

}

score=score+add;

speedup();

createfood();

}

else //没有食物

{

while(q->next->next!=NULL)

{

gotoxy(q->x,q->y);

color(14);

printf("★");

q=q->next;

}

gotoxy(q->next->x,q->next->y);

color(3);

printf("■");

free(q->next);

q->next=NULL;

}

}

if(biteself()==1) //判断是否会咬到自己

{

endgamestatus=2;

endgame();

}

}

/**

* 控制键盘按键

*/

void keyboardControl()

{

status=R; //初始蛇向右移动

while(1)

{

scoreandtips();

if(GetAsyncKeyState(VK_UP) && status!=D) //GetAsyncKeyState函数用来判断函数调用时指定虚拟键的状态

{

status=U; //如果蛇不是向下前进的时候,按上键,执行向上前进操作

}

else if(GetAsyncKeyState(VK_DOWN) && status!=U) //如果蛇不是向上前进的时候,按下键,执行向下前进操作

{

status=D;

}

else if(GetAsyncKeyState(VK_LEFT)&& status!=R) //如果蛇不是向右前进的时候,按左键,执行向左前进

{

status=L;

}

else if(GetAsyncKeyState(VK_RIGHT)&& status!=L) //如果蛇不是向左前进的时候,按右键,执行向右前进

{

status=R;

}

if(GetAsyncKeyState(VK_SPACE)) //按暂停键,执行pause暂停函数

{

while(1)

{

Sleep(300); //sleep()函数,头文件#include <unistd.h> 另进程暂停,知道达到里面设定的参数的时间。

if(GetAsyncKeyState(VK_SPACE)) //按空格键暂停

{

break;

}

}

}

else if(GetAsyncKeyState(VK_ESCAPE))

{

endgamestatus=3; //按esc键,直接到结束界面

break;

}

else if(GetAsyncKeyState(VK_F1)) //按F1键,加速

{

speedup();

}

else if(GetAsyncKeyState(VK_F2)) //按F2键,减速

{

speeddown();

}

Sleep(sleeptime);

snakemove();

}

}

/**

* 储存最高分进文件

*/

void File_in()

{

FILE *fp;

fp = fopen("save.txt", "w+"); //以读写的方式建立一个名为save.txt的文件

fprintf(fp, "%d", score); //把分数写进文件中

fclose(fp); //关闭文件

}

/**

* 在文件中读取最高分

*/

void File_out()

{

FILE *fp;

fp = fopen("save.txt", "a+"); //打开文件save.txt

fscanf(fp, "%d", &HighScore); //把文件中的最高分读出来

fclose(fp); //关闭文件

}

/*

* 游戏说明

*/

void explation()

{

int i,j = 1;

system("cls");

color(13);

gotoxy(44,3);

printf("游戏说明");

color(2);

for (i = 6; i <= 22; i++) //输出上下边框===

{

for (j = 20; j <= 75; j++) //输出左右边框||

{

gotoxy(j, i);

if (i == 6 || i == 22) printf("=");

else if (j == 20 || j == 75) printf("||");

}

}

color(3);

gotoxy(30,8);

printf("tip1: 不能穿墙,不能咬到自己");

color(10);

gotoxy(30,11);

printf("tip2: 用↑.↓.←.→分别控制蛇的移动");

color(14);

gotoxy(30,14);

printf("tip3: F1 为加速,F2 为减速");

color(11);

gotoxy(30,17);

printf("tip4: 按空格键暂停游戏,再按空格键继续");

color(4);

gotoxy(30,20);

printf("tip5: ESC :退出游戏.space:暂停游戏");

getch(); //按任意键返回主界面

system("cls");

printsnake();

welcometogame();

}

/**

* 结束游戏

*/

void endgame()

{

system("cls");

if(endgamestatus==1)

{

Lostdraw();

gotoxy(35,9);

color(12);

printf("对不起,您撞到墙了。游戏结束!");

}

else if(endgamestatus==2)

{

Lostdraw();

gotoxy(35,9);

color(12);

printf("对不起,您咬到自己了。游戏结束!");

}

else if(endgamestatus==3)

{

Lostdraw();

gotoxy(40,9);

color(12);

printf("您已经结束了游戏。");

}

gotoxy(43,12);

color(13);

printf("您的得分是 %d",score);

if(score >= HighScore)

{

color(10);

gotoxy(33,16);

printf("创纪录啦!最高分被你刷新啦,真棒!!!");

File_in(); //把最高分写进文件

}

else

{

color(10);

gotoxy(33,16);

printf("继续努力吧~ 你离最高分还差:%d",HighScore-score);

}

choose();

}

/**

* 边框下面的分支选项

*/

void choose()

{

int n;

gotoxy(25,23);

color(12);

printf("我要重新玩一局-------1");

gotoxy(52,23);

printf("不玩了,退出吧-------2");

gotoxy(46,25);

color(11);

printf("选择:");

scanf("%d", &n);

switch (n)

{

case 1:

system("cls"); //清屏

score=0; //分数归零

sleeptime=200; //设定初始速度

add = 10; //使add设定为初值,吃一个食物得分10,然后累加

printsnake(); //返回欢迎界面

welcometogame();

break;

case 2:

exit(0); //退出游戏

break;

default:

gotoxy(35,27);

color(12);

printf("※※您的输入有误,请重新输入※※");

system("pause >nul");

endgame();

choose();

break;

}

}

/**

* 失败界面

*/

void Lostdraw()

{

system("cls");

int i;

gotoxy(45,2);

color(6);

printf("\\\\\\|///");

gotoxy(43,3);

printf("\\\\");

gotoxy(47,3);

color(15);

printf(".-.-");

gotoxy(54,3);

color(6);

printf("//");

gotoxy(44,4);

color(14);

printf("(");

gotoxy(47,4);

color(15);

printf(".@.@");

gotoxy(54,4);

color(14);

printf(")");

gotoxy(17,5);

color(11);

printf("+------------------------");

gotoxy(35,5);

color(14);

printf("oOOo");

gotoxy(39,5);

color(11);

printf("----------");

gotoxy(48,5);

color(14);

printf("(_)");

gotoxy(51,5);

color(11);

printf("----------");

gotoxy(61,5);

color(14);

printf("oOOo");

gotoxy(65,5);

color(11);

printf("-----------------+");

for(i = 6;i<=19;i++) //竖边框

{

gotoxy(17,i);

printf("|");

gotoxy(82,i);

printf("|");

}

gotoxy(17,20);

printf("+---------------------------------");

gotoxy(52,20);

color(14);

printf("☆☆☆〃");

gotoxy(60,20);

color(11);

printf("----------------------+");

}

/**

* 主函数

*/

int main()

{

system("mode con cols=100 lines=30"); //设置控制台的宽高

printsnake();

welcometogame();

File_out();

keyboardControl();

endgame();

return 0;

}

相关推荐
~yY…s<#>1 小时前
【刷题17】最小栈、栈的压入弹出、逆波兰表达式
c语言·数据结构·c++·算法·leetcode
远翔调光芯片^138287988721 小时前
远翔升压恒流芯片FP7209X与FP7209M什么区别?做以下应用市场摄影补光灯、便携灯、智能家居(调光)市场、太阳能、车灯、洗墙灯、舞台灯必看!
科技·单片机·智能家居·能源
极客小张2 小时前
基于STM32的智能充电桩:集成RTOS、MQTT与SQLite的先进管理系统设计思路
stm32·单片机·嵌入式硬件·mqtt·sqlite·毕业设计·智能充电桩
EricWang13583 小时前
[OS] 项目三-2-proc.c: exit(int status)
服务器·c语言·前端
我是谁??3 小时前
C/C++使用AddressSanitizer检测内存错误
c语言·c++
希言JY4 小时前
C字符串 | 字符串处理函数 | 使用 | 原理 | 实现
c语言·开发语言
午言若4 小时前
C语言比较两个字符串是否相同
c语言
Footprint_Analytics4 小时前
Footprint Analytics 助力 Sei 游戏生态增长
游戏·web3·区块链
m0_739312875 小时前
【STM32】项目实战——OV7725/OV2604摄像头颜色识别检测(开源)
stm32·单片机·嵌入式硬件
嵌入式小章5 小时前
基于STM32的实时时钟(RTC)教学
stm32·嵌入式硬件·实时音视频