关于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);
}

可以看下 c参考手册中的 c语言-exp()