m0_62475902 2022-06-24 00:29 采纳率: 66.7%
浏览 104
已结题

关于c语言贪吃蛇的问题

问题遇到的现象和发生背景
问题相关代码,请勿粘贴截图
运行结果及报错内容
我的解答思路和尝试过的方法
我想要达到的结果
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <time.h>
#include <windows.h>
void welcome();   
void HideCursor();              //光标隐藏
void gotoxy(int x, int y);      //光标定位

typedef struct snake
{
    int x;
    int y;
    struct snake* next;
}snake;

#define WIDTH 100           //控制台窗口宽度
#define HEIGHT 30           //控制台窗口高度
#define SNAKEN 4            //贪吃蛇初始长度
#define LIFE 3              //初始生命次数
#define SPEED 200           //游戏速度、循环休眠时间
#define U 1                 //使用宏代替需要数字代替的蛇的行动方向
#define D 2                 //宏名含义是各方向英文单词首字母
#define L 3                 //蛇的状态,U:上 ;D:下;L:左 R:右
#define R 4                 


 

void dtxxcsh()              //输出地图
{

    for (int i = 1; i < WIDTH-1; i++)        //输出上下面墙
    {
        gotoxy(i, 26);
        printf("-");
        gotoxy(i, 0);
        printf("-");
    }
    for (int i = 0; i < HEIGHT-3; i++)    //输出左右两面墙
    {
        gotoxy(0, i);
        printf("|");
        gotoxy(99, i);
        printf("|");
    }
    gotoxy(24, 28);
    printf("得分:  0           生命:  %d           时间:  0           ",LIFE);   
    //xy 30,28可用得分数值      14个空格
}


int foodx, foody;           //食物位置坐标

void sjcsswhs()             //随机产生一个食物
{
    srand(time(NULL));      

    foodx = rand() % (WIDTH - 4) + 2;       //使用宏运算随机数最大值需要加括号

    while (foodx % 2)                       //如果食物的x坐标不是偶数,再获取一个x坐标
    {
        foodx = rand() % (WIDTH - 4) + 2;   //宽度
    }

    foody = rand() % (HEIGHT - 7) + 3;      //高度

    gotoxy(foodx, foody);
    printf("★");
}

snake* head;                //蛇头指针

void cshs()                 //初始化蛇的位置
{   
    snake *tail;            //蛇尾指针
    int i;

    tail = (snake*)malloc(sizeof(snake));
    tail->next = NULL;
    tail->x = HEIGHT-6;
    tail->y = 8;

    //贪吃蛇初始长度5  SNAKEN
    for (i = 1; i <= SNAKEN; i++)               //在蛇尾处创建链表
    {
        head = (snake*)malloc(sizeof(snake));
        head->next = tail;

        head->x = 24 + i * 2;                   //head->x这个数必须为偶数,和食物坐标偶数对应
        head->y = 8;
        tail = head;                            //此时蛇尾指针指向蛇头
    }

    while (tail)
    {
        gotoxy(tail->x, tail->y);
        printf("■");
        tail = tail->next;
    }
}

int status = R;            //蛇前进状态

snake* p = NULL;        //工作指针
snake* nexthead;        //下一个蛇头
int score = 0;          //得分

void snakemove()        //蛇前进,上U,下D,左L,右R
{
    nexthead = (snake*)malloc(sizeof(snake));

    if (status == U)
    {
        nexthead->y = head->y - 1;  //确定新蛇头的下一个坐标  x,y
        nexthead->x = head->x;
    }
    if (status == D)                //下
    {
        nexthead->y = head->y + 1;
        nexthead->x = head->x;
    }
    if (status == L)                //左
    {
        nexthead->x = head->x - 2;
        nexthead->y = head->y;
    }
    if (status == R)                //右
    {
        nexthead->x = head->x + 2;
        nexthead->y = head->y;
    }
    nexthead->next = head;
    head = nexthead;
    p = head;

    if (p->x == foodx && p->y == foody) //判断蛇头的位置是否和食物的位置重合
    {
        while (p)                       //输出尾结点
        {
            gotoxy(p->x, p->y);
            if (p == head)
                printf("●");
            else
                printf("■");
            p = p->next;                //因为每次运动都是新创建一个头结点再删除一个尾结点,
        }                               //所以要增加一节身体,只需要这次循环不释放尾结点,并输出一次尾结点就好了
        
        //sjcsswhs();                   //碰到食物则再产生一个食物

        score++;
        gotoxy(32, 28);
        printf("%d", score);
    }
    else
    {
        while (p->next->next)           //不输出尾结点
        {
            gotoxy(p->x, p->y);
            if (p == head)
                printf("●");
            else
                printf("■");
            p = p->next;
        }

        gotoxy(p->next->x, p->next->y);
        printf("  ");
        free(p->next);
        p->next = NULL;
    }

    p = head;
    while (p)                       //如果食物的坐标刷新到了蛇身上则再产生一个食物 *
    {
        if (p->x == foodx && p->y == foody)
            sjcsswhs();
        p = p->next;
    }
}

