贪吃蛇(C语言)1.0版本(可以直接CV)

目录

效果

贪吃蛇(可以直接CV)

解析

变量

主函数

文件操作(用于记录最高历史记录)

墙初始化

 蛇初始化

食物初始化

GUI界面显示蛇、食物等

移动光标 

 游戏逻辑

蛇的移动 

键盘控制 (wasd与空格键暂停)

 结束游戏

吃到自己

吃到食物

隐藏光标 

 颜色


效果

贪吃蛇(可以直接CV)

实现贪吃蛇游戏的C语言代码可以分为几个关键部分:初始化游戏界面、控制贪吃蛇移动、生成食物、处理用户输入、游戏逻辑判断等。下面是一个简易贪吃蛇的代码代码,展示了如何实现基本功能的贪吃蛇游戏

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <windows.h>
#include <conio.h>

#define wide 45
#define hige 20
#define open_score 100
#define space 32 

typedef struct body
{
    int x;
    int y;
}BODY;

typedef struct snake
{
    BODY list[wide*hige];
    int size;
    BODY food;
    BODY move_xy;
    BODY tail;
    int score;
    int higest_score;
    char t;
    unsigned char speed;
}SNAKE;


FILE *open_file(char *filename, char *mode);
void gui_init(int x, int y);
void snake_init(SNAKE *snake);
void food_init(SNAKE *snake);
void gui_show(SNAKE *snake);
void movecursor(int x, int y);
void start_game(SNAKE *snake);
void move_snake(SNAKE *snake);
void control_snake(SNAKE *snake);
void end_game(SNAKE *snake);
void snake_eat_body(SNAKE *snake);
void snake_eat_food(SNAKE *snake);
void hide_console_cursor();
void color(int c);


int main()
{
    SNAKE *snake = (SNAKE *)malloc(sizeof(SNAKE));
    if (snake == NULL) {
       
        fprintf(stderr, "内存分配失败。\n");
        return 1;
    }
    hide_console_cursor();
    gui_init( 0, 0);
    gui_init( wide + 10, 0);
    snake_init(snake);
    food_init(snake);
    gui_show(snake);
    start_game(snake);

    free(snake);
    return 0;  
}

FILE *open_file(char *filename, char *mode)
{
    FILE *fp = fopen(filename, mode);  
    if (!fp)
    {
        perror("打开失败");  
        return NULL;
    }
    return fp;  
}

void gui_init(int x, int y)
{
	system("title 贪吃蛇");
	color(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY);
    for(int i = 0; i < hige + 1; i ++) 
    {
    	movecursor( y + i, x);
        for(int j = 0; j < wide + 1; j ++) 
        {
            if(j == 0 || j == wide || i == 0 || i == hige)
                printf("■");
            else
                printf(" ");
        }
            printf("\n");
    }
}

void snake_init(SNAKE *snake)
{
    snake->list[0].x = wide / 2;
    snake->list[0].y = hige / 2;

    snake->list[1].x = wide / 2 - 1;
    snake->list[1].y = hige / 2;

    snake->move_xy.x = 1;
    snake->move_xy.y = 0;

    snake->size = 2;
    snake->score = 0;
    snake->t = 1;
    snake->speed = 200;
    
    FILE *fp = open_file("./历史最高记录分数.txt","r");
    fscanf(fp,"历史最高记录分数为%d",&(snake->higest_score));
    fclose(fp);
}

void food_init(SNAKE *snake)
{
food_init:
    srand(time(NULL));
    snake->food.x = rand() % (wide - 2) + 1;
    snake->food.y = rand() % (hige - 2) + 1;
    if(snake->food.x - (snake->food.y * 2) && snake->t > 1)
    {
    	snake->food.x = (rand() % (wide - 2) + 1) + wide + 10;
	}

    for(int i = 0; i < snake->size; i ++)
    {
        if(snake->food.x == snake->list[i].x && snake->food.y == snake->list[i].y) 
            goto food_init;
    }
}

