首页 > 分享 > 用C语言实现贪吃蛇游戏

用C语言实现贪吃蛇游戏

在这里,我们主要使用C语言和数据结构链表来实现对贪吃蛇小游戏的实现。

主函数

在主函数中,我们需要实现对贪吃蛇游戏的整体流程的实现。

HideCursor();//隐藏光标显示,调用一次 srand((unsigned)time(NULL)); Snake snake; //创建游戏框架 GameStart(&snake); //游戏开始 GameRun(&snake); //游戏过程 GameEnd(&snake); //游戏结束 123456

游戏信息定义

#define INIT_X 26 //初始位列 #define INIT_Y 12 //初始位行 enum Direction //蛇的运动方向 {UP, //上DOWN, //下LEFT, //左RIGHT //右 }; enum Gamestatus //游戏状态 {OK, //正常状态NORMAL_END, //正常退出KILL_BY_WALL, //撞墙死亡KILL_EY_SELF //撞蛇死亡 }; typedef struct SnakeNode //结点位置 {int x;int y;struct SnakeNode* next; }SnakeNode, *pSnakeNode; typedef struct Snake //游戏框架 {pSnakeNode _pSnake; //蛇头指针pSnakeNode _pFood; //食物位置指针int _TotalScore; //得分int _AddScore; //增加的分数int _SleepTime; //休眠时间enum Direction _Dir;//方向enum Gamestatus _status;//游戏状态 }Snake, *pSnake;

123456789101112131415161718192021222324252627282930313233343536

游戏信息设置

游戏界面设置

实现对游戏界面的初始化

void WecomeToGame()//打印欢迎界面 {//设置窗口大小system("mode con cols=100 lines=30");//设置DOS窗口的尺寸将会变为100列30行的/*键入mode con cols = 100 lines = 30则DOS窗口的尺寸将会变为30行100列的,cols(列)最小值为13,lines(行)最小值为1。在C语言中也可以通过system函数调用这个dos命令来实现这个功能。*///打印文字SerPos(37, 12); //定位光标 列,行printf("欢迎来到贪吃蛇小游戏");SerPos(37, 20);system("pause");system("cls");SerPos(37, 12); //定位光标 列,行printf("提示:↑ ↓ ← → 控制贪吃蛇方向");SerPos(37, 13); //定位光标 列,行printf("提示:F1:加速,F2,减速 加速可获得更高的分数");SerPos(37, 20);system("pause");system("cls"); }

123456789101112131415161718192021222324 创建地图

通过一些特殊字符,来实现对地图边界的划分.

void CreateMap()//创建地图 60列 * 28行 {int i = 0;//上边界for (i = 0; i < 60; i = i + 2){SerPos(i, 0); //定位光标 列,行printf("%s", "▇");}//下边界for (i = 0; i < 60; i = i + 2){SerPos(i, 27); //定位光标 列,行printf("%s", "▇");}//左边界for (i = 1; i < 27; i++){SerPos(0, i); //定位光标 列,行printf("%s", "▇");}//右边界for (i = 1; i < 27; i++){SerPos(58, i); //定位光标 列,行printf("%s", "▇");} }

12345678910111213141516171819202122232425262728 打印信息

void PrintInformation(pSnake ps)//打印信息 {//打印得分SerPos(70, 10);printf("得分:%d ", ps->_TotalScore);SerPos(70, 11);printf("当前所加得分:%d ", ps->_AddScore);//打印文字SerPos(70, 12);printf("↑ ↓ ← → 控制贪吃蛇方向");SerPos(70, 13);printf("提示:");SerPos(70, 14);printf("F1:加速,F2:减速");SerPos(70, 15);printf("空格:暂停");SerPos(70, 16);printf("Esc:退出"); }

12345678910111213141516171819

游戏流程

游戏开始

