C语言项目实战(一)

好久没写博客了,今天来水一点东西(bushi)
这段时间一直在写C语言这学期的课程设计(选的是游戏类的贪吃蛇游戏),今天就来写个博客来教下大概怎么写吧

  • 注意:1.此篇文章仅供参考代码以及学习技术,禁止在违法开源协议(选用的是最宽松的开源协议)/照搬代码/看不懂代码就直接写/直接挪用代码作为课程设计等上述行为
    2.目前项目仍然存在一些问题,以实际情况为准 *

清屏函数

void clearScreen()
{
    HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
    COORD coordScreen = {0, 0};
    DWORD cCharsWritten;
    CONSOLE_SCREEN_BUFFER_INFO csbi;
    DWORD dwConSize;

    // 获取控制台缓冲区信息
    GetConsoleScreenBufferInfo(hConsole, &csbi);
    dwConSize = csbi.dwSize.X * csbi.dwSize.Y;

    // 用空格填充整个缓冲区
    FillConsoleOutputCharacter(hConsole, ' ', dwConSize, coordScreen, &cCharsWritten);

    // 获取当前文本属性
    GetConsoleScreenBufferInfo(hConsole, &csbi);

    // 用当前文本属性填充整个缓冲区
    FillConsoleOutputAttribute(hConsole, csbi.wAttributes, dwConSize, coordScreen, &cCharsWritten);

    // 将光标位置设置到左上角
    SetConsoleCursorPosition(hConsole, coordScreen);
}

本身我们可以使用system(“cls”)函数来清屏,但是经过实际测试,效果并不好,同时在某些特定的情况下会出现一些问题,所以我查找资料使用了这个方法直接调用WindowsAPI来进行清屏,同时在后续需要的时候直接使用clearScreen()即可

主菜单构建

在长达十秒钟的思维风暴后,我构建出主菜单的几个主要功能

printf("=================================n");
printf("欢迎来到贪吃蛇游戏!n");
printf("请选择你要进行的操作:n");
printf("0.加载游戏n");
printf("1.开始游戏n");
printf("2.查看分数n");
printf("3.关于我们n");
printf("4.游戏规则n");
printf("5.退出系统n");
printf("=================================n");
printf("请输入要进行的序号(0-5):");

同时,为了持续检测用户的输入值,我们再使用while循环来检测用户输入的序号

fflush(stdin);
    char choice = getchar();
    // 忽略换行符
    if (choice == 'n')
    {
        continue;
    }
    switch (choice)
    {
    case '1':
        clearScreen();
        start();
        break;
    case '2':
        query();
        break;
    case '3':
        about();
        break;
    case '4':
        printf("n==============游戏规则===============:n");
        printf("1.移动:使用方向键(W上,S下,A左,D右)控制蛇的移动方向。n");
        printf("2.吃食物(#):吃食物可以增加蛇的长度。n");
        printf("3.陷阱(X):碰撞陷阱将会导致游戏失败。n");
        printf("4.碰撞墙壁将会导致游戏失败。n");
        printf("5.游戏中按住q将保存游戏数据并退出n");
        printf("注意:为了保证游戏公平,每轮游戏最多仅允许暂停一次,否则判断失败!!!n");
        printf("祝你玩得开心!n");
        printf("按任意键继续...");
        _getch();
        clearScreen();
        main();
        break;
    case '5':
        exit(0);
        break;
    case '0':
        load();
        break;
    default:
        printf("输入错误!请重新输入:");
    }

但是在这里,我们调用了一个新的函数fflush(stdin);
查询资料之后,这个函数的只要功能是清除输入缓冲区的残留的内容,因为我们使用的是持续读取,再我们获得操作指令之后可能仍然存在内容,为了保证执行正常,我们使用此函数来清除输入缓冲区

初始化

在开始游戏之前,我们需要进行一些初始化,比如初始化蛇的位置,初始化食物的位置,初始化蛇的长度,初始化蛇的方向等等
注意:在这里我们只进行初始化而不进行处理!!!

初始化蛇

在这里,我们采用结构体的方式来村塾蛇的位置

struct body {
    int x, y;//蛇的坐标
};

什么?你问我为什么只有一个结构体,而且结构体里面只有一个x,y?
在这里,我们记录的是蛇头的坐标,舍得身体必定会经过蛇头所经过的坐标,所以这里我们记录蛇头坐标,蛇身坐标可以通过蛇头坐标和蛇的身体推算出来,所以我们会有一个定义蛇身体的函数

struct snake {
    int size;//蛇的长度
    struct body body[wide * high];//嵌套蛇的身子
}snake;

(不要在意结构体的名字,我在写的时候也没想到名字怎么变这么奇怪了)

初始化食物

在这里我们采用容量为2的数组来存储食物的位置(一个空间存x,一个存y)

int food[2] = { 0 };//food[0]为x坐标,food[1]为y坐标

初始化陷阱

陷阱的初始化与食物一样,但是我们的关卡难度会持续上升,陷阱的数量会随着关卡数量而增加
陷阱数量的问题我们在主函数中解决,在这里,我们只初始化而不进行处理

//初始化陷阱
typedef struct trap {
    int x, y;
} trap;
//陷阱数量
int trapNum = 0;
//全局陷阱数组
trap traps[wide * high];

其他初始化

在头文件中应该没有初始化了,剩下的如果有应该在main函数中,随后我们声明了我们要在.c中要调用的函数以及一些变量

//函数声明部分
void initFood();//初始化食物
void initSnake();//初始化蛇 
void showUI();//显示界面
void playGame();//开始游戏
void start();//在选择菜单为开始游戏引导代码声明
int score = 0;
//偏移坐标
int dx = 0;
int dy = 0;
void initWall();//初始化墙
//记录尾巴坐标
int lx = 0;
int ly = 0;
void initTrap(int score);

void save();
void load();

开始游戏

我们直接使用在main中的switch语句钓友我们的start函数
首先,这里要介绍一篇文章https://docs.pingcode.com/baike/1162036
这篇文章使用了WindowsAPI以隐藏光标来获得更好的视觉体验
具体代码如下

//隐藏光标获取良好体验https://docs.pingcode.com/baike/1162036
    CONSOLE_CURSOR_INFO cci;  // 声明cci结构体
    cci.dwSize = sizeof(cci); // 设置大小
    cci.bVisible = FALSE;     // 隐藏光标
    SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cci);

但在使用之前我们应该清一下屏,然后由于我们时开始一轮新的游戏,会有说一句游戏缓存,我们也要同步清理

    clearScreen();
    score = 0; // 防止上一轮分数未归零
    SetConsoleOutputCP(65001); // 设置控制台为UTF-8编码,解决中文乱码
    srand(time(NULL));         // 设置随机种子

随后我们要调用我们上一步的初始化函数来构造游戏界面

// 调用函数部分
    initFood();  // 调用食物
    initSnake(); // 调用蛇
    //showUI();//显示界面
    initWall(); // 调用墙
    playGame(); // 开始玩游戏

但是,值得注意的是,游戏结束后依旧会有scanner在,此处清除键盘缓存区的内容

int c;
    while ((c = getchar()) != 'n' && c != EOF)//目标时换行
    {
        // 读取并丢弃字符
    }

总结(一)

综上便是第一部分的内容
完整代码暂不直接提供,但是源代码已经在github开源,可以参考一下
感谢支持!

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇
皖ICP备2025092305号-1