void gui_show(SNAKE *snake)
{
    for(int i = 0; i < snake->size; i ++)
    {
        movecursor(snake->list[i].y,snake->list[i].x);
        if(i == 0)
        {
        	color(FOREGROUND_RED | FOREGROUND_INTENSITY); 
            printf("@");
        }
        else
        {
            color(FOREGROUND_GREEN | FOREGROUND_INTENSITY);
			printf("●");
        }
    }
    
    movecursor(snake->food.y,snake->food.x);
    printf("$");
    movecursor(snake->tail.y,snake->tail.x);
    printf(" ");
    movecursor(hige + 1,0);
	printf("当前得分为%d\t历史最高记录分数为%d\n",snake->score,snake->higest_score);
	if(snake->t == 1)
	{
		color(FOREGROUND_RED | FOREGROUND_INTENSITY); 
		movecursor(hige/2 - 1,wide + 1);
		printf("当前得分");
		movecursor(hige/2,wide + 1);
		printf("为%d时",open_score);
		movecursor(hige/2 + 1,wide + 1);
		printf("通道打开");	
	}
	else if(snake->t > 1)
	{
		color(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY);并加亮
		movecursor(hige/2 - 1,wide + 1);
		printf("■■■■■■■■■");
		movecursor(hige/2,wide);
		printf("           ",open_score);
		movecursor(hige/2 + 1,wide + 1);
		printf("■■■■■■■■■");
	}
}

void movecursor(int x, int y) 
{
    COORD coord;
    coord.X = y; 
    coord.Y = x;
    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
}

void start_game(SNAKE *snake)
{
    while (snake->t == 1 && (snake->list[0].x < wide && snake->list[0].x > 0 && snake->list[0].y < hige && snake->list[0].y > 0))
    {
        control_snake(snake);
        move_snake(snake);
        gui_show(snake);
        snake_eat_body(snake);
        snake_eat_food(snake);
        Sleep(snake->speed);
    }
    while (snake->t > 1 && (snake->list[0].x > 0 && snake->list[0].y < hige && snake->list[0].y > 0)
	|| (snake->t > 1 && (snake->list[0].x < (2 * wide + 10) && snake->list[0].y < hige && snake->list[0].y > 0)))
    {
    	if((snake->list[0].x == wide && snake->list[0].y != hige / 2) || (snake->list[0].x == wide + 10 && snake->list[0].y != hige / 2))
    		break;
        control_snake(snake);
        move_snake(snake);
        gui_show(snake);
        snake_eat_body(snake);
        snake_eat_food(snake);
        Sleep(snake->speed);
    }
    end_game(snake);
}

void move_snake(SNAKE *snake)
{
    snake->tail.x = snake->list[snake->size - 1].x;
    snake->tail.y = snake->list[snake->size - 1].y;

    for(int i = snake->size - 1; i > 0; i--)
    {
        snake->list[i].x = snake->list[i - 1].x;
        snake->list[i].y = snake->list[i - 1].y;
    } 

    snake->list[0].x += snake->move_xy.x;
    snake->list[0].y += snake->move_xy.y;
}

void control_snake(SNAKE *snake)
{
    char key = 0;
    while (_kbhit())
    {
       key = _getch();
    }
    switch (key)
    {
    case 'a':
    	if(snake->move_xy.x == 1)
    		break;
        snake->move_xy.x = -1;
        snake->move_xy.y = 0;
        break;
    case 'w':
    	if(snake->move_xy.y == 1)
    		break;
        snake->move_xy.x = 0;
        snake->move_xy.y = -1;
        break;
    case 's':
    	if(snake->move_xy.y == -1)
    		break;
        snake->move_xy.x = 0;
        snake->move_xy.y = 1;
        break;
    case 'd':
    	if(snake->move_xy.x == -1) 
    		break;
        snake->move_xy.x = 1;
        snake->move_xy.y = 0;
        break; 
    case space: 
		system("pause>nul"); 
		break;
    }
}

