当前位置: 首页 > news >正文

C语言贪吃蛇项目——第二部分绘制菜单和初始界面

1.了解Windows下的终端控制头文件及其API

1.1#include <windows.h>

我们需要了解该头文件其中的
        1.HANDLE检索指定标准设备的句柄,知道怎么标准输出设备;
        2.结构体COORD来设置光标;
        3.了解SetConsoleCursorPosition()函数怎么使用

          利用上面的内容自行设定gotoxy()函数

void gotoxy(int x,int y)
{
    HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
    COORD pos = {
    .X = x,
    .Y = y};
    SetConsoleCursorPosition(handle,pos);
}

1.2.#include <conio.h>

我们需要了解该头文件其中的

        1.kbhit()函数,作用是判断键盘是否有输入,有输入返回1,否则返回0

        2.getch()函数,作用是获取输入的键值,不需要回车

        3.getchar()函数,作用是获取输入的键值,需要回车

        4.gotoxy()函数,在当代编译器中不可用,需要自行实现(在上面)

2.绘制游戏欢迎界面

2.1绘制边界

        首先,我们先来绘制游戏中的边界,就是该墙体,它用于确定游戏的边界限制。主要是运用for()函数嵌套循环和putchar()函数输出。最后输出一个30*20的边界。

void draw_wall(void)
{
    gotoxy(0,0);
    for(int y=0;y<=HEIGHT;y++)
    {
        for(int x=0;x<=WIDTH;x++)
        {
            if(x==0||x==WIDTH)
                putchar('*');
            else if(y==0||y==HEIGHT)
                putchar('*');
            else
                putchar(' ');
        }
        puts("");
    }
}

2.2绘制开始游戏和结束游戏的图标

        接下来,我们先来定义char start_game[]和char exit_game[]的数组,并找到在游戏中间的位置,在该位置设立开始游戏和结束游戏的光标,通过puts()函数输出开始游戏和结束游戏的图标。

        这段代码定义了两字符串常量 start_game 和 exit_game 分别存储了 "START GAME" 和 "EXIT GAME" 字符串。另外,还定义了两个 COORD 结构体类型的变量 start_pos 和 exit_pos,分别表示开始游戏选项和退出游戏选项在屏幕中的位置。

        函数 draw_menu 负责在屏幕上绘制菜单,通过调用 gotoxy 函数将光标移动到 start_pos 和 exit_pos 所表示的位置,然后使用 puts 将对应的字符串输出到屏幕上,最终展示了开始游戏选项和退出游戏选项。

const char start_game[] = "START GAME";
const char exit_game[] = "EXIT GAME";

COORD start_pos = {
    .X = WIDTH/2 - strlen(start_game)/2,
    .Y = HEIGHT/2
};

COORD exit_pos = {
    .X = WIDTH/2 - strlen(exit_game)/2,
    .Y = HEIGHT/2 + 2
};

void draw_menu(void)
{
    gotoxy(start_pos.X,start_pos.Y);
    puts(start_game);
    gotoxy(exit_pos.X,exit_pos.Y);
    puts(exit_game);
}

2.3键盘控制函数

        通过这样的方式,用户可以在控制台中看到可视化的提示,并通过按键来控制游戏的开始和结束。这是一个简单但有效的方法来增强用户体验。

具体功能如下:

  1. 函数名为get_key,返回一个整型值。
  2. 使用kbhit()函数来检测是否有按键按下,若有键按下则返回非零值。
  3. 使用getch()函数来获取用户按下的键值。
  4. 如果获取的键值为224,则表示键值为特殊键,需要再次调用getch()获取具体的特殊键值。
  5. 根据用户按下的键值,将其转换为相应的操作指令:
    • 'w'/'W'/72:表示向上移动操作,返回1。
    • 's'/'S'/80:表示向下移动操作,返回2。
    • 'a'/'A'/75:表示向左移动操作,返回3。
    • 'd'/'D'/77:表示向右移动操作,返回4。
    • 13:表示中心操作,返回5。
int get_key(void)
{
    int kb = kbhit();
    if(kb == 0)
        return 0;
    int key = getch();
    if(key == 224)
        key = getch();
    if(key == 'w' || key == 'W' || key == 72)  //Turn up
        return 1;
    else if(key == 's' || key == 'S' || key == 80)  //Turn down
        return 2;
    else if(key == 'a' || key == 'A' || key == 75)  //Turn left
        return 3;
    else if(key == 'd' || key == 'D' || key == 77)  //Turn right
        return 4;
    else if(key == 13)  //Center
        return 5;
}

2.4方向键选择菜单

        本函数是为了能够上下选择进入游戏或者离开游戏

        这段代码实现了一个简单的菜单选择功能。首先定义了一个函数select_menu(),该函数没有参数,返回一个整型值。在函数中,通过COORD结构体定义了菜单项的起始位置start_pos和退出位置exit_pos,然后通过gotoxy函数将光标移动到起始位置,并输出一个'O'表示当前选择的菜单项。

        接着进入一个无限循环,不断监听键盘输入。在每次循环中,通过get_key()函数获取键盘输入的键值。如果输入的是上下方向键(Up或Down),则根据当前选择的菜单项位置进行切换:如果当前在起始位置,则切换到退出位置,反之亦然。

如果按下确认键(Center),则根据当前选择的菜单项位置判断返回值:如果在起始位置则返回1,表示选择了菜单项1;如果在退出位置则返回0,表示选择了退出。

        总之,这段代码实现了一个简单的菜单选择功能,允许用户通过上下方向键选择菜单项,通过确认键确定选择的菜单项,并返回相应的整数值。