void GameStart(pSnake ps) //游戏开始 {//打印欢迎界面WecomeToGame();//创建地图CreateMap();//初始化蛇InitSnake(ps);//初始化食物CreateFood(ps);//初始化其他数据ps->_TotalScore = 0; //得分ps->_AddScore = 10; //增加的分数ps->_SleepTime = 500; //休眠时间ps->_Dir = RIGHT;//方向ps->_status = OK;//游戏状态 }

1234567891011121314151617 游戏过程

void GameRun(pSnake ps) //游戏过程 {do{DirectionOfDdtermination(ps);//键盘输入操作SnakeMovement(ps);//蛇移动PrintInformation(ps);//打印信息KillByWall(ps);//被墙撞死KillBySelf(ps);//被蛇撞死Sleep(ps->_SleepTime); //蛇睡眠} while (OK == ps->_status); } 12345678910111213 游戏结束

void GameEnd(pSnake ps)//游戏结束 {if(NORMAL_END == ps->_status){SerPos(22, 13);printf("游戏结束!");}else if(KILL_BY_WALL == ps->_status){SerPos(22, 13);printf("撞墙,游戏结束!");}else if (KILL_EY_SELF == ps->_status){SerPos(22, 13);printf("撞蛇身,游戏结束!");}//释放蛇while (NULL != ps->_pSnake){pSnakeNode del = ps->_pSnake;ps->_pSnake = ps->_pSnake->next;free(del);del = NULL;}//释放食物free(ps->_pFood);ps->_pFood = NULL; }

1234567891011121314151617181920212223242526272829

初始化蛇与食物

void InitSnake(pSnake ps)//初始化蛇 {//创建蛇身//创建第一个结点pSnakeNode first = BuyNode();first->x = INIT_X;first->y = INIT_Y;//创建剩余结点pSnakeNode cur;for (int i = 0; i < 4; i++){//创建结点cur = BuyNode();cur->x = first->x + 2;cur->y = first->y;//插入节点(头插)cur->next = first;first = cur;}ps->_pSnake = first; //蛇头指针//打印蛇while (cur != NULL) //循环cur指向第一个结点{SerPos(cur->x, cur->y);printf("%s", "■");cur = cur->next;}printf("n"); }

1234567891011121314151617181920212223242526272829 食物

void CreateFood(pSnake ps)//生成食物 {pSnakeNode pfood = BuyNode(); //食物结点 again://随机生成食物的位置do //列{pfood->x = rand()%55 + 2; //2-56 0-54+2} while (0 != pfood->x % 2); //x必须为偶数,否则蛇吃不到pfood->y = rand() % 26 + 1;//1-26 0-25+//行pSnakeNode cur = ps->_pSnake; //蛇头while (NULL != cur) //遍历蛇身,防止食物出现在蛇身上{if (cur->x == pfood->x && cur->y == pfood->y){goto again; //跳转至again处}cur = cur->next;}ps->_pFood = pfood;SerPos(pfood->x, pfood->y);printf("%s", "★"); }

123456789101112131415161718192021222324 吃食物

void EatFood(pSnake ps, pSnakeNode snewnode)//吃食物 {//把新节点插入到蛇中snewnode->next = ps->_pSnake;ps->_pSnake = snewnode;//打印新结点SerPos(ps->_pSnake->x, ps->_pSnake->y);printf("■");//加分ps->_TotalScore = ps->_TotalScore + ps->_AddScore;//重新生成食物CreateFood(ps); } 12345678910111213 无食物

void NoFood(pSnake ps, pSnakeNode snewnode)//无食物 {//把新节点插入到蛇中snewnode->next = ps->_pSnake;ps->_pSnake = snewnode;//打印新结点SerPos(ps->_pSnake->x, ps->_pSnake->y);printf("%s", "■");//处理尾结点 需要把倒数第二个结点的next变成空pSnakeNode cur = ps->_pSnake;while (cur->next->next != NULL) //尾结点{cur = cur->next;}SerPos(cur->next->x, cur->next->y);printf(" ");free(cur->next);cur->next = NULL; }