void end_game(SNAKE *snake)
{
	if(snake->score > snake->higest_score)
	{
		snake->higest_score = snake->score;
		system("cls");
		color(FOREGROUND_BLUE | FOREGROUND_INTENSITY); 
		movecursor( hige / 2,0);
		printf("恭喜你打破最高记录\n游戏结束得分为%d\t历史最高记录分数为%d\n是否再来一局?(y/n):",snake->score,snake->higest_score);
		
		FILE *fp = open_file("./历史最高记录分数.txt","w");
	    fprintf(fp,"历史最高记录分数为%d\n",snake->higest_score);
	    fclose(fp);
	}
	else
	{
		system("cls");
		color(FOREGROUND_BLUE | FOREGROUND_INTENSITY); 
		movecursor( hige / 2,0);
		printf("请继续加油!\n游戏结束得分为%d\t历史最高记录分数为%d\n是否再来一局?(y/n):",snake->score,snake->higest_score);
	}
	int i = 0;
	while (1) //询问玩家是否再来一局
	{
		char ch;
		scanf("%c", &ch);
		if (ch == 'y' || ch == 'Y')
		{
			i = 0;
			system("cls");
			main();
		}
		else if (ch == 'n' || ch == 'N')
		{
			color(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY); 
			movecursor( 0, 0);
			system("cls");
			Sleep(100);
			exit(0);
		}
		else
		{
			color(FOREGROUND_RED | FOREGROUND_INTENSITY); 
			movecursor( hige / 2 + 3 + i,0);
			i ++;
			printf("选择错误,请再次选择(y/n):");
		}
	}
}

void snake_eat_body(SNAKE *snake)
{
	for(int i = 1; i < snake->size; i ++)
	{
		if(snake->list[0].x == snake->list[i].x && snake->list[0].y == snake->list[i].y)
		{
			end_game(snake);
		}
	}
}

void snake_eat_food(SNAKE *snake)
{
	if(snake->list[0].x == snake->food.x && snake->list[0].y == snake->food.y)
	{
		food_init(snake);
		snake->size ++;
		snake->t = ((snake->score += (10 * snake->t)) / 100) + 1;
		snake->speed = (snake->speed >= 50) ? (snake->speed - 5) : 50;
	}
}

void hide_console_cursor()
{
    HANDLE consoleHandle = GetStdHandle(STD_OUTPUT_HANDLE);
    CONSOLE_CURSOR_INFO cursorInfo;
    GetConsoleCursorInfo(consoleHandle, &cursorInfo);
    cursorInfo.bVisible = FALSE; 
    SetConsoleCursorInfo(consoleHandle, &cursorInfo);
}

void color(int c)
{
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), c);
}

解析

变量

#define wide 45//墙宽
#define hige 20//墙高
#define open_score 100//通道打开的分数阈值
#define space 32 //暂停

typedef struct body
{
    int x;//坐标
    int y;
}BODY;

typedef struct snake
{
    BODY list[wide*hige];//蛇
    int size;//蛇长
    BODY food;//食物的坐标
    BODY move_xy;//移动方向
    BODY tail;//蛇的尾部
    int score;//当前分数
    int higest_score;//最高分数
    char t;//改变计分方式、判断条件等等
    unsigned char speed;//刷屏速度
}SNAKE;

主函数

// 主函数,程序入口
int main()
{
    SNAKE *snake = (SNAKE *)malloc(sizeof(SNAKE));//申请内存空间
    if (snake == NULL) {
        // 处理内存分配失败的情况
        fprintf(stderr, "内存分配失败。\n");
        return 1;
    }
    hide_console_cursor();//隐藏光标
    gui_init( 0, 0);//gui界面显示(墙)
    gui_init( wide + 10, 0);
    snake_init(snake);//参数初始化
    food_init(snake);//食物随机生成
    gui_show(snake);//gui界面显示(蛇、食物等)
    start_game(snake);//游戏开始

    free(snake);//释放申请的内存
    return 0;  // 程序正常退出
}

文件操作(用于记录最高历史记录)

FILE *open_file(char *filename, char *mode)
{
    FILE *fp = fopen(filename, mode);  // 使用指定模式打开文件
    if (!fp)
    {
        perror("打开失败");  // 如果打开失败,打印错误信息
        return NULL;
    }
    return fp;  // 返回文件指针
}

墙初始化

void gui_init(int x, int y)
{
    // 设置控制台窗口标题为"贪吃蛇"
    system("title 贪吃蛇");
    
    // 设置文本颜色为黄色并加亮
    color(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY);
    
    // 绘制游戏界面
    for(int i = 0; i < hige + 1; i ++) // 循环绘制每一行
    {
        movecursor(y + i, x); // 移动光标到指定位置(x, y + i)
        
        for(int j = 0; j < wide + 1; j ++) // 循环绘制每一列
        {
            if(j == 0 || j == wide || i == 0 || i == hige)
                printf("■"); // 如果是边界位置,打印实心方块
            else
                printf(" "); // 否则打印空格,用于填充内部空白区域
        }
        
        printf("\n"); // 每行绘制完成后换行
    }
}

 蛇初始化

