本篇会加入个人的所谓‘鱼式疯言’
❤️❤️❤️鱼式疯言:❤️❤️❤️此疯言非彼疯言
而是理解过并总结出来通俗易懂的大白话,
我会尽可能的在每个概念后插入鱼式疯言,帮助大家理解的.
🤭🤭🤭可能说的不是那么严谨.但小编初心是能让更多人能接受我们这个概念 !!
前言
亲爱的,你可能只是玩过普通移动
吧,但友子们应该很少见过能加速和减速,能加额外分和减去分值的贪吃蛇小游戏吧!!!
友子们居然点进来来,就别着急走哦,今天小编就详细的讲解我们是怎么用C语言实现我们想要的贪吃蛇游戏的。💕💕💕
目录
1.贪吃蛇游戏功能介绍 💖 💖 💖
2.游戏环境介绍 🤔 🤔 🤔
3. 游戏设计与分析 (●’◡’●) (●’◡’●) (●’◡’●)
4. 核心逻辑实现分析 (/ω\) (/ω\) (/ω\)
5. 参考代码 😍😍😍
一.贪吃蛇游戏功能介绍
使用C语言在Windows环境的控制台中模拟实现经典小游戏贪吃蛇
基本的功能:
• 贪吃蛇地图绘制
• 蛇吃食物的功能 (上、下、左、右方向键控制蛇的动作)
• 蛇撞墙死亡
• 蛇撞自身死亡
• 计算得分
• 蛇身加速、减速
• 暂停游戏
二.游戏环境介绍
当宝子们要写贪吃蛇游戏时,我们不禁想一个问题,我们要在哪个运行环境来执行我们的代码程序呢 🤔 🤔 🤔
<1>.控制台程序
1.设置控制台窗口的大小和名字,40行,125列
贪吃蛇
//设置控制台大小和标题 system("mode con cols=125 lines=40"); system("title 贪吃蛇小游戏");
讯享网
2.隐藏光标操作
讯享网void TrandCUrsor() //隐藏光标 {
//去除光标 HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE); //得到句手 CONSOLE_CURSOR_INFO CursorInfo; //设置光标结构体变量 GetConsoleCursorInfo(handle, &CursorInfo); //得到光标信息 CursorInfo.bVisible = false; //隐藏光标 SetConsoleCursorInfo(handle, &CursorInfo); //操作光标 }
3.设置控制台屏幕上的坐标COORD
void setpos(int x, int y) //设置光标位置 {
HANDLE handle=GetStdHandle(STD_OUTPUT_HANDLE); //得到句手 COORD pos = {
x,y }; //输入想要的坐标 SetConsoleCursorPosition(handle, pos); //执行所在的坐标 }
4.设置本地化的状态
这时有宝子就要问啦,为啥要设置本地化状态呢💕💕💕
因为我们后期要打印相关的蛇身,蛇身的每个元素就需要迁移到本地来操作,如果还有 疑惑,友友们不用着急哦,小编这就细细到来💖💖💖
这时就需要设置相关的 本地化!!!
讯享网setlocale(LC_ALL, ""); //实现本地化,对应输入空字符
最终效果展示

鱼式疯言
小编想说:小爱同学问的好的,有时候我们的编译器不是控制台程序,那怎么办呢,请听小编 一 一 道来 😎 😎 😎


宝子们按照上面做就可以啦💕💕💕
三 . 游戏设计与分析
这时我们就需要设置三个游戏的步骤
1.游戏开始的准备页面
2.游戏进行的维护页面
3,游戏结束的清理页面