void czfxhs()                   //操作方向函数,接收从键盘输入的按键,控制贪吃蛇行进方向
{
    char ch = _getch();
    switch (ch)
    {
        case 'w': 
            if(status != D)
                status = U; break;
        case 's': 
            if (status != U)
                status = D; break;
        case 'a': 
            if (status != R)
                status = L; break;
        case 'd': 
            if (status != L)
                status = R; break;
        case ' ': 
            _getch(); break;        //空格暂停
    }
}

int yxjstjjsmz_1()                  //生命掉落条件1咬自己
{
    snake* self = head->next;       //self为蛇身上的一个结点
    while (self)
    {
        if (self->x == head->x && self->y == head->y) //head和self的成员作比较,蛇头一直存在,这里遍历的是蛇身
        {
            return 1;
        }
        self = self->next;
    }
    return 0;【 
}

int yxjstjjsmz_2()                  //生命掉落条件2碰墙
{
    if (head->x <= 1 || head->x >= 98 || head->y <= 0 || head->y >= 26)
        return 1;
    
    return 0;
}

int i = LIFE - 1;                   //变量存储生命次数

void qcsytmslbhs()                  //清除并释放上一条蛇留下来的痕迹,更新生命信息
{
    p = head;
    int _x_ = p->x;                 //用于保存死掉的蛇的蛇头处的位置,用于输出被蛇头顶掉的墙壁
    int _y_ = p->y;
    while (head)
    {
        gotoxy(head->x, head->y);
        printf("  ");
        head = head->next;
        free(p);
        p = head;
    }
    gotoxy(52, 28);                 //更新生命信息
    printf("%d", i);

    if (_y_ == 0 || _y_ == HEIGHT - 4)      //用于在蛇死掉后,蛇头的位置输出被清除蛇头顶替掉的墙壁
    {
        gotoxy(_x_, _y_);
        printf("--");
    }
    else if (_x_ == WIDTH - 2)
    {
        gotoxy(_x_+1, _y_);
        printf("|");
    }
    else if(_x_ == 0)
    {
        gotoxy(_x_, _y_);
        printf("|");
    }
}

void sbjsjmhs()                     //失败结束界面
{
    p = head;                       //释放内存
    while (head)
    {
        head = head->next;
        free(p);
        p = head;
    }

    system("cls");
    gotoxy(45, 12);
    printf("游戏结束!");
    gotoxy(44, 14);
    printf("最终得分:%d", score);
    gotoxy(0,28);
}

int updatetime()                        //获取一次电脑现在的时间
{
    int now;
    SYSTEMTIME system_time;             
    GetLocalTime(&system_time);
    now = system_time.wMinute * 60 + system_time.wSecond;   
    return now;
}

int time_1 = updatetime();                  //保存游戏刚开始的时间

void gametime()                             //写在每次循环之内
{
    int time_2 = updatetime() - time_1;     //更新游戏开始后时间,用现在的时间减去刚开始的时间
    gotoxy(72, 28);
    printf("%d s", time_2);
}

int main()//主函数
{
    system("mode con cols=100 lines=30");   //设置控制台大小
    system("title 贪吃蛇游戏");             //设置标题
    HideCursor();                           //隐藏光标

    sjcsswhs();                             //初始化随机产生一个食物
    dtxxcsh();                              //初始化地图、信息

    for (; i >= 0; i--)                         //生命
    {
        cshs();                                 //初始化蛇的位置
        status = R;                             //初始化运动方向

        while (1)
        {
            snakemove();                        //蛇行动动画,方向被控制变量控制

            if (_kbhit())
            {
                czfxhs();                       //接收键盘按键,控制控制变量
            }
            
            if (yxjstjjsmz_1() || yxjstjjsmz_2())//两个掉落生命的条件
                break;

            gametime();                         //更新游戏时间

            Sleep(SPEED);
        }
        qcsytmslbhs();                          //清除上一条蛇留下来的痕迹,更新生命信息
    }

    sbjsjmhs();                                 //失败结束界面

    return 0;
}

void HideCursor()
{
    CONSOLE_CURSOR_INFO cursor_info = { 1, 0 };
    SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info);
}

void gotoxy(int x, int y)
{
    COORD pos = { x,y };
    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);
}

  • 写回答

3条回答 默认 最新

  • fuill 2022-06-24 11:46
    关注

    img

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

问题事件

  • 系统已结题 7月2日
  • 已采纳回答 6月24日
  • 创建了问题 6月24日

悬赏问题

  • ¥20 关于#stm32#的问题:需要指导自动酸碱滴定仪的原理图程序代码及仿真
  • ¥20 设计一款异域新娘的视频相亲软件需要哪些技术支持
  • ¥15 stata安慰剂检验作图但是真实值不出现在图上
  • ¥15 c程序不知道为什么得不到结果
  • ¥40 复杂的限制性的商函数处理
  • ¥15 程序不包含适用于入口点的静态Main方法
  • ¥15 素材场景中光线烘焙后灯光失效
  • ¥15 请教一下各位,为什么我这个没有实现模拟点击
  • ¥15 执行 virtuoso 命令后,界面没有,cadence 启动不起来
  • ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因