void snake_init(SNAKE *snake)
{
    // 设置蛇的初始位置
    snake->list[0].x = wide / 2;   // 蛇头的初始 x 坐标为界面宽度的一半
    snake->list[0].y = hige / 2;   // 蛇头的初始 y 坐标为界面高度的一半

    snake->list[1].x = wide / 2 - 1;   // 蛇尾的初始 x 坐标为蛇头左侧
    snake->list[1].y = hige / 2;       // 蛇尾的初始 y 坐标与蛇头一致

    // 设置蛇的初始移动方向
    snake->move_xy.x = 1;   // 蛇初始向右移动
    snake->move_xy.y = 0;

    // 初始化蛇的长度、分数、时间、速度
    snake->size = 2;    // 蛇初始长度为2(包括头部和尾部)
    snake->score = 0;   // 分数初始为0
    snake->t = 1;       // 时间初始为1
    snake->speed = 200; // 初始速度为200

    // 从文件中读取历史最高分数
    FILE *fp = open_file("./历史最高记录分数.txt", "r"); // 打开存放历史最高分数的文件
    fscanf(fp, "历史最高记录分数为%d", &(snake->higest_score)); // 读取历史最高分数
    fclose(fp); // 关闭文件
}

食物初始化

void food_init(SNAKE *snake)
{
food_init:
    // 使用当前时间作为随机种子
    srand(time(NULL));

    // 随机生成食物的位置,确保不超出屏幕边界
    snake->food.x = rand() % (wide - 2) + 1;
    snake->food.y = rand() % (hige - 2) + 1;

    // 检查通道是否打开,让食物可以在另外一个区域位置生成
    //确保两个区域都有可能生成食物
    if (snake->food.x - (snake->food.y * 2) && snake->t > 1)
    {
        snake->food.x = (rand() % (wide - 2) + 1) + wide + 10;
    }

    // 确保食物不与贪吃蛇的身体重叠,如果重叠则重新生成食物位置
    for (int i = 0; i < snake->size; i++)
    {
        if (snake->food.x == snake->list[i].x && snake->food.y == snake->list[i].y)
            goto food_init;
    }
}

GUI界面显示蛇、食物等

void gui_show(SNAKE *snake)
{
    // 遍历蛇的每个身体部分
    for(int i = 0; i < snake->size; i ++)
    {
        // 将光标移动到蛇身体的当前位置
        movecursor(snake->list[i].y, snake->list[i].x);
        
        // 如果是蛇头部分(第一个节点)
        if(i == 0)
        {
            color(FOREGROUND_RED | FOREGROUND_INTENSITY); // 设置文本为红色并加亮
            printf("@"); // 打印蛇头(使用@表示)
        }
        else
        {
            color(FOREGROUND_GREEN | FOREGROUND_INTENSITY); // 设置文本为绿色并加亮
            printf("●"); // 打印蛇身体的其他部分(使用●表示)
        }
    }
    
    // 将光标移动到食物的位置
    movecursor(snake->food.y, snake->food.x);
    printf("$"); // 打印食物(使用$表示)
    
    // 将光标移动到蛇尾的位置,并打印空格来清除之前的蛇尾(移动效果)
    movecursor(snake->tail.y, snake->tail.x);
    printf(" ");
    
    // 将光标移动到界面底部,并显示当前得分和历史最高分数
    movecursor(hige + 1, 0);
    printf("当前得分为%d\t历史最高记录分数为%d\n", snake->score, snake->higest_score);
    
    // 如果分数没有到达100,显示相应的信息
    if(snake->t == 1)
    {
        color(FOREGROUND_RED | FOREGROUND_INTENSITY); // 设置文本为红色并加亮
        movecursor(hige / 2 - 1, wide + 1); // 将光标移动到特定位置
        printf("当前得分");
        movecursor(hige / 2, wide + 1); // 继续在下一行打印
        printf("为%d时", open_score); // 打印特定的得分值
        movecursor(hige / 2 + 1, wide + 1); // 继续在下一行打印
        printf("通道打开"); // 打印特定的状态信息
    }
    // 如果分数大于100(t大于1),显示通道
    else if(snake->t > 1)
    {
        color(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY); // 设置文本为黄色并加亮
        movecursor(hige / 2 - 1, wide + 1); // 将光标移动到特定位置
        printf("■■■■■■■■■");
        movecursor(hige / 2, wide); // 继续在下一行打印
        printf("           "); // 打印空白以覆盖之前的内容
        movecursor(hige / 2 + 1, wide + 1); // 继续在下一行打印
        printf("■■■■■■■■■"); // 打印特定的形状(方块)
    }
}