于是我们就有了一下这些
void Test() {
int n = 0; do {
Snoke snoke = {
0 }; //蛇身初始 GameInit(&snoke); //游戏开始 GameContin(&snoke); //游戏过程 GameOver(&snoke); //游戏结束 setpos(15, 14); printf("亲,再来一局么(Y/N):"); n = getchar(); getchar(); //设置是否重来一局 } while (n == 'Y' || n == 'y'); setpos(0, 32); //-退出提示的打印到最后几行 }
四.核心逻辑实现分析
1.游戏开始的准备
<1>.地图和欢迎页面的打印
讯享网void setwelcome() //打印欢迎界面 {
setpos(46, 15); printf("各位王子 ,公主殿下"); setpos(46, 17); printf("欢迎进入贪吃蛇小游戏!"); setpos(49, 30); system("pause"); system("cls"); setpos(40, 15); printf("亲,请按 ↑ ↓ ← → 来控制蛇的移动"); setpos(40, 17); printf("F3为加速,F4为减速"); setpos(40, 19); printf("加速可以得到更高分"); setpos(49, 30); system("pause"); system("cls"); }


void Printmap() //打印地图 {
//上 setpos(0, 0); //先定位第一行第一列 int i = 0; for ( i = 0; i <=56; i+=2) //上方墙两个字符空间为一个宽字符字符 {
wprintf(L"%lc", WALL); //打印墙 } //下 setpos(0, 26); //最后一行即为下 for ( i = 0; i <= 56; i += 2) //下方墙两个字符空间为一个宽字符字符 {
wprintf(L"%lc", WALL); } //左 for ( i = 0; i <=25; i++) {
setpos(0, i); //每次打印就要移动到下一行 wprintf(L"%lc", WALL); } //右 for (i = 0; i <= 25; i++) {
setpos(56, i); wprintf(L"%lc", WALL); } setpos(49, 30); }
<2>.蛇身的打印
讯享网void SnokeInit(pSnoke ps) //蛇身的初始化与打印 {
ps->pFood = ps->pSnoke = NULL; //食物和蛇头置为NULL ps->Sorce = 0; //得分清楚为0 ps->FoodWeight = 10; //食物初始得分10 ps->SleepTime = 200; //休眠时间200 //决定着蛇的初始速度 ps->Dir = RIGHT; //方向向右 ps->status = OK; //状态正常 pSnoke cur = NULL; int i = 0; for (i = 0; i < 5; i++) {
pSnakeNode cat = (pSnakeNode)malloc(sizeof(SnakeNode)); //创建蛇身 if (cat == NULL) //检查是否创建成功 {
perror("SnokeInit()::malloc()"); return; } cat->x = POS_X + 2 * i; //初始的长度一直往右走 cat->y = POS_Y; cat->next=NULL; if (ps->pSnoke == NULL) //蛇头为NULL.就先放蛇头节点 {
ps->pSnoke = cat; } else //放完之后,蛇头下一个节点继续放 {
cat->next = ps->pSnoke; ps->pSnoke = cat; } } pSnakeNode stu = ps->pSnoke; while (stu) //最终打印 {
setpos(stu->x, stu->y); wprintf(L"%lc", BODY); stu = stu->next; } }
<3>.食物打印
void CreatFood(pSnoke ps) //食物的初始化与打印 {
int x = 0; int y = 0; //初始化预定值 again: do {
x = rand() % 53 + 2; y = rand() % 24 + 1; } while (x%2!=0); //跳出的是偶数就是我们想要的值 pSnakeNode stu = ps->pSnoke; //给个头来遍历链表 while (stu) //遍历我们每一个蛇身的坐标 {
if (stu->x == x && stu->y == y) //在遍历蛇身坐标的过程中 //一旦蛇身坐标等于该食物坐标就goto跳回 {
goto again; //跳到上面的do...while循环 } stu = stu->next; } pSnakeNode cur = (pSnakeNode)malloc(sizeof(SnakeNode)); if (cur == NULL) {
perror("CreatFood()::malloc()"); return; } cur->x = x; cur->y = y; ps->pFood = cur; //坐标附上 //食物的节点同时也接上 setpos(cur->x, cur->y); wprintf(L"%lc", FOOD); //给定随机生成的坐标并打印 }

3.打印提示信息
讯享网void printInfo(pSnoke ps) //打印提示信息 {
setpos(70, 15); printf("亲,请按 ↑ ↓ ← → 来控制蛇的移动"); setpos(70, 17); printf("不能穿墙,不能咬到自己"); setpos(70, 19); printf("F3 为加速,F4 为减速"); setpos(70, 21); printf("ESC 为退出,空格 为暂停"); setpos(70, 23); printf("吃鱼专属版本"); setpos(70, 25); printf("有更优化的大佬可以加我wx:zcy 欢迎指点在下"); }

