赞
踩
C语言实现贪吃蛇游戏
蛇的方向和游戏的状态采用枚举列举。
// 蛇的方向 enum DIRECTION { UP = 1, DOWN, LEFT, RIGHT }; // 游戏的状态(正常、撞墙、撞到自己、正常退出) enum GAME_STATUS { ok,//正常状态 KILL_BY_WALL,// 撞墙死 KILL_BY_SELF,// 撞到自己死 END_NORMAL // esc正常退出 }; // 创建蛇身的节点 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 test() { int ch = 0; do { system("cls"); // 创建贪吃蛇 Snake snake = { 0 }; // 初始化游戏 // 1. 打印欢迎界面 // 2. 打印功能介绍 // 3. 绘制地图 // 4. 创建蛇 // 5. 创建食物 // 6. 设置游戏的相关信息 GameStart(&snake); // 游戏运行 GameRun(&snake); // 游戏结束--- 游戏的善后工作 GameEnd(&snake); SetPos(25, 18); printf("要再来一局吗?(Y/N)"); ch = getchar(); while (getchar() != '\n'); } while (ch == 'Y' || ch == 'y'); SetPos(0, 27); }
void SetPos(short x, short y) { // 获得标准输出设备的句柄 HANDLE houtput = NULL; houtput = GetStdHandle(STD_OUTPUT_HANDLE); //定位光标的位置 COORD pos = { x, y }; SetConsoleCursorPosition(houtput, pos); } // 1-2.欢迎界面的打印及功能介绍函数 void WelcomeToGame() { SetPos(40, 14); wprintf(L"欢迎来到贪吃蛇小游戏!!\n"); SetPos(42, 25); system("pause"); system("cls"); SetPos(30, 14); wprintf(L"按↑. ↓. ←. →来控制蛇的方向,按F3加速,F4减速"); SetPos(40, 16); wprintf(L"加速可以得到跟高的分数"); SetPos(42, 25); system("pause"); system("cls"); } // 3. 打印地图 void CreateMap() { // 上 int i = 0; for (i = 0; i < 29; i++) { wprintf(L"%lc", WALL); } // 下 SetPos(0, 26); for (i = 0; i < 29; i++) { wprintf(L"%lc", WALL); } // 左 for (i = 1; i <= 25; i++) { SetPos(0, i); wprintf(L"%lc", WALL); } // 右 for (i = 1; i <= 25; i++) { SetPos(56, i); wprintf(L"%lc", WALL); } } // 4. 创建蛇 void InitSnake(pSnake ps) { pSnakeNode cur = NULL; int i = 0; for (i = 0; i < 5; i++) { // 申请一个蛇身节点 cur = (pSnakeNode)malloc(sizeof(SnakeNode)); if (NULL == cur) { perror("InitSnake()::malloc()"); return; } cur->next = NULL; cur->x = POS_X + 2 * i; cur->y = POS_Y; // 头插法插入链表 if (ps->_pSnake == NULL) // 空链表 { ps->_pSnake = cur; } else // 非空链表 { cur->next = ps->_pSnake; ps->_pSnake = cur; } } // 打印蛇身 cur = ps->_pSnake; SetPos(cur->x, cur->y); wprintf(L"%lc", HEAD); cur = cur->next; while (cur) { SetPos(cur->x, cur->y); wprintf(L"%lc", BODY); cur = cur->next; } // 设置贪吃蛇属性 ps->_dir = RIGHT; // 初始方向设置为向右 ps->_score = 0; // 总成绩初始为0 ps->_food_weight = 10;// 一个食物10分 ps->_sleep_time = 200; // 休眠时间,单位为毫秒 ps->_status = ok; // 默认游戏状态ok } // 5. 创建食物函数 void CreateFood(pSnake ps) { int x = 0; int y = 0; again: // 随机生成食物位置,不能在墙体上 do { x = rand() % 53 + 2; y = rand() % 25 + 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 = malloc(sizeof(SnakeNode)); if (pFood == NULL) { perror("CreateFood()::malloc()"); return; } pFood->next = NULL; pFood->x = x; pFood->y = y; // 定位位置打印食物 SetPos(pFood->x, pFood->y); wprintf(L"%lc", FOOD); ps->_pFood = pFood; } // 初始化游戏 void GameStart(pSnake ps) { // 0. 先设置窗口大小再光标隐藏 //设置窗口大小 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);// 设置控制台光标信息 // 1. 打印欢迎界面 // 2. 打印功能介绍 WelcomeToGame(); // 3. 绘制地图 CreateMap(); // 4. 创建蛇 InitSnake(ps); // 5. 创建食物 CreateFood(ps); }
// 打印帮助信息函数 void PrintHelpInfo() { SetPos(64, 17); wprintf(L"不能穿墙,不能咬到自己"); SetPos(64, 18); wprintf(L"按↑. ↓. ←. →来控制蛇的方向"); SetPos(64, 19); wprintf(L"+ 为加速,- 为减速"); SetPos(64, 20); wprintf(L"ESC: 退出游戏!SPACE: 暂停游戏"); SetPos(64, 22); wprintf(L"hhb@版权"); } // 检测按键的宏 #define KEY_PRESS(vk) ((GetAsyncKeyState(vk) & 1)? 1 : 0) // 暂停函数 void Pause() { while (1) { Sleep(200); if (KEY_PRESS(VK_SPACE)) { break; } } } // 判断下一个节点是否为食物 int NextIsFood(pSnakeNode pn, pSnake ps) { return (pn->x == ps->_pFood->x && pn->y == ps->_pFood->y); } // 吃掉食物函数 void EatFood(pSnakeNode pn, pSnake ps) { // 将食物节点头插到蛇头之前 ps->_pFood->next = ps->_pSnake; ps->_pSnake = ps->_pFood; // 释放next节点 free(pn); pn = NULL; // 打印蛇身 pSnakeNode cur = ps->_pSnake; SetPos(cur->x, cur->y); wprintf(L"%lc", HEAD); cur = cur->next; while (cur) { SetPos(cur->x, cur->y); wprintf(L"%lc", BODY); cur = cur->next; } ps->_score += ps->_food_weight; // 吃掉食物,再创建一个新的事物 CreateFood(ps); } // 没有食物 void NoFood(pSnakeNode pn, pSnake ps) { // 新的节点头插到链表中 pn->next = ps->_pSnake; ps->_pSnake = pn; // 打印蛇 pSnakeNode cur = ps->_pSnake; SetPos(cur->x, cur->y); wprintf(L"%lc", HEAD); cur = cur->next; while (cur->next->next != NULL) { 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; break; } cur = cur->next; } } // 蛇向前走一步函数 void SnakeMove(pSnake ps) { // 创建下一个位置的节点 pSnakeNode pNextNode = (pSnakeNode)malloc(sizeof(SnakeNode)); if (pNextNode == NULL) { perror("SnakeMove()::malloc()"); return; } // 确定下一节点的位置 switch (ps->_dir) { case UP: pNextNode->x = ps->_pSnake->x; pNextNode->y = ps->_pSnake->y - 1; break; case DOWN: pNextNode->x = ps->_pSnake->x; pNextNode->y = ps->_pSnake->y + 1; break; case LEFT: pNextNode->x = ps->_pSnake->x - 2; pNextNode->y = ps->_pSnake->y; break; case RIGHT: pNextNode->x = ps->_pSnake->x + 2; pNextNode->y = ps->_pSnake->y; break; } // 需要判断下一点是否是食物 if (NextIsFood(pNextNode, ps)) { EatFood(pNextNode, ps); } else { NoFood(pNextNode, ps); } // 检测蛇是否撞到墙 KillByWall(ps); // 检测蛇是否撞到自己 KillBySelf(ps); } // 游戏运行 void GameRun(pSnake ps) { // 打印帮助信息 PrintHelpInfo(); do { // 打印总得分和食物权重 SetPos(64, 10); wprintf(L"总得分为: %d", ps->_score); SetPos(64, 12); wprintf(L"当前食物的分数为: %2d", ps->_food_weight); // 检测按键 if (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_SPACE)) { // 暂停 Pause(); } else if (KEY_PRESS(VK_ESCAPE)) { // 正常退出 ps->_status = END_NORMAL; } else if (KEY_PRESS(VK_ADD)) { // 加速 if (ps->_sleep_time > 80) { ps->_sleep_time -= 30; ps->_food_weight += 2; } } else if (KEY_PRESS(VK_SUBTRACT)) { // 减速 if (ps->_food_weight >2 ) { ps->_sleep_time += 30; ps->_food_weight -= 2; } } // 蛇向前走走一步 SnakeMove(ps); // 蛇每走一步sleep一下 Sleep(ps->_sleep_time); } while (ps->_status == ok); }
// 游戏结束--游戏善后工作 void GameEnd(pSnake ps) { SetPos(24, 12); switch (ps->_status) { case END_NORMAL: wprintf(L"您正常退出了!!\n"); break; case KILL_BY_WALL: wprintf(L"您撞到墙上了,游戏结束!!\n"); break; case KILL_BY_SELF: wprintf(L"您撞到自己了,游戏结束!!\n"); break; } // 销毁链表 pSnakeNode cur = ps->_pSnake; while (cur) { pSnakeNode del = cur; cur = cur->next; free(del); } }
C语言实现贪吃蛇游戏
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。