int select_menu(void)
{
    COORD menu_int_pos = start_pos;
    gotoxy(start_pos.X - 2,start_pos.Y);
    putchar('O');
    while (1)
    {
        int key = get_key();
        if(key == Up || key == Down)
        {
            if(menu_int_pos.X == start_pos.X && menu_int_pos.Y == start_pos.Y)
            {
                gotoxy(start_pos.X - 2,start_pos.Y);
                putchar(' ');
                gotoxy(exit_pos.X-2,exit_pos.Y);
                putchar('O');
                menu_int_pos = exit_pos;
            }
            else if(menu_int_pos.X == exit_pos.X && menu_int_pos.Y == exit_pos.Y)
            {
                gotoxy(exit_pos.X - 2,exit_pos.Y);
                putchar(' ');
                gotoxy(start_pos.X-2,start_pos.Y);
                putchar('O');
                menu_int_pos = start_pos;
            }
        }
        if(key == Center)
        {
            gotoxy(0,HEIGHT+2);
            if(menu_int_pos.X == start_pos.X && menu_int_pos.Y == start_pos.Y)
            {
                return 1;
            }
            else if(menu_int_pos.X == exit_pos.X && menu_int_pos.Y == exit_pos.Y)
            {
                return 0;
            }
        }

    }
}


int main()
{
    draw_wall();
    draw_menu();

    int menu = select_menu();
    if(menu == 0)   return 0;

    return 0;
}

3.绘制蛇身和随机刷新食物

3.1绘制游戏开始的最初蛇身

        这段代码定义了一个静态的 COORD 类型的数组 snake,长度为 1024,用来存储蛇身体的各个部分的坐标。同时还定义了一个静态的整型变量 snake_body_length,表示蛇的身体长度。

        函数 draw_int_snake 负责初始化蛇的初始位置和外观。首先将蛇头的坐标设置为屏幕中央位置,用字符 'O' 表示蛇头并输出到屏幕上。然后将蛇身体的第二个部分的坐标设置在蛇头的左边一个单位,用字符 '*' 表示蛇的身体并输出到屏幕上。最后,将蛇的身体长度设置为 1。

        这段代码的功能是在屏幕上绘制一个初始状态的蛇,包括蛇头和一个蛇身体部分,用字符 'O' 和 '*' 表示。同时记录蛇的身体长度为 1。

static COORD snake[1024];
static int snake_body_length = 0;
void draw_int_snake(void)
{
    snake[0].X = WIDTH/2;
    snake[0].Y = HEIGHT/2;
    gotoxy(snake[0].X,snake[0].Y);
    putchar('O');
    snake[1].X = WIDTH/2-1;
    snake[1].Y = HEIGHT/2;
    gotoxy(snake[1].X,snake[1].Y);
    putchar('*');
    snake_body_length = 1;
}

3.2随机刷新食物

        本模块的功能是在游戏窗口中随机生成食物的位置,供蛇来吃。

  1. 在程序中引入随机数函数的库,比如在C语言中使用stdlib.h库的rand()函数。
  2. 利用rand()函数生成随机数,限定在游戏窗口内食物出现的范围内,得到食物的随机位置。
void generate_food_pos(int * outx ,int * outy )
{
    while(1)
    {
        int isuseful = 1;
        int x = rand() % WIDTH;
        int y = rand() % HEIGHT;
        if(x == 0 || y == 0)    continue;
        for(int i=0; i<=snake_body_length; i++)
        {
            if(x == snake[i].X && y == snake[i].Y)
            {
                isuseful = 0;
                break;
            }
        }
        if(isuseful == 0)   continue;
        *outx = x;
        *outy = y;
        break;
    }
}

3.3绘画食物

        本模块的作用是将食物的位置信息传递给绘制食物的函数,将食物绘制在游戏窗口中。

void draw_int_food(void)
{
    int x;
    int y;
    generate_food_pos(&x,&y);
    gotoxy(x,y);
    putchar('@');
}

相关文章:

  • MySQL基础知识点总结
  • python高效环境管理工具UV详解:性能与功能对比分析
  • GLPI 未授权SQL注入漏洞(CVE-2025-24799)
  • Apache httpclient okhttp(1)
  • 国内外网络安全政策动态(2025年3月)
  • 记录一次使用datax一次性导入多张表的经验
  • LeeCode 5. 最长回文子串
  • saltstack自动化运维工具安装部署以及常用模块
  • 学透Spring Boot — 007. 七种配置方式及优先级
  • 用户模块——整合 Spring 缓存(Cacheable)
  • 系统与网络安全------Windows系统安全(7)
  • Deep Learning-Based Human Pose Estimation: A Survey【读到2d单人hpe】
  • Java For 循环全解析:从基础到增强的实战指南
  • Spring Boot项目中策略模式的应用与实现
  • 教程:如何使用 JSON 合并脚本
  • AutoDev Next:IDE 即 AI 编程服务,构建多端粪围编程
  • 接口自动化学习三:参数化parameterize
  • 多品种金融数据高效导入丨DolphinDB 希施玛历史数据自动化导入模块介绍
  • 【目标检测】【深度学习】【Pytorch版本】YOLOV3模型算法详解
  • JVM深入原理(一+二):JVM概述和JVM功能
  • 网站ip访问做图表/培训机构网站制作
  • 自己做网站引用别人的电影/成都做整站优化
  • 网站平台建设需求的意见/网站制作哪家公司好
  • 公司简介图片模板/南昌seo网站排名
  • 医疗器械网站前置审批/seo技术
  • 网站设计论文总结/2024很有可能再次封城吗