12345678910111213141516171819

控制蛇移动

键盘输入

void DirectionOfDdtermination(pSnake ps)//键盘输入操作 {if (DOWN != ps->_Dir && GetAsyncKeyState(VK_UP))//向上,不能走回去{ps->_Dir = UP;}else if (UP != ps->_Dir && GetAsyncKeyState(VK_DOWN))//向下{ps->_Dir = DOWN;}else if (RIGHT != ps->_Dir && GetAsyncKeyState(VK_LEFT))//向左{ps->_Dir = LEFT;}else if (LEFT != ps->_Dir && GetAsyncKeyState(VK_RIGHT))//向右{ps->_Dir = RIGHT;}else if (GetAsyncKeyState(VK_SPACE))//暂停{Pause();//时间暂停,如果任意键为空格,则会读取一个空格}else if (GetAsyncKeyState(VK_ESCAPE))//退出{ps->_status = NORMAL_END;}else if (GetAsyncKeyState(VK_F1))//加速{//300if (ps->_AddScore < 15){ps->_AddScore = ps->_AddScore + 1; //增加的分数+1ps->_SleepTime = ps->_SleepTime - 30; //休眠时间-30 min=150}}else if (GetAsyncKeyState(VK_F2))//减速{if (ps->_AddScore > 5){ps->_AddScore = ps->_AddScore - 1; //增加的分数-1ps->_SleepTime = ps->_SleepTime + 30; //休眠时间-30 max = 450}} }

123456789101112131415161718192021222324252627282930313233343536373839404142434445 蛇移动

void SnakeMovement(pSnake ps)//蛇移动 {pSnakeNode snewnode = BuyNode(); //创捷新结点switch (ps->_Dir){case UP://向上{//新结点赋值snewnode->x = ps->_pSnake->x;snewnode->y = ps->_pSnake->y - 1;//判断是否为食物if (snewnode->x == ps->_pFood->x && snewnode->y == ps->_pFood->y) //是食物{EatFood(ps, snewnode);}else//不是食物{NoFood(ps, snewnode);}}break;case DOWN://向下{//新结点赋值snewnode->x = ps->_pSnake->x;snewnode->y = ps->_pSnake->y + 1;//判断是否为食物if (snewnode->x == ps->_pFood->x && snewnode->y == ps->_pFood->y) //是食物{EatFood(ps, snewnode);}else//不是食物{NoFood(ps, snewnode);}}break;case LEFT://向左{//新结点赋值snewnode->x = ps->_pSnake->x - 2;snewnode->y = ps->_pSnake->y;//判断是否为食物if (snewnode->x == ps->_pFood->x && snewnode->y == ps->_pFood->y) //是食物{EatFood(ps, snewnode);}else//不是食物{NoFood(ps, snewnode);}}break;case RIGHT://向右{//新结点赋值snewnode->x = ps->_pSnake->x + 2;snewnode->y = ps->_pSnake->y;//判断是否为食物if (snewnode->x == ps->_pFood->x && snewnode->y == ps->_pFood->y) //是食物{EatFood(ps, snewnode);}else//不是食物{NoFood(ps, snewnode);}}break;} }

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071

判断游戏失败

被墙撞死

void KillByWall(pSnake ps)//被墙撞死 {//2-58 1-26if (ps->_pSnake->x< 2 ||ps->_pSnake->x > 56 ||ps->_pSnake->y < 1 ||ps->_pSnake->y > 26){ps->_status = KILL_BY_WALL;} } 1234567891011 被蛇身撞死

void KillBySelf(pSnake ps)//被蛇身撞死 {pSnakeNode cur = ps->_pSnake->next;while (NULL != cur){if (ps->_pSnake->x == cur->x && ps->_pSnake->y == cur->y){ps->_status = KILL_EY_SELF;return;}cur = cur->next;} } 12345678910111213