2.游戏进行的维护
#define KEY_PRESS(VK) ((GetAsyncKeyState(VK) & 0x1) ? 1 : 0) //设置感应键
<1>.这样我们就可以分装按键识别的函数
讯享网void Touchboard(pSnoke ps) //按键识别 {
do {
setpos(70, 8); printf("每个食物的分数为:%02d 总分为:%3d", ps->FoodWeight, ps->Sorce); 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_ESCAPE)) //感应ESC键 {
ps->status = ESC; //ESC键赋值 break; //break可有可无 //一旦状态不为OK就会跳出 } else if (KEY_PRESS(VK_SPACE)) //感应空格键 {
pause(); //分装暂停函数 } else if (KEY_PRESS(VK_F3)) //感应F3 {
if (ps->SleepTime >= 80) //最快的休眠时间限制 {
ps->SleepTime -= 30; //时间减30 ps->FoodWeight += 2; //分数加2 } } else if (KEY_PRESS(VK_F4)) {
if (ps->FoodWeight > 2) {
ps->SleepTime += 30; //时间加长 ps->FoodWeight -= 2; //分数减2 } } Sleep(ps->SleepTime); //每次调整蛇的休眠 //休眠时间即蛇的速度 SnakeWalk(ps); //蛇的行走 } while (ps->status == OK); //主要游戏运行过程在这里 //以ps->status 的 OK 状态进行游戏的循环进行 }
<2> .控制蛇的移动
void SnakeWalk(pSnoke ps) //蛇的行走 {
pSnakeNode pNext = (pSnakeNode)malloc(sizeof(SnakeNode)); //创建个预先要前进的节点 if (pNext==NULL) //判断是否创建成功 {
perror("SnakeWalk()::malloc()"); return; } pNext->next = NULL; //先置NULL,判断是否下一个节点是食物 switch (ps->Dir) {
case UP: pNext->x = ps->pSnoke->x; pNext->y = ps->pSnoke->y-1; //向上走,横坐标不变,纵坐标减1 break; case DOWN: pNext->x = ps->pSnoke->x; pNext->y = ps->pSnoke->y + 1; //向下走,横坐标不变,纵坐标加1 break; case LEFT: pNext->x = ps->pSnoke->x - 2; //向左走,横坐标减去一个宽字符的长度.纵坐标不变 pNext->y = ps->pSnoke->y; break; case RIGHT: pNext->x = ps->pSnoke->x + 2; //向右走,横坐标加上一个宽字符的长度.纵坐标不变 pNext->y = ps->pSnoke->y; break; } NextIsFood(ps, pNext); //判断下一个是不是食物 KillByWall(ps); //被墙撞死 KillBySelf(ps); //咬到自己 }
<3>.判断下一个点是否是食物
讯享网void NextIsFood(pSnoke ps,pSnakeNode pNext) //判断下一个是不是食物并打印 {
if (pNext->x == ps->pFood->x && pNext->y == ps->pFood->y) //如果蛇的坐标和食物的坐标重合 //就可以判断蛇吃到了食物 {
pNext->next = ps->pSnoke; //新的节点为蛇头连接蛇身 ps->pSnoke = pNext; pSnakeNode tre = ps->pSnoke; while (tre) //循环打印过程 {
setpos(tre->x, tre->y); wprintf(L"%lc", BODY); tre = tre->next; } ps->Sorce += ps->FoodWeight; //计算上总分 free(ps->pFood); //释放该食物节点 CreatFood(ps); //创建新的食物 } else {
pNext->next = ps->pSnoke; ps->pSnoke = pNext; pSnakeNode tre = ps->pSnoke; //从头开始找.遇到最后一个节点的前一个节点就跳出 while (tre->next->next ) {
setpos(tre->x, tre->y); wprintf(L"%lc", BODY); //一般遍历向下找 // 一边打印身体 tre = tre->next; } setpos(tre->x, tre->y); //遗留下最后一个节点 wprintf(L"%lc", BODY); setpos(tre->next->x, tre->next->y); //最后一个节点打印空格 printf(" "); free(tre->next); //最终要销毁蛇的最后一个节点 tre->next = NULL; //形成移动的过程 } }
鱼式疯言
虽然这里没有游戏页面的展示,但好戏都是压轴哒,友友们耐点心哦
惊喜都在后面
💕💕💕
<4>.空格功能的分装
void pause() //分装空格暂停 {
while (1) //无限循环 {
Sleep(100); //不断休眠 if (KEY_PRESS(VK_SPACE)) //一旦感应到就跳出休眠 break; } }

