行业知识
贪吃蛇(C语言实现)
2026-11-16 02:34:31
来源:互联网转载
�� 贪食蛇(也叫贪吃蛇)是一款经典的小游戏。
——————————————————————
本博客实现使用C语言在Windows环境的控制台中模拟实现贪吃蛇小游戏。
实行的基本功能:
• 贪吃蛇地图的绘制
• 蛇吃食物的功能(上、下、左、右方向键来控制蛇的方向)
• 蛇撞墙***亡
• 蛇撞自身***亡
• 计算得分
• 蛇身加速、减速
• 暂停游戏
主要框架(主要函数):
GameStrat();//游戏开始前的初始化GameRun();//玩游戏的过程GameEnd();//善后工作(节点的释放)
游戏流程设计:
参考代码:
snake.h
#pragma once#include #include #include #include #include #define WALL L'□'#define BODY L'●'#define FOOD L'★'//蛇默认的起始坐标#define POS_X 24#define POS_Y 5#define KEY_PRESS(VK) ( (GetAsyncKeyState(VK) & 0x1) ? 1 : 0 )//游戏的状态enum GAME_STATUS{OK=1,//正常运行ESC, //按了ESC键退出,正常退出KILL_BY_WALL,//撞墙KILL_BY_SELF //撞到自身};//蛇行走的方向enum DIRECTION{UP=1,DOWN,LEFT,RIGHT};//蛇身结点的定义typedef struct SnakeNode{int x;int y;struct SnakeNode* next;}SnakeNode, * pSnakeNode;//贪吃蛇typedef struct Snake{pSnakeNode pSnake;//维护整条蛇的指针,是指向蛇头pSnakeNode pFood;//指向食物的指针int Score;//当前累积的分数int FoodWeight;//一个食物的分数int SleepTime;//蛇休眠的时间,休眠的时间越短,蛇的速度越快,休眠的时间越长,蛇的速度越慢enum GAME_STATUS status;//游戏当前的状态enum DIRECTION dir;//蛇当前走的方向//...}Snake, * pSnake;//定位控制台光标位置void SetPos(int x, int y);//游戏开始前的准备void GameStart(pSnake ps);//打印欢迎界面void WelcomeToGame();//绘制地图void CreateMap();//初始化贪吃蛇void InitSnake(pSnake ps);//创建食物void CreateFood(pSnake ps);//游戏运行的整个逻辑void GameRun(pSnake ps);//打印帮助信息void PrintHelpInfo();//蛇移动的函数- 每次走一步void SnakeMove(pSnake ps);//判断蛇头的下一步要走的位置处是否是食物int NextIsFood(pSnake ps, pSnakeNode pNext);//下一步要走的位置处就是食物,就吃掉食物void EatFood(pSnake ps, pSnakeNode pNext);//下一步要走的位置处不是食物,不吃食物void NotEatFood(pSnake ps, pSnakeNode pNext);//检测是否撞墙void KillByWall(pSnake ps);//检测是否撞自己void KillBySelf(pSnake ps);//游戏结束的资源释放void GameEnd(pSnake ps); snake.c
#define _CRT_SECURE_NO_WARNINGS 1#include "snake.h"void SetPos(int x,int y){//获得设备句柄HANDLE hanlde = GetStdHandle(STD_OUTPUT_HANDLE);//根据句柄设置光标的位置COORD pos = { x, y };SetConsoleCursorPosition(hanlde, pos);}void WelcomeToGame(){//欢迎信息SetPos(35, 10);printf("欢迎来到贪吃蛇小游戏\n");SetPos(38, 20);system("pause");system("cls");//功能介绍信息SetPos(15, 10);printf("用 ↑ . ↓ . ← . → 来控制蛇的移动,F3是加速,F4是减速");SetPos(15, 11);printf("加速能得到更高的分数");SetPos(38, 20);system("pause");system("cls");}void CreateMap(){int i = 0;//上SetPos(0, 0);for (i = 0; i pSnake == NULL){ps->pSnake = cur;}else{cur->next = ps->pSnake;ps->pSnake = cur;}}//打印蛇身cur = ps->pSnake;while (cur){SetPos(cur->x, cur->y);wprintf(L"%lc", BODY);cur = cur->next;}//贪吃蛇的其他信息初始化ps->dir = RIGHT;ps->FoodWeight = 10;ps->pFood = NULL;ps->Score = 0;ps->SleepTime = 200;ps->status = OK;}void CreateFood(pSnake ps){int x = 0;int y = 0;again:do{x = rand() % 53 + 2;y = rand() % 24 + 1;} while (x % 2 != 0);//坐标和蛇的身体的每个节点的做坐标比较pSnakeNode cur = ps->pSnake;while (cur){if (x == cur->x && y == cur->y){goto again;}cur = cur->next;}//创建食物pSnakeNode pFood = (pSnakeNode)malloc(sizeof(SnakeNode));if (pFood == NULL){perror("CreateFood()::malloc()");return;}pFood->x = x;pFood->y = y;ps->pFood = pFood;SetPos(x, y);wprintf(L"%lc", FOOD);}void GameStart(pSnake ps){//设置控制台的信息,窗口大小,窗口名system("mode con cols=100 lines=30");system("title 贪吃蛇");//隐藏光标HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);CONSOLE_CURSOR_INFO CursorInfo;GetConsoleCursorInfo(handle, &CursorInfo);//获取控制台光标信息CursorInfo.bVisible = false;SetConsoleCursorInfo(handle, &CursorInfo);//打印欢迎信息WelcomeToGame();//绘制地图CreateMap();//初始化蛇InitSnake(ps);//创建食物CreateFood(ps);}void PrintHelpInfo(){SetPos(62, 15);printf("1.不能穿墙,不能咬到自己");SetPos(62, 16);printf("2.用 ↑.↓.←.→ 来控制蛇的移动"); SetPos(62, 17);printf("3.F3是加速,F4是减速");SetPos(62, 19);printf("版权@比特就业课");}void pause(){while (1){Sleep(100);if (KEY_PRESS(VK_SPACE)){break;}}}int NextIsFood(pSnake ps, pSnakeNode pNext){if (ps->pFood->x == pNext->x && ps->pFood->y == pNext->y)return 1;//下一个坐标处是食物elsereturn 0;}void EatFood(pSnake ps, pSnakeNode pNext){pNext->next = ps->pSnake;ps->pSnake = pNext;//打印蛇pSnakeNode cur = ps->pSnake;while (cur){SetPos(cur->x, cur->y);wprintf(L"%lc", BODY);cur = cur->next;}ps->Score += ps->FoodWeight;//释放旧的食物free(ps->pFood);//新建食物CreateFood(ps);}void NotEatFood(pSnake ps, pSnakeNode pNext){//头插法pNext->next = ps->pSnake;ps->pSnake = pNext;//释放尾结点pSnakeNode cur = ps->pSnake;while (cur->next->next){SetPos(cur->x, cur->y);wprintf(L"%lc", BODY);cur = cur->next;}//将尾节点的位置打印成空白字符SetPos(cur->next->x, cur->next->y);printf(" ");free(cur->next);cur->next = NULL;//易错}//检测是否撞墙void KillByWall(pSnake ps){if (ps->pSnake->x == 0 ||ps->pSnake->x == 56 ||ps->pSnake->y == 0 ||ps->pSnake->y == 26){ps->status = KILL_BY_WALL;}}//检测是否撞自己void KillBySelf(pSnake ps){pSnakeNode cur = ps->pSnake->next;//从第二个节点开始while (cur){if (cur->x == ps->pSnake->x && cur->y == ps->pSnake->y){ps->status = KILL_BY_SELF;return;}cur = cur->next;}}void SnakeMove(pSnake ps){pSnakeNode pNext = (pSnakeNode)malloc(sizeof(SnakeNode));if (pNext == NULL){perror("SnakeMove()::malloc()");return;}pNext->next = NULL;switch (ps->dir){case UP:pNext->x = ps->pSnake->x;pNext->y = ps->pSnake->y - 1;break;case DOWN:pNext->x = ps->pSnake->x;pNext->y = ps->pSnake->y + 1;break;case LEFT:pNext->x = ps->pSnake->x-2;pNext->y = ps->pSnake->y;break;case RIGHT:pNext->x = ps->pSnake->x+2;pNext->y = ps->pSnake->y;break;}//下一个坐标处是否是食物if (NextIsFood(ps, pNext)){//是食物就吃掉EatFood(ps, pNext);}else{//不是食物就正常一步NotEatFood(ps, pNext);}//检测撞墙KillByWall(ps);//检测撞到自己KillBySelf(ps);}void GameRun(pSnake ps){//打印帮助信息PrintHelpInfo();do{//当前的分数情况SetPos(62, 10);printf("总分:%5d\n", ps->Score);SetPos(62, 11);printf("食物的分值:%02d\n", ps->FoodWeight); //检测按键//上、下、左、右、ESC、空格、F3、F4if (KEY_PRESS(VK_UP) && ps->dir != DOWN){ps->dir = UP;}else if (KEY_PRESS(VK_DOWN) && ps->dir != UP){ps->dir = DOWN;}else if (KEY_PRESS(VK_LEFT) && ps->dir != RIGHT){ps->dir = LEFT;}else if (KEY_PRESS(VK_RIGHT) && ps->dir != LEFT){ps->dir = RIGHT;}else if (KEY_PRESS(VK_ESCAPE)){ps->status = ESC;break;}else if (KEY_PRESS(VK_SPACE)){//游戏要暂定pause();//暂定和回复暂定}else if(KEY_PRESS(VK_F3)){if (ps->SleepTime >= 80){ps->SleepTime -= 30;ps->FoodWeight += 2;}}else if (KEY_PRESS(VK_F4)){if (ps->FoodWeight > 2){ps->SleepTime += 30;ps->FoodWeight -= 2;}}//走一步SnakeMove(ps);//睡眠一下Sleep(ps->SleepTime);} while (ps->status == OK);}void GameEnd(pSnake ps){SetPos(15, 12);switch (ps->status){case ESC:printf("主动退出游戏,正常退出\n");break;case KILL_BY_WALL:printf("很遗憾,撞墙了,游戏结束\n");break;case KILL_BY_SELF:printf("很遗憾,咬到自己了,游戏结束\n");break;}//释放贪吃蛇的链表资源pSnakeNode cur = ps->pSnake;pSnakeNode del = NULL;while (cur){del = cur;cur = cur->next;free(del);}free(ps->pFood);ps = NULL;} test.c
#define _CRT_SECURE_NO_WARNINGS 1#include "snake.h"void test(){//创建贪食蛇int ch = 0;do{Snake snake = { 0 };GameStart(&snake);//游戏开始前的初始化GameRun(&snake);//玩游戏的过程GameEnd(&snake);//善后的工作SetPos(20, 15);printf("再来一局吗?(Y/N):");ch = getchar();getchar();// 清理\n} while (ch == 'Y' || ch =='y');}int main(){//修改适配本地中文环境setlocale(LC_ALL, "");test();//贪吃蛇游戏的测试SetPos(0, 27);return 0;} 这个博客如果对你有帮助,给博主一个免费的点赞就是最大的帮助❤
欢迎各位点赞,收藏和关注哦❤
如果有疑问或有不同见解,欢迎在评论区留言哦❤
后续我会一直分享双一流211西北大学软件(C,数据结构,C++,Linux,MySQL)的学习干货以及重要代码的分享