会加速且贪吃的美杜莎女王(C语言代码超详解)

会加速且贪吃的美杜莎女王(C语言代码超详解)本篇会加入个人的所谓 鱼式疯言 鱼式疯言 此疯言非彼疯言 而是理解过并总结出来通俗易懂的大白话 我会尽可能的在每个概念后插入鱼式疯言 帮助大家理解的 可能说的不是那么严谨 但小编初心是能让更多人能接受我们这个概念 前言 亲爱的

大家好,我是讯享网,很高兴认识大家。

本篇会加入个人的所谓‘鱼式疯言’
❤️❤️❤️鱼式疯言:❤️❤️❤️此疯言非彼疯言
而是理解过并总结出来通俗易懂的大白话,
我会尽可能的在每个概念后插入鱼式疯言,帮助大家理解的.
🤭🤭🤭可能说的不是那么严谨.但小编初心是能让更多人能接受我们这个概念 !!

在这里插入图片描述
讯享网

前言

亲爱的,你可能只是玩过普通移动在这里插入图片描述吧,但友子们应该很少见过能加速和减速,能加额外分和减去分值的贪吃蛇小游戏吧!!!
友子们居然点进来来,就别着急走哦,今天小编就详细的讲解我们是怎么用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); } 

贪吃蛇 展示视频

小讯
上一篇 2025-02-22 12:39
下一篇 2025-01-19 22:58

相关推荐

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