3.游戏结束的清理
游戏结束有三种情况,有可能撞墙死,有可能咬到自己,或者是自己退出.
<1>.撞墙死亡
讯享网void KillByWall(pSnoke ps) //被墙撞死 {
if (ps->pSnoke->x == 0 || ps->pSnoke->x==56 ||ps->pSnoke->y==0 ||ps->pSnoke->y==26) //一旦头节点越级到墙边就说明撞墙了 {
ps->status = KILL_BY_WALL; //状态改变为撞墙了 } }

<2>.咬到自己死亡
void KillBySelf(pSnoke ps) //咬到自己 {
pSnakeNode stu = ps->pSnoke->next; //先给个头节点的下一个节点 while (stu) //开始遍历 {
if (stu->x == ps->pSnoke->x && stu->y == ps->pSnoke->y) //一但头咬到身体的任何一个部位,就状态跳出 {
ps->status = KILL_BY_SELF; return; } stu = stu->next; } }

<3>. ESC正常退出

<4>. 销毁蛇身和食物节点
讯享网void GameOver(pSnoke ps) //游戏结束 {
setpos(15, 10); //打印游戏怎么结束的提示信息 //这里也可以用 switch 来判断更方便 //枚举常量也是整型开始的 if (ps->status == KILL_BY_SELF) //咬到自己了 {
printf("很遗憾!咬到自己了,游戏结束..."); } else if(ps->status==KILL_BY_WALL) //撞墙了 {
printf("很遗憾!撞墙了,游戏结束..."); } else if (ps->status==ESC) //ESC退出了 {
printf("游戏正在退出中..."); } pSnakeNode str = ps->pSnoke; //头节点 pSnakeNode del = NULL; //双指针 while (str) {
del = str; str = str->next; //先赋值,再释放 free(del); } ps->pSnoke = NULL; free(ps->pFood); //没有结束的食物也要释放掉 ps->pFood = NULL; //食物和蛇身都要置NULL }

