纯C语⾔编写贪吃蛇(附源码,⽆EasyX、MFC)
⼤⼀下学期,我所选的C语⾔⼯程实践是写⼀个贪吃蛇游戏。那⼏天真的挺肝的,完成本专业的答辩之后就没怎么动过这程序了。那时候写的贪吃蛇,还有⼀个栈溢出的问题没有解决,是因为当时所学知识有限,还没想到较好的解决⽅法。现在⼤⼆上学期,在上了好⼏节数据结构之后,对栈有了⼀定的了解,随着对栈的学习,我想出了解决我写的贪吃蛇栈溢出的办法。其实是前两天刚刚有这个想法,刚刚才测试并实现了,办法可⾏。现在我加⼊了计算机学院的创新开放实验室,打算做的⼀个项⽬是⼩程序。以后想记录⼀下我的开发过程和⼀些经历,⼜刚刚完善好贪吃蛇的代码,就简单记录⼀下吧。
因为代码⽐较长,先把参考资料写⼀下,想⾃⼰⼿写⼀遍的建议先看参考资料,再看这⾥的代码
参考资料
源代码
/*预处理*/
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <time.h>
/*宏定义*/
#define YES 1
#define NO 0
//蛇的移动⽅向
#define U 1 //上
#define D 2 //下
#define L 3 //左
#define R 4 //右
#define RESPEED 250 //蛇的移动速度
/*定义节点*/
typedef struct SNAKE
{
int x;
int y;
struct SNAKE* next;
}snake;
/*全局变量*/
snake* head, * food; //蛇头指针,⾷物指针
snake* q; //遍历蛇的时候⽤到的指针
/
*【以下为所有函数的声明】*/
void HideCursor(void); //隐藏光标
void color(short int num); //颜⾊函数
void StartWindow(void); //开始界⾯
int gotoxy(int x, int y); //定位光标位置
void creatMap(void); //创建地图
void notice(int* score, int* highscore, int* Time, int* LongTime); //提⽰
void initsnake(void); //初始化蛇⾝
int biteself(unsigned long* sleeptime); //判断是否咬到了⾃⼰
int createfood(void); //随机出现⾷物
void endgame(int* score, int* highscore, int* endgamestatus, int* Time, int* LongTime); //结束游戏
void pause(int* PauseBegin, int* PauseEnd); //暂停游戏
void gamecontrol(unsigned long* sleeptime, int* count, int* score, int* highscore, int* status, int* endgamestatus,
int* Time, int* LongTime, int* TimeBegin, int* TimeEnd, int* TimePause, int* PauseBegin, int* PauseEnd); //控制游戏(包含蛇不能穿墙)
void snakemove(unsigned long* sleeptime, int* count, int* score, int* status, int* endgamestatus); //蛇移动
void gamestart(int* score, int* highscore, int* endgamestatus, int* Time, int* LongTime, int* TimeBegin); //游戏初始化
void gamecontinue(unsigned long* sleeptime, int* count, int* score, int* highscore, int* status, int* endgamestatus,
int* Time, int* LongTime, int* TimeBegin, int* TimeEnd, int* TimePause, int* PauseBegin, int* PauseEnd); //再来⼀局
void stop(unsigned long* sleeptime); //蛇停⽌移动
void start(unsigned long* sleeptime); //蛇恢复移动
void reset(int* count, int* score, int* Time, int* TimeBegin, int* TimeEnd, int* TimePause, int* PauseBegin, int* PauseEnd); //重置多项数据
void updatescore(int* score, int* highscore, int* Time, int* LongTime); //更新多项数据
int main(void)
{
unsigned long sleeptime = RESPEED;
int score = 0, highscore = 0, count = 0; //count是记录吃到⾷物的次数
int status, endgamestatus = 0; //游戏结束情况,0未开始游戏前退出,1撞到墙,2咬到⾃⼰,3主动退出游戏,4通关
int TimeBegin, TimeEnd;
int Time, LongTime, TimePause, PauseBegin, PauseEnd;
HideCursor();
gamestart(&score, &highscore, &endgamestatus, &Time, &LongTime, &TimeBegin);
gamecontrol(&sleeptime, &count, &score, &highscore, &status, &endgamestatus, &Time, &LongTime, &TimeBegin, &TimeEnd, &TimePause, &Pa useBegin, &PauseEnd);
endgame(&score, &highscore, &endgamestatus, &Time, &LongTime);
gamecontinue(&sleeptime, &count, &score, &highscore, &status, &endgamestatus, &Time, &LongTime, &TimeBegin, &TimeEnd, &TimePause, &P auseBegin, &PauseEnd);
return 0;
}
void HideCursor(void) //隐藏光标
{
CONSOLE_CURSOR_INFO cursor_info = { 1, 0 };
SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info);
}
void color(short int num)
{
HANDLE hConsole = GetStdHandle((STD_OUTPUT_HANDLE));
SetConsoleTextAttribute(hConsole, num);
}
void StartWindow(void)
{
short int i;
system("mode con cols=120 lines=30"); //设置窗⼝⼤⼩
printf("温馨提⽰:请使⽤键盘操作(⿏标点击可能会导致程序出错)\n");
printf("╔═══════════════════════════════════════════════════╗ \n");
for (i = 0; i < 26; i++)
{
printf("║  ║ \n");
}
printf("╚═══════════════════════════════════════════════════╝ \n");
gotoxy(23, 2);
color(3);
printf("贪吃蛇");
for (i = 15; ; i--)
{
gotoxy(18, 4);
color(i);
printf("按任意键加载程序");
Sleep(600);
if (i == 1)
{
i = 15;
}
if (kbhit()) //判断是否按键,等待输⼊按键为0,按键为1
{
break;
}
}
gotoxy(10, 4);
printf("1.开始游戏          2.退出游戏");
getch();
}
int gotoxy(int x, int y)
{
HANDLE handle; //定义句柄变量handle,创建⼀个句柄
COORD pos; //定义结构体coord (坐标系coord)
pos.X = x; //横坐标x
pos.Y = y; //纵坐标y
handle = GetStdHandle(STD_OUTPUT_HANDLE); //获取控制台输出句柄(值为-11)
SetConsoleCursorPosition(handle, pos); //移动光标
return YES;
}
void creatMap(void)
{
int i;
//地图⼤⼩:长24×宽20
for (i = 2; i < 52; i += 2) //打印上下边框
{
printf("■");
gotoxy(i, 27);
printf("■");
}
for (i = 7; i < 28; i++) //打印左右边框
{
gotoxy(2, i);
printf("■");
gotoxy(50, i);
printf("■");
}
}
void notice(int* score, int* highscore, int* Time, int* LongTime)
{
system("title 2018051170 Project:贪吃蛇");
gotoxy(4, 4);
color(15);
printf("得分:%3d 最⾼分:%3d ⽣存:%4ds 最久⽣存:%4ds", *score, *highscore, *Time, *LongTime); gotoxy(60, 7);
printf("Author: 2018051170 Project: 贪吃蛇");
gotoxy(60, 9);
printf("游戏说明:");
gotoxy(60, 10);
printf("不能穿墙,不能咬到⾃⼰");
gotoxy(60, 11);
printf("↑↓←→控制蛇的移动");
gotoxy(60, 12);
printf("ESC:退出游戏空格:暂停游戏");
}
void initsnake(void)
{
int i;
snake* tail;
tail = (snake*)malloc(sizeof(snake)); //从蛇尾开始,插头法,以x,y设定开始的位置
tail->x = 26;
tail->y = 14;
tail->next = NULL;
for (i = 1; i < 3; i++)
{
head = (snake*)malloc(sizeof(snake));
head->next = tail;
head->x = 26 - 2 * i;
head->y = 14;
tail = head;
}
while (tail != NULL) //从头到为,输出蛇⾝
{
gotoxy(tail->x, tail->y);
if (i == 3)
{
color(2);
printf("●");
i++;
}
else if (tail != NULL)
{
color(2);
printf("■");
}
tail = tail->next;
}
}
int biteself(unsigned long* sleeptime)
{
snake* self;
self = head->next;
while (self != NULL)
{
if (self->x == head->x && self->y == head->y)
{
stop(sleeptime);
self = self->next;
}
return NO;
}
int createfood(void)
{
snake* food_1;
food_1 = (snake*)malloc(sizeof(snake));
srand((unsigned)time(NULL)); //产⽣⼀个随机数
while ((food_1->x % 2) != 0) //保证其为偶数,使得⾷物能与蛇头对其
{
food_1->x = rand() % 50; //保证其在墙壁⾥X1 < X < X2
if (food_1->x <= 4)
{
food_1->x = food_1->x + 4;
}
}
food_1->y = rand() % 27; //保证其在墙壁⾥Y1 < Y < Y2
if (food_1->y < 7)
{
food_1->y = food_1->y + 7;
}
q = head;
while (q != NULL) //判断蛇⾝是否与⾷物重合
{
if (q->x == food_1->x && q->y == food_1->y)
{
free(food_1);
return 1;
}
if (q->next == NULL)
{
break;
}
q = q->next;
}
gotoxy(food_1->x, food_1->y);
food = food_1;
color(3);
printf("★");
return 0;
}
void endgame(int* score, int* highscore, int* endgamestatus, int* Time, int* LongTime) {
color(15);
gotoxy(60, 14);
if (*endgamestatus == 0)
{
printf("您退出了游戏。");
}
else
{
if (*endgamestatus == 1)
{
printf("您撞到墙了,游戏结束。");
}
else if (*endgamestatus == 2)
{
printf("您咬到⾃⼰了,游戏结束。");
}
else if (*endgamestatus == 3)
{
printf("您已经结束了游戏。");
}
else if (*endgamestatus == 4)
{
printf("恭喜您通关了游戏!");
}
gotoxy(60, 15);
printf("您的得分是: %d", *score);
}
void pause(int* PauseBegin, int* PauseEnd)
{
*PauseBegin = time(NULL);
while (1)
{
Sleep(300);
if (GetAsyncKeyState(VK_SPACE))
{
*PauseEnd = time(NULL);
break;
}
}
}
void gamecontrol(unsigned long* sleeptime, int* count, int* score, int* highscore, int* status, int* endgamestatus, int* Time, int* LongTime, int* TimeBegin, int* TimeEnd, int* TimePause, int* PauseBegin, int* PauseEnd)
{
*status = L;
while (1)
{
*TimeEnd = time(NULL);
*TimePause = *TimePause + *PauseEnd - *PauseBegin;
*PauseBegin = *PauseEnd = 0;
*Time = *TimeEnd - *TimeBegin - *TimePause;
//实时更新得分
gotoxy(4, 4);
color(15);
printf("得分:%3d 最⾼分:%3d ⽣存:%4ds 最久⽣存:%4ds", *score, *highscore, *Time, *LongTime);
//如果撞墙,停⽌蛇的移动
if (head->x == 2 || head->x == 50 || head->y == 6 || head->y == 27)
{
stop(sleeptime);
*endgamestatus = 1;
break;
}
//如果咬到⾃⼰(在biteself函数⾥停⽌蛇的移动)
if (biteself(sleeptime) == 1)
{c语言游戏贪吃蛇源码
*endgamestatus = 2;
break;
}
//如果通关
if (*endgamestatus == 4)
{
break;
}
//读取到【↑】且蛇头指向不为【↓】
if (GetAsyncKeyState(VK_UP) && *status != D)
{
*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;
}
else if (GetAsyncKeyState(VK_SPACE)) //读取到【空格】
{
pause(PauseBegin, PauseEnd);
}
else if (GetAsyncKeyState(VK_ESCAPE)) //读取到【ESC】
{
stop(sleeptime);

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。