辅助函数

void HideCursor()//隐藏光标显示,只需调用一次 {CONSOLE_CURSOR_INFO cursor_info = { 1, 0 };SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info); } void SerPos(int x, int y) //定位光标,将光标调整到(x,y)的位置 列,行 {HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);//获取标准输出的句柄COORD pos = { 0 };pos.X = x;pos.Y = y;SetConsoleCursorPosition(handle, pos); //设置标准输出上光标的位置为pos } void Pause()//时间暂停 {while (1){Sleep(100);if (GetAsyncKeyState(VK_SPACE)){break;}} }

123456789101112131415161718192021222324

源代码

snake.h

#ifndef __SNAKE_H__ #define __SNAKE_H__ #include <stdio.h> #include <windows.h> #include <string.h> #include <stdlib.h> #include <time.h> #define INIT_X 26 #define INIT_Y 12 enum Direction //蛇的运动方向 {UP,DOWN,LEFT,RIGHT }; enum Gamestatus //游戏状态 {OK,NORMAL_END,KILL_BY_WALL,KILL_EY_SELF }; typedef struct SnakeNode //结点位置 {int x;int y;struct SnakeNode* next; }SnakeNode, *pSnakeNode; typedef struct Snake //游戏框架 {pSnakeNode _pSnake;pSnakeNode _pFood;int _TotalScore;int _AddScore;int _SleepTime;enum Direction _Dir;enum Gamestatus _status; }Snake, *pSnake; void HideCursor();//隐藏光标显示,调用一次 void SerPos(int x, int y);//定位光标 void WecomeToGame();//打印欢迎界面 void CreateMap();//创建地图 pSnakeNode BuyNode(); //创捷新结点 void InitSnake(pSnake ps);//初始化蛇 void CreateFood(pSnake ps);//生成食物 void Pause();//时间暂停 void DirectionOfDdtermination(pSnake ps);//键盘输入操作 void EatFood(pSnake ps, pSnakeNode snewnode);//吃食物 void NoFood(pSnake ps, pSnakeNode snewnode);//无食物 void SnakeMovement(pSnake ps);//蛇移动 void PrintInformation(pSnake ps);//打印信息 void KillByWall(pSnake ps);//被墙撞死 void KillBySelf(pSnake ps);//被蛇撞死 void GameStart(pSnake ps);//游戏开始 void GameRun(pSnake ps); //游戏过程 void GameEnd(pSnake ps);//游戏结束 #endif __SNAKE_H__

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364 snack.c

