大家好,欢迎来到IT知识分享网。
本篇仅提供C语言代码,详细讲解在这篇博客:C语言:贪吃蛇游戏(从0开始完整版)-CSDN博客
1、运行演示
–
2、代码构成(VS编译器)
3、C语言代码
3.1 头文件Snake.h
#pragma once #include <locale.h> #include <windows.h> #include <stdbool.h> #include <stdlib.h> #include <stdio.h> #include <time.h> #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);
3.2 Snake.c(游戏相关代码)
#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 <errno.h> //初始化蛇身 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; }
3.3 test.c(运行相关代码)
#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; }
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/120698.html