五.参考代码
<1>.头文件 snake,h
#pragma once #define _CRT_SECURE_NO_WARNINGS //定义蛇的元素 #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) //设置感应键 #include<stdio.h> #include<stdlib.h> #include<Windows.h> #include<stdbool.h> #include<locale.h> #include<time.h> typedef struct SnakeNode //贪吃蛇节点的定义 {
int x; int y; struct SnakeNode* next; }SnakeNode, *pSnakeNode; enum GAME_STATUS //游戏状态枚举 {
OK=1, //正常运行 ESC, //正常退出 KILL_BY_WALL, //撞墙了 KILL_BY_SELF //咬到自己 }; enum DRECTION //蛇移动的方向 {
UP=1, //上 DOWN, //下 LEFT, //左 RIGHT //右 }; typedef struct Snoke //贪吃蛇 {
pSnakeNode pSnoke; //维护整条蛇的指针 pSnakeNode pFood; //指向食物的指针 int FoodWeight; //每个食物的分数 int Sorce; //总得分 int SleepTime; //蛇的休眠时间即蛇的速度 enum GAME_STATUS status; //游戏状态 enum DRECTION Dir; //蛇的移动 }Snoke ,*pSnoke; void GameInit(); //游戏开始 void TrandCUrsor(); //隐藏光标 void setpos(int x, int y); //设置光标位置 void setwelcome(); //打印欢迎界面 void Printmap(); //打印地图 void SnokeInit(pSnoke ps); //蛇身的初始化与打印 void CreatFood(pSnoke ps); //食物的初始化与打印 void printInfo(pSnoke ps); //打印提示信息 void GameContin(pSnoke ps); //游戏过程 void pause(); //封装空格暂停 void Touchboard(pSnoke ps); //按键识别 void SnakeWalk(pSnoke ps); //蛇的行走 void NextIsFood(pSnoke ps); //判断下一个是不是食物 void KillByWall(pSnoke ps); //被墙撞死 void KillBySelf(pSnoke ps); //咬到自己 void GameOver(pSnoke ps); //游戏结束
<2>.逻辑文件 test.c
讯享网#include "snake.h" void Test() {
int n = 0; do {
Snoke snoke = {
0 }; //蛇身初始 GameInit(&snoke); //游戏开始 GameContin(&snoke); //游戏过程 GameOver(&snoke); //游戏结束 setpos(15, 14); printf("亲,再来一局么(Y/N):"); n = getchar(); getchar(); //设置是否重来一局 } while (n == 'Y' || n == 'y'); setpos(0, 32); //-退出提示的打印到最后几行 } int main() {
srand((unsigned)time(NULL)); //设置随机数种子 setlocale(LC_ALL, ""); //实现本地化,可以输出空字符 Test(); return 0; }
<3>,游戏文件 snake.c
#include "snake.h" void GameInit(pSnoke ps) //设置初始页面 {
//设置控制台大小和标题 system("mode con cols=125 lines=40"); system("title 贪吃蛇小游戏"); TrandCUrsor(); //隐藏光标 setwelcome(); //打印欢迎界面 Printmap(); //打印地图 SnokeInit(ps); //蛇的初始化 CreatFood(ps); //食物的初始化和打印 printInfo(ps); //打印提示信息 } void GameContin(pSnoke ps) {
Touchboard(ps); //按键识别以及蛇的行走过程 } void GameOver(pSnoke ps) //游戏结束 {
setpos(15, 10); //打印游戏怎么结束的提示信息 //这里也可以用 switch 来判断更方便 //枚举常量也是整型开始的 if (ps->status == KILL_BY_SELF) //咬到自己了 {
printf("很遗憾!咬到自己了,游戏结束..."); } else if(ps->status==KILL_BY_WALL) //撞墙了 {
printf("很遗憾!撞墙了,游戏结束..."); } else if (ps->status==ESC) //ESC退出了 {
printf("游戏正在退出中..."); } pSnakeNode str = ps->pSnoke; //头节点 pSnakeNode del = NULL; //双指针 while (str) {
del = str; str = str->next; //先赋值,再释放 free(del); } ps->pSnoke = NULL; free(ps->pFood); //没有结束的食物也要释放掉 ps->pFood = NULL; //食物和蛇身都要置NULL } void SnakeWalk(pSnoke ps) //蛇的行走 {
pSnakeNode pNext = (pSnakeNode)malloc(sizeof(SnakeNode)); //创建个预先要前进的节点 if (pNext==NULL) //判断是否创建成功 {
perror("SnakeWalk()::malloc()"); return; } pNext->next = NULL; //先置NULL,判断是否下一个节点是食物 switch (ps->Dir) {
case UP: pNext->x = ps->pSnoke->x; pNext->y = ps->pSnoke->y-1; //向上走,横坐标不变,纵坐标减1 break; case DOWN: pNext->x = ps->pSnoke->x; pNext->y = ps->pSnoke->y + 1; //向下走,横坐标不变,纵坐标加1 break; case LEFT: pNext->x = ps->pSnoke->x - 2; //向左走,横坐标减去一个宽字符的长度.纵坐标不变 pNext->y = ps->pSnoke->y; break; case RIGHT: pNext->x = ps->pSnoke->x + 2; //向右走,横坐标加上一个宽字符的长度.纵坐标不变 pNext->y = ps->pSnoke->y; break; } NextIsFood(ps, pNext); //判断下一个是不是食物 KillByWall(ps); //被墙撞死 KillBySelf(ps); //咬到自己 } void KillByWall(pSnoke ps) //被墙撞死 {
if (ps->pSnoke->x == 0 || ps->pSnoke->x==56 ||ps->pSnoke->y==0 ||ps->pSnoke->y==26) //一旦头节点越级到墙边就说明撞墙了 {
ps->status = KILL_BY_WALL; //状态改变为撞墙了 } } void KillBySelf(pSnoke ps) //咬到自己 {
pSnakeNode stu = ps->pSnoke->next; //先给个头节点的下一个节点 while (stu) //开始遍历 {
if (stu->x == ps->pSnoke->x && stu->y == ps->pSnoke->y) //一但头咬到身体的任何一个部位,就状态跳出 {
ps->status = KILL_BY_SELF; return; } stu = stu->next; } } void NextIsFood(pSnoke ps,pSnakeNode pNext) //判断下一个是不是食物并打印 {
if (pNext->x == ps->pFood->x && pNext->y == ps->pFood->y) //如果蛇的坐标和食物的坐标重合 //就可以判断蛇吃到了食物 {
pNext->next = ps->pSnoke; //新的节点为蛇头连接蛇身 ps->pSnoke = pNext; pSnakeNode tre = ps->pSnoke; while (tre) //循环打印过程 {
setpos(tre->x, tre->y); wprintf(L"%lc", BODY); tre = tre->next; } ps->Sorce += ps->FoodWeight; //计算上总分 free(ps->pFood); //释放该食物节点 CreatFood(ps); //创建新的食物 } else {
pNext->next = ps->pSnoke; ps->pSnoke = pNext; pSnakeNode tre = ps->pSnoke; //从头开始找.遇到最后一个节点的前一个节点就跳出 while (tre->next->next ) {
setpos(tre->x, tre->y); wprintf(L"%lc", BODY); //一般遍历向下找 // 一边打印身体 tre = tre->next; } setpos(tre->x, tre->y); //遗留下最后一个节点 wprintf(L"%lc", BODY); setpos(tre->next->x, tre->next->y); //最后一个节点打印空格 printf(" "); free(tre->next); //最终要销毁蛇的最后一个节点 tre->next = NULL; //形成移动的过程 } } void Touchboard(pSnoke ps) //按键识别 {
do {
setpos(70, 8); printf("每个食物的分数为:%02d 总分为:%3d", ps->FoodWeight, ps->Sorce); 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_ESCAPE)) //感应ESC键 {
ps->status = ESC; //ESC键赋值 break; //break可有可无 //一旦状态不为OK就会跳出 } else if (KEY_PRESS(VK_SPACE)) //感应空格键 {
pause(); //分装暂停函数 } else if (KEY_PRESS(VK_F3)) //感应F3 {
if (ps->SleepTime >= 80) //最快的休眠时间限制 {
ps->SleepTime -= 30; //时间减30 ps->FoodWeight += 2; //分数加2 } } else if (KEY_PRESS(VK_F4)) {
if (ps->FoodWeight > 2) {
ps->SleepTime += 30; //时间加长 ps->FoodWeight -= 2; //分数减2 } } Sleep(ps->SleepTime); //每次调整蛇的休眠 //休眠时间即蛇的速度 SnakeWalk(ps); //蛇的行走 } while (ps->status == OK); //主要游戏运行过程在这里 //以ps->status 的 OK 状态进行游戏的循环进行 } void pause() //分装空格暂停 {
while (1) //无限循环 {
Sleep(100); //不断休眠 if (KEY_PRESS(VK_SPACE)) //一旦感应到就跳出休眠 break; } } void printInfo(pSnoke ps) //打印提示信息 {
setpos(70, 15); printf("亲,请按 ↑ ↓ ← → 来控制蛇的移动"); setpos(70, 17); printf("不能穿墙,不能咬到自己"); setpos(70, 19); printf("F3 为加速,F4 为减速"); setpos(70, 21); printf("ESC 为退出,空格 为暂停"); setpos(70, 23); printf("吃鱼专属版本"); setpos(70, 25); printf("有更优化的大佬可以加我wx:zcy 欢迎指点在下"); } void SnokeInit(pSnoke ps) //蛇身的初始化与打印 {
ps->pFood = ps->pSnoke = NULL; //食物和蛇头置为NULL ps->Sorce = 0; //得分清楚为0 ps->FoodWeight = 10; //食物初始得分10 ps->SleepTime = 200; //休眠时间200 //决定着蛇的初始速度 ps->Dir = RIGHT; //方向向右 ps->status = OK; //状态正常 pSnoke cur = NULL; int i = 0; for (i = 0; i < 5; i++) {
pSnakeNode cat = (pSnakeNode)malloc(sizeof(SnakeNode)); //创建蛇身 if (cat == NULL) //检查是否创建成功 {
perror("SnokeInit()::malloc()"); return; } cat->x = POS_X + 2 * i; //初始的长度一直往右走 cat->y = POS_Y; cat->next=NULL; if (ps->pSnoke == NULL) //蛇头为NULL.就先放蛇头节点 {
ps->pSnoke = cat; } else //放完之后,蛇头下一个节点继续放 {
cat->next = ps->pSnoke; ps->pSnoke = cat; } } pSnakeNode stu = ps->pSnoke; while (stu) //最终打印 {
setpos(stu->x, stu->y); wprintf(L"%lc", BODY); stu = stu->next; } } void CreatFood(pSnoke ps) //食物的初始化与打印 {
int x = 0; int y = 0; //初始化预定值 again: do {
x = rand() % 53 + 2; y = rand() % 24 + 1; } while (x%2!=0); //跳出的是偶数就是我们想要的值 pSnakeNode stu = ps->pSnoke; //给个头来遍历链表 while (stu) //遍历我们每一个蛇身的坐标 {
if (stu->x == x && stu->y == y) //在遍历蛇身坐标的过程中 //一旦蛇身坐标等于该食物坐标就goto跳回 {
goto again; //跳到上面的do...while循环 } stu = stu->next; } pSnakeNode cur = (pSnakeNode)malloc(sizeof(SnakeNode)); if (cur == NULL) {
perror("CreatFood()::malloc()"); return; } cur->x = x; cur->y = y; ps->pFood = cur; //坐标附上 //食物的节点同时也接上 setpos(cur->x, cur->y); wprintf(L"%lc", FOOD); //给定随机生成的坐标并打印 } void setpos(int x, int y) //设置光标位置 {
HANDLE handle=GetStdHandle(STD_OUTPUT_HANDLE); //得到句手 COORD pos = {
x,y }; //输入想要的坐标 SetConsoleCursorPosition(handle, pos); //执行所在的坐标 } void TrandCUrsor() //隐藏光标 {
//去除光标 HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE); //得到句手 CONSOLE_CURSOR_INFO CursorInfo; //设置光标结构体变量 GetConsoleCursorInfo(handle, &CursorInfo); //得到光标信息 CursorInfo.bVisible = false; //隐藏光标 SetConsoleCursorInfo(handle, &CursorInfo); //操作光标 } void setwelcome() //打印欢迎界面 {
setpos(46, 15); printf("各位王子 ,公主殿下"); setpos(46, 17); printf("欢迎进入贪吃蛇小游戏!"); setpos(49, 30); system("pause"); system("cls"); setpos(40, 15); printf("亲,请按 ↑ ↓ ← → 来控制蛇的移动"); setpos(40, 17); printf("F3为加速,F4为减速"); setpos(40, 19); printf("加速可以得到更高分"); setpos(49, 30); system("pause"); system("cls"); } void Printmap() //打印地图 {
//上 setpos(0, 0); //先定位第一行第一列 int i = 0; for ( i = 0; i <=56; i+=2) //上方墙两个字符空间为一个宽字符字符 {
wprintf(L"%lc", WALL); //打印墙 } //下 setpos(0, 26); //最后一行即为下 for ( i = 0; i <= 56; i += 2) //下方墙两个字符空间为一个宽字符字符 {
wprintf(L"%lc", WALL); } //左 for ( i = 0; i <=25; i++) {
setpos(0, i); //每次打印就要移动到下一行 wprintf(L"%lc", WALL); } //右 for (i = 0; i <= 25; i++) {
setpos(56, i); wprintf(L"%lc", WALL); } setpos(49, 30); }
贪吃蛇 展示视频


版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/48165.html