#include "snake.h" void HideCursor()//隐藏光标显示,调用一次 {CONSOLE_CURSOR_INFO cursor_info = { 1, 0 };SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info); } void SerPos(int x, int y) //定位光标,将光标调整到(x,y)的位置 列,行 {HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);COORD pos = { 0 };pos.X = x;pos.Y = y;SetConsoleCursorPosition(handle, pos); } void WecomeToGame()//打印欢迎界面 {system("mode con cols=100 lines=30");SerPos(37, 12);printf("欢迎来到贪吃蛇小游戏");SerPos(37, 20);system("pause");system("cls");SerPos(37, 12);printf("提示:↑ ↓ ← → 控制贪吃蛇方向");SerPos(37, 13);printf("提示:F1:加速,F2,减速 加速可获得更高的分数");SerPos(37, 20);system("pause");system("cls"); } void CreateMap()//创建地图 60列 * 28行 {int i = 0;for (i = 0; i < 60; i = i + 2){SerPos(i, 0);printf("%s", "▇");}for (i = 0; i < 60; i = i + 2){SerPos(i, 27);printf("%s", "▇");}for (i = 1; i < 27; i++){SerPos(0, i);printf("%s", "▇");}for (i = 1; i < 27; i++){SerPos(58, i);printf("%s", "▇");} } pSnakeNode BuyNode() //创捷新结点 {pSnakeNode psnake = (pSnakeNode)malloc(sizeof(SnakeNode));if (NULL == psnake){perror(NULL);exit(EXIT_FAILURE);}psnake->next = NULL;return psnake; } void InitSnake(pSnake ps)//初始化蛇 {pSnakeNode first = BuyNode();first->x = INIT_X;first->y = INIT_Y;pSnakeNode cur;for (int i = 0; i < 4; i++){cur = BuyNode();cur->x = first->x + 2;cur->y = first->y;cur->next = first;first = cur;}ps->_pSnake = first;while (cur != NULL){SerPos(cur->x, cur->y);printf("%s", "■");cur = cur->next;}printf("n"); } void CreateFood(pSnake ps)//生成食物 {pSnakeNode pfood = BuyNode(); again:do{pfood->x = rand()%55 + 2;} while (0 != pfood->x % 2);pfood->y = rand() % 26 + 1;pSnakeNode cur = ps->_pSnake;while (NULL != cur){if (cur->x == pfood->x && cur->y == pfood->y){goto again;}cur = cur->next;}ps->_pFood = pfood;SerPos(pfood->x, pfood->y);printf("%s", "★"); } void Pause()//时间暂停 {while (1){Sleep(100);if (GetAsyncKeyState(VK_SPACE)){break;}} } void DirectionOfDdtermination(pSnake ps)//键盘输入操作 {if (DOWN != ps->_Dir && GetAsyncKeyState(VK_UP)){ps->_Dir = UP;}else if (UP != ps->_Dir && GetAsyncKeyState(VK_DOWN)){ps->_Dir = DOWN;}else if (RIGHT != ps->_Dir && GetAsyncKeyState(VK_LEFT)){ps->_Dir = LEFT;}else if (LEFT != ps->_Dir && GetAsyncKeyState(VK_RIGHT)){ps->_Dir = RIGHT;}else if (GetAsyncKeyState(VK_SPACE)){Pause();}else if (GetAsyncKeyState(VK_ESCAPE)){ps->_status = NORMAL_END;}else if (GetAsyncKeyState(VK_F1)){if (ps->_AddScore < 15){ps->_AddScore = ps->_AddScore + 1;ps->_SleepTime = ps->_SleepTime - 30;}}else if (GetAsyncKeyState(VK_F2)){if (ps->_AddScore > 5){ps->_AddScore = ps->_AddScore - 1;ps->_SleepTime = ps->_SleepTime + 30;}} } void EatFood(pSnake ps, pSnakeNode snewnode)//吃食物 {snewnode->next = ps->_pSnake;ps->_pSnake = snewnode;SerPos(ps->_pSnake->x, ps->_pSnake->y);printf("■");ps->_TotalScore = ps->_TotalScore + ps->_AddScore;CreateFood(ps); } void NoFood(pSnake ps, pSnakeNode snewnode)//无食物 {snewnode->next = ps->_pSnake;ps->_pSnake = snewnode;SerPos(ps->_pSnake->x, ps->_pSnake->y);printf("%s", "■");pSnakeNode cur = ps->_pSnake;while (cur->next->next != NULL){cur = cur->next;}SerPos(cur->next->x, cur->next->y);printf(" ");free(cur->next);cur->next = NULL; } void SnakeMovement(pSnake ps)//蛇移动 {pSnakeNode snewnode = BuyNode();switch (ps->_Dir){case UP:{snewnode->x = ps->_pSnake->x;snewnode->y = ps->_pSnake->y - 1;if (snewnode->x == ps->_pFood->x && snewnode->y == ps->_pFood->y){EatFood(ps, snewnode);}else{NoFood(ps, snewnode);}}break;case DOWN:{snewnode->x = ps->_pSnake->x;snewnode->y = ps->_pSnake->y + 1;if (snewnode->x == ps->_pFood->x && snewnode->y == ps->_pFood->y){EatFood(ps, snewnode);}else{NoFood(ps, snewnode);}}break;case LEFT:{snewnode->x = ps->_pSnake->x - 2;snewnode->y = ps->_pSnake->y;if (snewnode->x == ps->_pFood->x && snewnode->y == ps->_pFood->y){EatFood(ps, snewnode);}else{NoFood(ps, snewnode);}}break;case RIGHT:{snewnode->x = ps->_pSnake->x + 2;snewnode->y = ps->_pSnake->y;if (snewnode->x == ps->_pFood->x && snewnode->y == ps->_pFood->y){EatFood(ps, snewnode);}else{NoFood(ps, snewnode);}}break;} } void PrintInformation(pSnake ps)//打印信息 {SerPos(70, 10);printf("得分:%d ", ps->_TotalScore);SerPos(70, 11);printf("当前所加得分:%d ", ps->_AddScore);SerPos(70, 12);printf("↑ ↓ ← → 控制贪吃蛇方向");SerPos(70, 13);printf("提示:");SerPos(70, 14);printf("F1:加速,F2:减速");SerPos(70, 15);printf("空格:暂停");SerPos(70, 16);printf("Esc:退出"); } void KillByWall(pSnake ps)//被墙撞死 {if (ps->_pSnake->x< 2 ||ps->_pSnake->x > 56 ||ps->_pSnake->y < 1 ||ps->_pSnake->y > 26){ps->_status = KILL_BY_WALL;} } void KillBySelf(pSnake ps)//被蛇撞死 {pSnakeNode cur = ps->_pSnake->next;while (NULL != cur){if (ps->_pSnake->x == cur->x && ps->_pSnake->y == cur->y){ps->_status = KILL_EY_SELF;return;}cur = cur->next;} } void GameStart(pSnake ps) //游戏开始 {WecomeToGame();CreateMap();InitSnake(ps);CreateFood(ps);ps->_TotalScore = 0;ps->_AddScore = 10;ps->_SleepTime = 500;ps->_Dir = RIGHT;ps->_status = OK; } void GameRun(pSnake ps) //游戏过程 {do{DirectionOfDdtermination(ps);SnakeMovement(ps);PrintInformation(ps);KillByWall(ps);KillBySelf(ps);Sleep(ps->_SleepTime);} while (OK == ps->_status); } void GameEnd(pSnake ps)//游戏结束 {if(NORMAL_END == ps->_status){SerPos(22, 13);printf("游戏结束!");}else if(KILL_BY_WALL == ps->_status){SerPos(22, 13);printf("撞墙,游戏结束!");}else if (KILL_EY_SELF == ps->_status){SerPos(22, 13);printf("撞蛇身,游戏结束!");}while (NULL != ps->_pSnake){pSnakeNode del = ps->_pSnake;ps->_pSnake = ps->_pSnake->next;free(del);del = NULL;}free(ps->_pFood);ps->_pFood = NULL; }

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364 main.c

#include "snake.h" void test() {HideCursor();srand((unsigned)time(NULL));Snake snake;GameStart(&snake);GameRun(&snake);GameEnd(&snake); } int main() {test();return 0; }

12345678910111213141516

相关知识

用C语言实现贪吃蛇游戏
贪吃蛇(C语言)2018
基于单片机的贪吃蛇游戏设计
C语言贪吃蛇,流畅版,可继续升级改造
单片机贪吃蛇 毕业设计.pdf
python+pygame 贪吃蛇游戏
贪吃蛇游戏程序设计实验报告
贪吃蛇小程序(功能完善)
C的课程规范设计贪吃蛇小游戏内附完整源码及附件.doc
用c语言写一个桌面宠物

网址: 用C语言实现贪吃蛇游戏 https://m.mcbbbk.com/newsview657294.html

所属分类:萌宠日常
上一篇: 353 贪吃蛇
下一篇: 蛇含