移动光标 

void movecursor(int x, int y) 
{
    COORD coord;  // 声明一个 COORD 结构体变量 coord。COORD 是 Windows API 中的结构体,用于保存坐标对。
    coord.X = y;  // 将 coord 结构体的 X 坐标设置为 y 的值。在这里,'y' 表示列号。
    coord.Y = x;  // 将 coord 结构体的 Y 坐标设置为 x 的值。这里的 'x' 表示行号。

    // SetConsoleCursorPosition 是 Windows API 中的函数,用于将光标移动到屏幕上的指定位置。
    // GetStdHandle(STD_OUTPUT_HANDLE) 获取标准输出的句柄,代表控制台屏幕缓冲区。
    // 它作为 SetConsoleCursorPosition 的第一个参数,用于指定光标应该移动到的位置。
    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
    // 这个函数调用实际上将光标移动到由坐标 (x, y) 指定的位置。
}

 游戏逻辑

void start_game(SNAKE *snake)
{
    // 第一个 while 循环:100分之前
    while (snake->t == 1 && (snake->list[0].x < wide && snake->list[0].x > 0 && snake->list[0].y < hige && snake->list[0].y > 0))
    {
        control_snake(snake);     // 控制蛇的移动方向
        move_snake(snake);        // 移动蛇的位置
        gui_show(snake);          // 更新图形界面显示
        snake_eat_body(snake);    // 检查蛇是否吃到了自己的身体
        snake_eat_food(snake);    // 检查蛇是否吃到了食物
        Sleep(snake->speed);      // 控制游戏速度
    }

    // 第二个 while 循环:100分之后
    while (snake->t > 1 && (snake->list[0].x > 0 && snake->list[0].y < hige && snake->list[0].y > 0)
	|| (snake->t > 1 && (snake->list[0].x < (2 * wide + 10) && snake->list[0].y < hige && snake->list[0].y > 0)))
    {
        // 如果蛇头碰到了墙,跳出循环,游戏结束
        if((snake->list[0].x == wide && snake->list[0].y != hige / 2) || (snake->list[0].x == wide + 10 && snake->list[0].y != hige / 2))
            break;

        control_snake(snake);     // 控制蛇的移动方向
        move_snake(snake);        // 移动蛇的位置
        gui_show(snake);          // 更新图形界面显示
        snake_eat_body(snake);    // 检查蛇是否吃到了自己的身体
        snake_eat_food(snake);    // 检查蛇是否吃到了食物
        Sleep(snake->speed);      // 控制游戏速度
    }

    end_game(snake);  // 游戏结束,调用结束游戏的函数
}

蛇的移动 

void move_snake(SNAKE *snake)
{
    // 将蛇尾的位置保存下来,用于后续的移动操作
    snake->tail.x = snake->list[snake->size - 1].x;
    snake->tail.y = snake->list[snake->size - 1].y;

    // 从蛇尾开始,每个身体块的位置更新为前一个身体块的位置
    for (int i = snake->size - 1; i > 0; i--)
    {
        snake->list[i].x = snake->list[i - 1].x;
        snake->list[i].y = snake->list[i - 1].y;
    }

    // 根据蛇头的移动方向更新蛇头的位置
    snake->list[0].x += snake->move_xy.x;
    snake->list[0].y += snake->move_xy.y;
}

键盘控制 (wasd与空格键暂停)

