本篇仅提供C语言代码,详细讲解在这篇博客:C语言:贪吃蛇游戏(从0开始完整版)-CSDN博客
QQ2024618-155655

- #pragma once
- #include
- #include
- #include
- #include
- #include
- #include
-
- #define POS_X 24
- #define POS_Y 5
-
- #define WALL L'□'
- #define BODY L'●'
- #define FOOD L'★'
-
-
- //类型的声明
-
- //蛇的方向
- enum DIRECTION
- {
- UP = 1,
- DOWN,
- LEFT,
- RIGHT
- };
-
-
- //蛇的状态
- //正常、撞墙、撞到自己、正常退出
- enum GAME_STATUS
- {
- OK, //正常
- KILL_BY_WALL, //撞墙
- KILL_BY_SELF, //撞到自己
- END_NORMAL //正常退出
- };
-
- //蛇身的节点类型
- typedef struct SnakeNode
- {
- //坐标
- int x;
- int y;
- //指向下一个节点的指针
- struct SnakeNode* next;
- }SnakeNode, * pSnakeNode;
-
- //贪吃蛇
- typedef struct Snake
- {
- pSnakeNode _pSnake;//指向蛇头的指针
- pSnakeNode _pFood;//指向食物节点的指针
- enum DIRECTION _dir;//蛇的方向
- enum GAME_STATUS _status;//游戏的状态
- int _food_weight;//一个食物的分数
- int _score; //总成绩
- int _sleep_time; //休息时间,时间越短,速度越快,时间越长,速度越慢
- }Snake, * pSnake;
-
- //函数的声明
- //
- //
- //定位光标位置
- void SetPos(int x, int y);
-
- //欢迎界面的打印
- void WelcomeToGame();
-
- //游戏的初始化
- void GameStart(pSnake ps);
-
- //创建地图
- void CreateMap();
-
- //初始化蛇身
- void InitSnake(pSnake ps);
-
- //创建食物
- void CreateFood(pSnake ps);
-
- //游戏运行的逻辑
- void GameRun(pSnake ps);
-
- //蛇的移动-走一步
- void SnakeMove(pSnake ps);
-
- //判断下一个坐标是否是食物
- int NextIsFood(pSnakeNode next, pSnake ps);
-
- //下一个位置是食物,就吃掉食物
- void EatFood(pSnakeNode next, pSnake ps);
-
- //下一个位置不是食物
- void NoFood(pSnakeNode next, pSnake ps);
-
- //检测蛇是否撞墙
- void KillByWall(pSnake ps);
-
- //检测蛇是否撞到自己
- void KillBySelf(pSnake ps);
-
- //游戏善后的工作
- void GameEnd(pSnake ps);
- #define _CRT_SECURE_NO_WARNINGS 1
- #include "snake.h"
- void SetPos(int x, int y)
- {
- HANDLE hOutput = NULL;
- //获取标准输出的句柄(⽤来标识不同设备的数值)
- hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
- COORD pos = { x,y };
- SetConsoleCursorPosition(hOutput, pos);
- }
- void WelcomeToGame()
- {
- SetPos(40, 12);
- wprintf(L"欢迎来到贪吃蛇小游戏!");
- SetPos(43, 17);
- system("pause");
- system("cls");
- SetPos(25, 14);
- wprintf(L"用 ↑. ↓ . ← . → 来控制蛇的移动,按F3加速,F4减速\n");
- SetPos(40, 16);
- wprintf(L"加速能够得到更高的分数\n");
- SetPos(43, 20);
- system("pause");
- system("cls");
- }
- //●
- void CreateMap()
- {
- //上围墙
- for (int i = 0; i < 29; i++)
- {
- wprintf(L"%c", WALL);
- }
- //下围墙
- SetPos(0, 26);
- for (int i = 0; i < 29; i++)
- {
- wprintf(L"%c", WALL);
- }
- //左围墙
- for (int i = 1; i < 26; i++)
- {
- SetPos(0, i);
- wprintf(L"%c", WALL);
- }
- //右围墙
- {
- for (int i = 1; i < 26; i++)
- {
- SetPos(56, i);
- wprintf(L"%c", WALL);
- }
- }
- }
- #include
- //初始化蛇身
- void InitSnake(pSnake ps)
- {
- pSnakeNode cur = NULL;
- for (int i = 0; i < 5; i++)
- {
- cur = (pSnakeNode)malloc(sizeof(SnakeNode));
- if (cur == NULL)
- {
- perror("InitSnake::malloc() fail\n");
- return;
- }
- cur->x = POS_X + i * 2;
- cur->y = POS_Y;
- cur->next = NULL;
-
- if (ps->_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->_score = 0;
- ps->_food_weight = 10;
- ps->_sleep_time = 200;//单位是毫秒
- ps->_status = OK;
- }
-
- //创建食物
- void CreateFood(pSnake ps)
- {
- #if 1
- int x = 0;
- int y = 0;
- again:
- do
- {
- x = rand() % 53 + 2;//2~54
- y = rand() % 25 + 1;//1~25
- } while (x % 2 != 0);//只能为2的倍数
-
- pSnakeNode cur = ps->_pSnake;
-
- while (cur)
- {
- //不能和蛇身的坐标重合
- if (cur->x == x && cur->y == 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;
- pFood->next = NULL;
-
- SetPos(x, y);
- wprintf(L"%lc", FOOD);
-
- ps->_pFood = pFood;
- #endif
-
- }
- void GameStart(pSnake ps)
- {
- system("mode con cols=100 lines=30");
- system("title 贪吃蛇");
- HANDLE houtput = GetStdHandle(STD_OUTPUT_HANDLE);
- //隐藏光标操作
- CONSOLE_CURSOR_INFO CursorInfo;
- GetConsoleCursorInfo(houtput, &CursorInfo);//获取控制台光标信息
- CursorInfo.bVisible = false; //隐藏控制台光标
- SetConsoleCursorInfo(houtput, &CursorInfo);//设置控制台光标状态
- WelcomeToGame();
- CreateMap();
- InitSnake(ps);
- CreateFood(ps);
- }
-
- void HelpInfor(pSnake ps)
- {
- SetPos(60, 12);
- printf("不能穿墙,不能咬伤自己");
- SetPos(60, 13);
- printf("用 ↑. ↓ . ← . → 来控制蛇的移动");
- SetPos(60, 14);
- printf("按F3加速,F4减速");
- SetPos(60, 15);
- printf("ESC:退出游戏 space:暂停游戏");
- SetPos(60, 18);
- printf("由用户 小丁爱养花 制作");
- }
-
-
- //最⾼位是1,说明按键的状态是按下,
- // 如果最⾼是0,说明按键的状态是抬起
- #define KeyPress(VK) (GetAsyncKeyState(VK)&1)
-
- void Pause()
- {
- while (1)
- {
- Sleep(200);
- if (KeyPress(VK_SPACE))
- {
- break;
- }
- }
- }
-
- //判断下一个坐标是否是食物
- int NextIsFood(pSnakeNode next, pSnake ps)
- {
- if (next->x == ps->_pFood->x && next->y == ps->_pFood->y)
- {
- return 1;
- }
- else
- {
- return 0;
- }
- }
-
- //下一个位置是食物,就吃掉食物
- void EatFood(pSnakeNode next, pSnake ps)
- {
- ps->_pFood->next = ps->_pSnake;
- ps->_pSnake = ps->_pFood;
-
- free(next);
- next = NULL;
-
- pSnakeNode cur = ps->_pSnake;
- while (cur)
- {
- SetPos(cur->x, cur->y);
- wprintf(L"%lc", BODY);
- cur = cur->next;
- }
-
- ps->_score += ps->_food_weight;
-
- CreateFood(ps);
- }
-
- //下一个位置不是食物
- void NoFood(pSnakeNode next, pSnake ps)
- {
- next->next = ps->_pSnake;
- ps->_pSnake = next;
-
- pSnakeNode cur = ps->_pSnake;
- pSnakeNode prev = NULL;
- while (cur->next != NULL)
- {
- prev = cur;
- SetPos(cur->x, cur->y);
- wprintf(L"%lc", BODY);
- cur = cur->next;
- }
-
- SetPos(cur->x, cur->y);
- wprintf(L" ");
-
- if (prev)
- {
- prev->next = NULL;
- }
- free(cur);
- cur = NULL;
- }
-
- //检测蛇是否撞墙
- void KillByWall(pSnake ps)
- {
- if (ps->_pSnake->x <= 1|| ps->_pSnake->x >= 56
- || ps->_pSnake->y <= 0|| ps->_pSnake->y >= 26)
- {
- ps->_status = KILL_BY_WALL;
- }
- }
-
- //检测蛇是否撞到自己
- void KillBySelf(pSnake ps)
- {
- pSnakeNode body = ps->_pSnake->next;
- while (body)
- {
- if (ps->_pSnake->x == body->x && ps->_pSnake->y == body->y)
- {
- ps->_status = KILL_BY_SELF;
- break;
- }
- body = body->next;
- }
- }
-
-
- //蛇的移动-走一步
- void SnakeMove(pSnake ps)
- {
- pSnakeNode next = (pSnakeNode)malloc(sizeof(SnakeNode));
- if (next == NULL)
- {
- perror("CreateFood()::malloc()");
- return;
- }
- next->next = NULL;
- if (ps->_dir == UP)
- {
- next->x = ps->_pSnake->x;
- next->y = ps->_pSnake->y - 1;
- }
- else if (ps->_dir == DOWN)
- {
- next->x = ps->_pSnake->x;
- next->y = ps->_pSnake->y + 1;
- }
- else if (ps->_dir == LEFT)
- {
- next->x = ps->_pSnake->x - 2;
- next->y = ps->_pSnake->y;
- }
- else if (ps->_dir == RIGHT)
- {
- next->x = ps->_pSnake->x + 2;
- next->y = ps->_pSnake->y;
- }
-
-
- if (NextIsFood(next, ps))
- {
- EatFood(next, ps);
- }
- else
- {
- NoFood(next, ps);
- }
-
-
- //检测蛇是否撞墙
- KillByWall(ps);
-
- //检测蛇是否撞到自己
- KillBySelf(ps);
-
- }
-
- //游戏运行的逻辑
- void GameRun(pSnake ps)
- {
- HelpInfor(ps);
-
- do
- {
- SetPos(60, 7);
- printf("得分:%d 每个食物得分:%d", ps->_score, ps->_food_weight);
- if (KeyPress(VK_UP) && ps->_dir != DOWN)
- {
- ps->_dir = UP;
- }
- else if (KeyPress(VK_DOWN) && ps->_dir != UP)
- {
- ps->_dir = DOWN;
- }
- else if (KeyPress(VK_LEFT) && ps->_dir != RIGHT)
- {
- ps->_dir = LEFT;
- }
- else if (KeyPress(VK_RIGHT) && ps->_dir != LEFT)
- {
- ps->_dir = RIGHT;
- }
- else if (KeyPress(VK_SPACE))
- {
- Pause();
- }
- else if (KeyPress(VK_ESCAPE))
- {
- ps->_status = END_NORMAL;
- }
- else if (KeyPress(VK_F3))
- {
- if (ps->_sleep_time > 80)
- {
- ps->_sleep_time -= 30;
- ps->_food_weight += 2;
- }
- }
- else if (KeyPress(VK_F4))
- {
- if (ps->_food_weight > 2)
- {
- ps->_sleep_time += 30;
- ps->_food_weight -= 2;
- }
- }
-
- SnakeMove(ps);
- Sleep(ps->_sleep_time);
-
- } while (ps->_status == OK);
- }
-
-
- //游戏善后的工作
- void GameEnd(pSnake ps)
- {
- SetPos(24, 12);
- switch(ps->_status)
- {
- case KILL_BY_WALL:
- wprintf(L"!!!您撞上墙壁了,游戏结束!!!");
- break;
- case KILL_BY_SELF:
- wprintf(L"!!!您撞上自己了,游戏结束!!!");
- break;
- case END_NORMAL:
- wprintf(L"!!!您主动退出游戏,游戏结束!!!");
- break;
- }
-
- pSnakeNode cur = ps->_pSnake;
- pSnakeNode prev = NULL;
- while (cur)
- {
- prev = cur;
- cur = cur->next;
- free(prev);
- }
- prev = cur = NULL;
- }
- #define _CRT_SECURE_NO_WARNINGS 1
- #include "snake.h"
- //
- void TestSnack()
- {
- //char ch = '\0';
- int ch = 0;
- do {
- system("cls");
-
- Snake snake = { 0 };
- GameStart(&snake);
- GameRun(&snake);
- GameEnd(&snake);
- SetPos(20, 15);
- printf("是否开始新的一局游戏?Y/N:");
- ch = getchar();
- //while (getchar() != '\n');
- while (getchar() != '\n');
- system("cls");
- } while (ch == 'y' || ch == 'Y');
-
- SetPos(5, 26);
- }
- int main()
- {
- setlocale(LC_ALL, "");
- srand((unsigned int)time(NULL));
- TestSnack();
- return 0;
- }