void control_snake(SNAKE *snake)
{
    char key = 0; // 定义变量 key,用于存储按下的键值

    while (_kbhit()) // 当有键盘输入时进入循环
    {
        key = _getch(); // 获取键盘输入的字符
    }

    switch (key) // 根据输入的键值进行相应的操作
    {
    case 'a':
        if (snake->move_xy.x == 1)
            break; // 如果蛇当前正在向右移动,则忽略向左移动的命令
        snake->move_xy.x = -1; // 设置蛇向左移动
        snake->move_xy.y = 0;
        break;
    case 'w':
        if (snake->move_xy.y == 1)
            break; // 如果蛇当前正在向下移动,则忽略向上移动的命令
        snake->move_xy.x = 0; // 设置蛇向上移动
        snake->move_xy.y = -1;
        break;
    case 's':
        if (snake->move_xy.y == -1)
            break; // 如果蛇当前正在向上移动,则忽略向下移动的命令
        snake->move_xy.x = 0; // 设置蛇向下移动
        snake->move_xy.y = 1;
        break;
    case 'd':
        if (snake->move_xy.x == -1)
            break; // 如果蛇当前正在向左移动,则忽略向右移动的命令
        snake->move_xy.x = 1; // 设置蛇向右移动
        snake->move_xy.y = 0;
        break;
    case space: // 空格键暂停游戏的情况
        system("pause>nul"); // 调用系统命令暂停程序运行,按任意键继续
        break;
    }
}

 结束游戏

void end_game(SNAKE *snake)
{
    // 如果当前得分高于历史最高分,则更新历史最高分数
    if (snake->score > snake->higest_score)
    {
        snake->higest_score = snake->score;
        system("cls"); // 清空控制台屏幕
        color(FOREGROUND_BLUE | FOREGROUND_INTENSITY); // 设置文本为蓝色并加亮
        movecursor(hige / 2, 0); // 移动光标到指定位置
        printf("恭喜你打破最高记录\n游戏结束得分为%d\t历史最高记录分数为%d\n是否再来一局?(y/n):", snake->score, snake->higest_score);

        // 打开文件以写入历史最高分数
        FILE *fp = open_file("./历史最高记录分数.txt", "w");
        fprintf(fp, "历史最高记录分数为%d\n", snake->higest_score);
        fclose(fp);
    }
    else
    {
        system("cls"); // 清空控制台屏幕
        color(FOREGROUND_BLUE | FOREGROUND_INTENSITY); // 设置文本为蓝色并加亮
        movecursor(hige / 2, 0); // 移动光标到指定位置
        printf("请继续加油!\n游戏结束得分为%d\t历史最高记录分数为%d\n是否再来一局?(y/n):", snake->score, snake->higest_score);
    }

    int i = 0;
    while (1) // 询问玩家是否再来一局
    {
        char ch;
        scanf("%c", &ch); // 读取用户输入的字符

        if (ch == 'y' || ch == 'Y')
        {
            i = 0;
            system("cls"); // 清空控制台屏幕
            main(); // 调用主函数以重新开始游戏
        }
        else if (ch == 'n' || ch == 'N')
        {
            color(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY); // 设置文本为白色并加亮
            movecursor(0, 0); // 移动光标到指定位置
            system("cls"); // 清空控制台屏幕
            Sleep(100); // 等待100毫秒
            exit(0); // 退出程序
        }
        else
        {
            color(FOREGROUND_RED | FOREGROUND_INTENSITY); // 设置文本为红色并加亮
            movecursor(hige / 2 + 3 + i, 0); // 移动光标到指定位置
            i++;
            printf("选择错误,请再次选择(y/n):");
        }
    }
}

吃到自己

void snake_eat_body(SNAKE *snake)
{
    for(int i = 1; i < snake->size; i ++) // 从蛇身体的第二节开始遍历到最后一节
    {
        if(snake->list[0].x == snake->list[i].x && snake->list[0].y == snake->list[i].y)
        {
            end_game(snake); // 如果蛇头与任意一节身体重合,则调用游戏结束函数
        }
    }
}

吃到食物

void snake_eat_food(SNAKE *snake)
{
    if(snake->list[0].x == snake->food.x && snake->list[0].y == snake->food.y)
    {
        food_init(snake); // 初始化新的食物位置
        snake->size ++; // 增加蛇的长度
        snake->t = ((snake->score += (10 * snake->t)) / 100) + 1; // 更新分数与成长速率
        snake->speed = (snake->speed >= 50) ? (snake->speed - 5) : 50; // 调整蛇的移动速度
    }
}

隐藏光标 

void hide_console_cursor()
{
    HANDLE consoleHandle = GetStdHandle(STD_OUTPUT_HANDLE);
    CONSOLE_CURSOR_INFO cursorInfo;
    GetConsoleCursorInfo(consoleHandle, &cursorInfo);
    cursorInfo.bVisible = FALSE; 
    SetConsoleCursorInfo(consoleHandle, &cursorInfo);
}

 颜色

void color(int c)
{
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), c); // 设置控制台输出文本的颜色属性为 c
}

  • 13
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是一个简单的贪吃蛇C语言代码,供参考: ```c #include <stdio.h> #include <stdlib.h> #include <conio.h> #include <windows.h> #define WIDTH 20 #define HEIGHT 20 #define MAX_LENGTH (WIDTH*HEIGHT) int snake[MAX_LENGTH][2]; int food[2]; int score; int length; int direction; int running; void init() { // 初始化贪吃蛇的位置 snake[0][0] = WIDTH / 2; snake[0][1] = HEIGHT / 2; snake[1][0] = WIDTH / 2 - 1; snake[1][1] = HEIGHT / 2; snake[2][0] = WIDTH / 2 - 2; snake[2][1] = HEIGHT / 2; length = 3; // 初始化食物的位置 food[0] = rand() % WIDTH; food[1] = rand() % HEIGHT; // 初始化分数 score = 0; // 初始化方向 direction = 'd'; // 初始化运行标志 running = 1; } void draw() { system("cls"); // 画出地图 for (int i = 0; i <= HEIGHT; i++) { for (int j = 0; j <= WIDTH; j++) { if (i == 0 || i == HEIGHT || j == 0 || j == WIDTH) { printf("#"); } else if (i == snake[0][1] && j == snake[0][0]) { printf("@"); } else if (i == food[1] && j == food[0]) { printf("*"); } else { int flag = 0; for (int k = 1; k < length; k++) { if (i == snake[k][1] && j == snake[k][0]) { printf("#"); flag = 1; break; } } if (!flag) { printf(" "); } } } printf("\n"); } // 显示分数 printf("Score: %d\n", score); } void update() { // 记录蛇尾位置 int tail[2]; tail[0] = snake[length - 1][0]; tail[1] = snake[length - 1][1]; // 移动蛇身 for (int i = length - 1; i > 0; i--) { snake[i][0] = snake[i - 1][0]; snake[i][1] = snake[i - 1][1]; } // 根据方向移动蛇头 switch (direction) { case 'w': snake[0][1]--; break; case 'a': snake[0][0]--; break; case 's': snake[0][1]++; break; case 'd': snake[0][0]++; break; } // 判断是否吃到食物 if (snake[0][0] == food[0] && snake[0][1] == food[1]) { // 食物位置随机生成 food[0] = rand() % WIDTH; food[1] = rand() % HEIGHT; // 分数加一 score++; // 蛇身长度加一 length++; } // 判断是否碰到墙壁或自己的身体 if (snake[0][0] == 0 || snake[0][0] == WIDTH || snake[0][1] == 0 || snake[0][1] == HEIGHT) { running = 0; } for (int i = 1; i < length; i++) { if (snake[0][0] == snake[i][0] && snake[0][1] == snake[i][1]) { running = 0; break; } } } void input() { // 获取键盘输入 if (_kbhit()) { char c = _getch(); if (c == 'w' || c == 'a' || c == 's' || c == 'd') { // 只有输入合法的方向键才会改变方向 if ((c == 'w' && direction != 's') || (c == 'a' && direction != 'd') || (c == 's' && direction != 'w') || (c == 'd' && direction != 'a')) { direction = c; } } } } int main() { init(); while (running) { draw(); update(); input(); Sleep(100); } printf("Game over\n"); printf("Your score: %d\n", score); return 0; } ``` 这个代码使用了Windows.h库中的一个函数`Sleep()`,该函数可以让程序暂停一段时间,单位是毫秒。在这个代码中,每100毫秒刷新一次屏幕,相当于一秒钟刷新10次。如果需要在其他平台上运行此代码,需要修改画图函数和暂停函数。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值